diff --git a/src/main/java/nl/requios/effortlessbuilding/ClientConfig.java b/src/main/java/nl/requios/effortlessbuilding/ClientConfig.java new file mode 100644 index 0000000..e2021d2 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/ClientConfig.java @@ -0,0 +1,36 @@ +package nl.requios.effortlessbuilding; + +import net.minecraftforge.common.ForgeConfigSpec; + +public class ClientConfig { + + private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); + public static final Visuals visuals = new Visuals(builder); + public static final ForgeConfigSpec spec = builder.build(); + + public static class Visuals { + public final ForgeConfigSpec.ConfigValue showBlockPreviews; + public final ForgeConfigSpec.ConfigValue alwaysShowBlockPreview; + public final ForgeConfigSpec.ConfigValue maxBlockPreviews; + + public Visuals(ForgeConfigSpec.Builder builder) { + builder.push("Visuals"); + + showBlockPreviews = builder + .comment("Show previews of the blocks while placing them") + .define("useShaders", true); + + alwaysShowBlockPreview = builder + .comment("Show a block preview if you have a block in hand even in the 'Disabled' build mode") + .define("alwaysShowBlockPreview", false); + + maxBlockPreviews = builder + .comment("Don't show block previews when placing more than this many blocks. " + + "The outline will always be rendered.") + .define("shaderTreshold", 500); + + + builder.pop(); + } + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java b/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java index 120f6c3..e189f9b 100644 --- a/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java +++ b/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java @@ -133,7 +133,7 @@ public class ClientEvents { BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); if (mc.screen != null || - buildMode == BuildModes.BuildModeEnum.NORMAL || + buildMode == BuildModes.BuildModeEnum.DISABLED || RadialMenu.instance.isVisible()) { return; } @@ -175,7 +175,7 @@ public class ClientEvents { PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage()); } } - } else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) { + } else if (buildMode == BuildModes.BuildModeEnum.SINGLE) { placeCooldown--; if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0; } @@ -210,7 +210,7 @@ public class ClientEvents { BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage()); PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage()); } - } else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) { + } else if (buildMode == BuildModes.BuildModeEnum.SINGLE) { breakCooldown--; if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0; } diff --git a/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java b/src/main/java/nl/requios/effortlessbuilding/CommonConfig.java similarity index 74% rename from src/main/java/nl/requios/effortlessbuilding/BuildConfig.java rename to src/main/java/nl/requios/effortlessbuilding/CommonConfig.java index 2c84c58..9db7c50 100644 --- a/src/main/java/nl/requios/effortlessbuilding/BuildConfig.java +++ b/src/main/java/nl/requios/effortlessbuilding/CommonConfig.java @@ -1,8 +1,9 @@ package nl.requios.effortlessbuilding; import net.minecraftforge.common.ForgeConfigSpec; +import nl.requios.effortlessbuilding.create.foundation.render.SuperByteBufferCache; -public class BuildConfig { +public class CommonConfig { private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); public static final Reach reach = new Reach(builder); @@ -80,33 +81,21 @@ public class BuildConfig { } public static class Visuals { - public final ForgeConfigSpec.ConfigValue alwaysShowBlockPreview; - public final ForgeConfigSpec.ConfigValue dissolveTimeMultiplier; - public final ForgeConfigSpec.ConfigValue shaderThreshold; - public final ForgeConfigSpec.ConfigValue useShaders; + public final ForgeConfigSpec.ConfigValue appearAnimationLength; + public final ForgeConfigSpec.ConfigValue breakAnimationLength; - public Visuals(ForgeConfigSpec.Builder builder) { + public Visuals(ForgeConfigSpec.Builder builder) { builder.push("Visuals"); - alwaysShowBlockPreview = builder - .comment("Show a block preview if you have a block in hand even in the 'Normal' build mode") - .define("alwaysShowBlockPreview", false); + appearAnimationLength = builder + .comment("How long it takes for a block to appear when placed in ticks.", + "Set to 0 to disable animation.") + .define("appearAnimationLength", 5); - dissolveTimeMultiplier = builder - .comment("How long the dissolve effect takes when placing blocks.", - "Default between 30 and 60 ticks, you can multiply that here.", - "Recommended values:", - "Snappy: 0.7", - "Relaxing: 1.5") - .define("dissolveTimeMultiplier", 1.0); - - shaderThreshold = builder - .comment("Switch to using the simple performance shader when placing more than this many blocks.") - .define("shaderTreshold", 1500); - - useShaders = builder - .comment("Use fancy shaders while placing blocks") - .define("useShaders", true); + breakAnimationLength = builder + .comment("How long the break animation is in ticks.", + "Set to 0 to disable animation.") + .define("breakAnimationLength", 10); builder.pop(); } diff --git a/src/main/java/nl/requios/effortlessbuilding/CommonEvents.java b/src/main/java/nl/requios/effortlessbuilding/CommonEvents.java index 8c00125..541555e 100644 --- a/src/main/java/nl/requios/effortlessbuilding/CommonEvents.java +++ b/src/main/java/nl/requios/effortlessbuilding/CommonEvents.java @@ -11,6 +11,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.common.util.FakePlayer; import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.level.BlockEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -52,6 +53,13 @@ public class CommonEvents { } } + @SubscribeEvent + public static void onTick(TickEvent.LevelTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + EffortlessBuilding.DELAYED_BLOCK_PLACER.tick(); + } + @SubscribeEvent public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) { if (event.getLevel().isClientSide()) return; @@ -65,7 +73,7 @@ public class CommonEvents { BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); - if (buildMode != BuildModes.BuildModeEnum.NORMAL) { + if (buildMode != BuildModes.BuildModeEnum.DISABLED) { //Only cancel if itemblock in hand //Fixed issue with e.g. Create Wrench shift-rightclick disassembling being cancelled. @@ -104,7 +112,7 @@ public class CommonEvents { //Cancel event if necessary //If cant break far then dont cancel event ever BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode(); - if (buildMode != BuildModes.BuildModeEnum.NORMAL && ReachHelper.canBreakFar(event.getPlayer())) { + if (buildMode != BuildModes.BuildModeEnum.DISABLED && ReachHelper.canBreakFar(event.getPlayer())) { event.setCanceled(true); } else { //NORMAL mode, let vanilla handle block breaking @@ -155,7 +163,7 @@ public class CommonEvents { //Set build mode to normal ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); - modeSettings.setBuildMode(BuildModes.BuildModeEnum.NORMAL); + modeSettings.setBuildMode(BuildModes.BuildModeEnum.DISABLED); ModeSettingsManager.setModeSettings(player, modeSettings); //Disable modifiers diff --git a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java index 7d3db47..5748382 100644 --- a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java +++ b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java @@ -22,6 +22,7 @@ import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagContainer; import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagContainer; import nl.requios.effortlessbuilding.gui.RandomizerBagContainer; +import nl.requios.effortlessbuilding.helper.DelayedBlockPlacer; import nl.requios.effortlessbuilding.item.*; import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.proxy.ClientProxy; @@ -39,6 +40,8 @@ public class EffortlessBuilding { public static EffortlessBuilding instance; public static IProxy proxy = DistExecutor.safeRunForDist(() -> ClientProxy::new, () -> ServerProxy::new); + public static final DelayedBlockPlacer DELAYED_BLOCK_PLACER = new DelayedBlockPlacer(); + //Registration private static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); private static final DeferredRegister> CONTAINERS = DeferredRegister.create(ForgeRegistries.MENU_TYPES, EffortlessBuilding.MODID); @@ -69,7 +72,8 @@ public class EffortlessBuilding { CONTAINERS.register(FMLJavaModLoadingContext.get().getModEventBus()); //Register config - ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, BuildConfig.spec); + ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, CommonConfig.spec); + ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ClientConfig.spec); } public static void setup(final FMLCommonSetupEvent event) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java index 2812685..469f5cb 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/BuildModes.java @@ -66,7 +66,7 @@ public class BuildModes { //Check if player reach does not exceed startpos int maxReach = ReachHelper.getMaxReach(player); - if (buildMode != BuildModeEnum.NORMAL && player.blockPosition().distSqr(startPos) > maxReach * maxReach) { + if (buildMode != BuildModeEnum.DISABLED && player.blockPosition().distSqr(startPos) > maxReach * maxReach) { EffortlessBuilding.log(player, "Placement exceeds your reach."); return; } @@ -186,9 +186,6 @@ public class BuildModes { return new Vec3(x, y, z); } - - //-- Common build mode functionality --// - public static Vec3 findYBound(double y, Vec3 start, Vec3 look) { //then x and z are double x = (y - start.y) / look.y * look.x + start.x; @@ -246,8 +243,8 @@ public class BuildModes { } public enum BuildModeEnum { - NORMAL("normal", new Normal(), BuildModeCategoryEnum.BASIC), - NORMAL_PLUS("normal_plus", new NormalPlus(), BuildModeCategoryEnum.BASIC, OptionEnum.BUILD_SPEED), + DISABLED("normal", new Disabled(), BuildModeCategoryEnum.BASIC), + SINGLE("normal_plus", new Single(), BuildModeCategoryEnum.BASIC, OptionEnum.BUILD_SPEED), LINE("line", new Line(), BuildModeCategoryEnum.BASIC /*, OptionEnum.THICKNESS*/), WALL("wall", new Wall(), BuildModeCategoryEnum.BASIC, OptionEnum.FILL), FLOOR("floor", new Floor(), BuildModeCategoryEnum.BASIC, OptionEnum.FILL), diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/ModeSettingsManager.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/ModeSettingsManager.java index 264939c..e34510c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/ModeSettingsManager.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/ModeSettingsManager.java @@ -77,7 +77,7 @@ public class ModeSettingsManager { } public static class ModeSettings { - private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.NORMAL; + private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.DISABLED; public ModeSettings() { } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/NormalPlus.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java similarity index 95% rename from src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/NormalPlus.java rename to src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java index 07c3403..5ffee68 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/NormalPlus.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java @@ -9,7 +9,7 @@ import nl.requios.effortlessbuilding.buildmode.IBuildMode; import java.util.ArrayList; import java.util.List; -public class NormalPlus implements IBuildMode { +public class Disabled implements IBuildMode { @Override public void initialize(Player player) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Normal.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java similarity index 95% rename from src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Normal.java rename to src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java index 3f71149..e68b6f7 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Normal.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java @@ -9,7 +9,7 @@ import nl.requios.effortlessbuilding.buildmode.IBuildMode; import java.util.ArrayList; import java.util.List; -public class Normal implements IBuildMode { +public class Single implements IBuildMode { @Override public void initialize(Player player) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java index db2363a..1a5d16f 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/BuildModifiers.java @@ -14,11 +14,13 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.minecraft.world.level.Level; +import nl.requios.effortlessbuilding.CommonConfig; +import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.compatibility.CompatHelper; -import nl.requios.effortlessbuilding.helper.InventoryHelper; +import nl.requios.effortlessbuilding.helper.DelayedBlockPlacer; import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; -import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; +import nl.requios.effortlessbuilding.render.BlockPreviews; import java.util.ArrayList; import java.util.Collections; @@ -42,55 +44,17 @@ public class BuildModifiers { //check if valid blockstates if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; - //remember previous blockstates for undo - List previousBlockStates = new ArrayList<>(coordinates.size()); - List newBlockStates = new ArrayList<>(coordinates.size()); - for (BlockPos coordinate : coordinates) { - previousBlockStates.add(world.getBlockState(coordinate)); - } - if (world.isClientSide) { - BlockPreviewRenderer.onBlocksPlaced(); - - newBlockStates = blockStates; + BlockPreviews.onBlocksPlaced(); } else { - //place blocks - for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) { - BlockPos blockPos = coordinates.get(i); - BlockState blockState = blockStates.get(i); - ItemStack itemStack = itemStacks.get(i); + int delay = CommonConfig.visuals.appearAnimationLength.get() * 3; //DelayedBlockPlacer is called 3 times per tick? - if (world.isLoaded(blockPos)) { - //check itemstack empty - if (itemStack.isEmpty()) { - //try to find new stack, otherwise continue - itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); - if (itemStack.isEmpty()) continue; - } - SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, Direction.UP, hitVec, false, false, false); - } - } - - //find actual new blockstates for undo - for (BlockPos coordinate : coordinates) { - newBlockStates.add(world.getBlockState(coordinate)); - } - } - - //Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work - //(Block is placed by the time it gets here, and unplaced after this) - if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.defaultBlockState()); - - //If all new blockstates are air then no use in adding it, no block was actually placed - //Can happen when e.g. placing one block in yourself - if (Collections.frequency(newBlockStates, Blocks.AIR.defaultBlockState()) != newBlockStates.size()) { - //add to undo stack - BlockPos firstPos = startCoordinates.get(0); - BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); - UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos)); + //place blocks after delay + EffortlessBuilding.DELAYED_BLOCK_PLACER.placeBlocksDelayed(new DelayedBlockPlacer.Entry(world, player, coordinates, + blockStates, itemStacks, hitVec, placeStartPos, delay)); } } @@ -109,7 +73,7 @@ public class BuildModifiers { } if (world.isClientSide) { - BlockPreviewRenderer.onBlocksBroken(); + BlockPreviews.onBlocksBroken(); //list of air blockstates for (int i = 0; i < coordinates.size(); i++) { @@ -237,6 +201,7 @@ public class BuildModifiers { } public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) { + //startPos can be null return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) || Array.isEnabled(modifierSettings.getArraySettings()) || RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) || diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java index 7583398..87d9e2e 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/ModifierSettingsManager.java @@ -5,7 +5,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.network.PacketDistributor; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.helper.ReachHelper; @@ -192,16 +192,16 @@ public class ModifierSettingsManager { int reach = 10; switch (reachUpgrade) { case 0: - reach = BuildConfig.reach.maxReachLevel0.get(); + reach = CommonConfig.reach.maxReachLevel0.get(); break; case 1: - reach = BuildConfig.reach.maxReachLevel1.get(); + reach = CommonConfig.reach.maxReachLevel1.get(); break; case 2: - reach = BuildConfig.reach.maxReachLevel2.get(); + reach = CommonConfig.reach.maxReachLevel2.get(); break; case 3: - reach = BuildConfig.reach.maxReachLevel3.get(); + reach = CommonConfig.reach.maxReachLevel3.get(); break; } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java index 8d0152c..20b9a48 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmodifier/UndoRedo.java @@ -10,12 +10,12 @@ import net.minecraft.core.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; import net.minecraft.server.level.ServerLevel; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.helper.FixedStack; import nl.requios.effortlessbuilding.helper.InventoryHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper; -import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; +import nl.requios.effortlessbuilding.render.BlockPreviews; import java.util.*; @@ -50,7 +50,7 @@ public class UndoRedo { //If no stack exists, make one if (!undoStacks.containsKey(player.getUUID())) { - undoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()])); + undoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[CommonConfig.survivalBalancers.undoStackSize.get()])); } undoStacks.get(player.getUUID()).push(blockSet); @@ -63,7 +63,7 @@ public class UndoRedo { //If no stack exists, make one if (!redoStacks.containsKey(player.getUUID())) { - redoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()])); + redoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[CommonConfig.survivalBalancers.undoStackSize.get()])); } redoStacks.get(player.getUUID()).push(blockSet); @@ -88,7 +88,7 @@ public class UndoRedo { List itemStacks = findItemStacksInInventory(player, previousBlockStates); if (player.level.isClientSide) { - BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos()); + BlockPreviews.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos()); } else { //break all those blocks, reset to what they were for (int i = 0; i < coordinates.size(); i++) { @@ -148,7 +148,7 @@ public class UndoRedo { List itemStacks = findItemStacksInInventory(player, newBlockStates); if (player.level.isClientSide) { - BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos()); + BlockPreviews.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos()); } else { //place blocks for (int i = 0; i < coordinates.size(); i++) { diff --git a/src/main/java/nl/requios/effortlessbuilding/capability/ModeCapabilityManager.java b/src/main/java/nl/requios/effortlessbuilding/capability/ModeCapabilityManager.java index cc40ab2..6942e87 100644 --- a/src/main/java/nl/requios/effortlessbuilding/capability/ModeCapabilityManager.java +++ b/src/main/java/nl/requios/effortlessbuilding/capability/ModeCapabilityManager.java @@ -100,7 +100,7 @@ public class ModeCapabilityManager { //TODO add mode settings - ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.NORMAL); + ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.DISABLED); instance.setModeData(modeSettings); } diff --git a/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockParams.java b/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockParams.java index ecb3e1a..7202e91 100644 --- a/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockParams.java +++ b/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockParams.java @@ -3,6 +3,8 @@ package nl.requios.effortlessbuilding.create.foundation.utility.ghost; import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import nl.requios.effortlessbuilding.create.foundation.utility.Color; +import nl.requios.effortlessbuilding.create.foundation.utility.outliner.Outline; import java.util.function.Supplier; @@ -11,11 +13,15 @@ public class GhostBlockParams { protected final BlockState state; protected BlockPos pos; protected Supplier alphaSupplier; + protected Supplier scaleSupplier; + public Supplier rgbSupplier; private GhostBlockParams(BlockState state) { this.state = state; this.pos = BlockPos.ZERO; this.alphaSupplier = () -> 1f; + this.scaleSupplier = () -> 0.85f; + this.rgbSupplier = () -> Color.WHITE; } public static GhostBlockParams of(BlockState state) { @@ -47,4 +53,31 @@ public class GhostBlockParams { public GhostBlockParams breathingAlpha() { return this.alpha(() -> (float) GhostBlocks.getBreathingAlpha()); } + + public GhostBlockParams scale(Supplier scaleSupplier) { + this.scaleSupplier = scaleSupplier; + return this; + } + + public GhostBlockParams scale(float scale) { + return this.scale(() -> scale); + } + + public GhostBlockParams colored(Supplier colorSupplier) { + this.rgbSupplier = colorSupplier; + return this; + } + + public GhostBlockParams colored(Color color) { + return this.colored(() -> color); + } + + public GhostBlockParams colored(int color) { + var color2 = new Color(color, false); + return this.colored(() -> color2); + } + + public GhostBlockParams breathingCyan() { + return this.colored(() -> new Color((float) GhostBlocks.getBreathingColor(), 1f, 1f, 1f)); + } } diff --git a/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockRenderer.java b/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockRenderer.java index 1fa167b..fb29bc1 100644 --- a/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockRenderer.java +++ b/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlockRenderer.java @@ -19,6 +19,7 @@ import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.minecraftforge.client.model.data.ModelData; +import nl.requios.effortlessbuilding.create.foundation.utility.Color; import javax.annotation.Nullable; import java.util.List; @@ -76,6 +77,8 @@ public abstract class GhostBlockRenderer { BlockState state = params.state; BlockPos pos = params.pos; float alpha = params.alphaSupplier.get()/* * .75f* PlacementHelpers.getCurrentAlpha()*/; + float scale = params.scaleSupplier.get(); + Color color = params.rgbSupplier.get(); BakedModel model = dispatcher.getBlockModel(state); RenderType layer = RenderType.translucent(); @@ -85,10 +88,10 @@ public abstract class GhostBlockRenderer { ms.translate(pos.getX(), pos.getY(), pos.getZ()); ms.translate(.5, .5, .5); - ms.scale(.85f, .85f, .85f); + ms.scale(scale, scale, scale); ms.translate(-.5, -.5, -.5); - renderModel(ms.last(), vb, state, model, 0f, 1f, 1f, alpha, + renderModel(ms.last(), vb, state, model, color.getRedAsFloat(), color.getGreenAsFloat(), color.getBlueAsFloat(), alpha, LevelRenderer.getLightColor(mc.level, pos), OverlayTexture.NO_OVERLAY, ModelUtil.VIRTUAL_DATA, layer); @@ -120,15 +123,15 @@ public abstract class GhostBlockRenderer { float f; float f1; float f2; - if (quad.isTinted()) { +// if (quad.isTinted()) { f = Mth.clamp(red, 0.0F, 1.0F); f1 = Mth.clamp(green, 0.0F, 1.0F); f2 = Mth.clamp(blue, 0.0F, 1.0F); - } else { - f = 1.0F; - f1 = 1.0F; - f2 = 1.0F; - } +// } else { +// f = 1.0F; +// f1 = 1.0F; +// f2 = 1.0F; +// } consumer.putBulkData(pose, quad, f, f1, f2, alpha, packedLight, packedOverlay, true); } diff --git a/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlocks.java b/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlocks.java index eb38081..96c2893 100644 --- a/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlocks.java +++ b/src/main/java/nl/requios/effortlessbuilding/create/foundation/utility/ghost/GhostBlocks.java @@ -17,6 +17,13 @@ public class GhostBlocks { return 0.55d - 0.2d * offset; } + public static double getBreathingColor() { + double period = 2500; + double timer = System.currentTimeMillis() % period; + double offset = Mth.cos((float) ((2d/period) * Math.PI * timer)); + return 0.35d + 0.35d * offset; + } + final Map ghosts; public GhostBlockParams showGhostState(Object slot, BlockState state) { diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/DelayedBlockPlacer.java b/src/main/java/nl/requios/effortlessbuilding/helper/DelayedBlockPlacer.java new file mode 100644 index 0000000..bac8f8c --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/helper/DelayedBlockPlacer.java @@ -0,0 +1,108 @@ +package nl.requios.effortlessbuilding.helper; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.Vec3; +import nl.requios.effortlessbuilding.buildmodifier.BlockSet; +import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; +import nl.requios.effortlessbuilding.create.foundation.utility.AnimationTickHolder; + +import java.util.*; + +public class DelayedBlockPlacer { + + private final Set entries = Collections.synchronizedSet(new HashSet<>()); + private final Set entriesView = Collections.unmodifiableSet(entries); + + public void placeBlocksDelayed(Entry entry) { + if (entry.world.isClientSide) return; + + entries.add(entry); + } + + public void tick() { + for (Entry entry : entries) { + entry.ticksTillPlacement--; + if (entry.ticksTillPlacement <= 0) { + entry.place(); + entries.remove(entry); + } + } + } + + public Set getEntries() { + return entriesView; + } + + public static class Entry { + private Level world; + private Player player; + private List coordinates; + private List blockStates; + private List itemStacks; + private Vec3 hitVec; + private boolean placeStartPos; + private int ticksTillPlacement; + + public Entry(Level world, Player player, List coordinates, List blockStates, + List itemStacks, Vec3 hitVec, boolean placeStartPos, int ticksTillPlacement) { + this.world = world; + this.player = player; + this.coordinates = coordinates; + this.blockStates = blockStates; + this.itemStacks = itemStacks; + this.hitVec = hitVec; + this.placeStartPos = placeStartPos; + this.ticksTillPlacement = ticksTillPlacement; + } + + public void place() { + //remember previous blockstates for undo + List previousBlockStates = new ArrayList<>(coordinates.size()); + for (BlockPos coordinate : coordinates) { + previousBlockStates.add(world.getBlockState(coordinate)); + } + + for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) { + BlockPos blockPos = coordinates.get(i); + BlockState blockState = blockStates.get(i); + ItemStack itemStack = itemStacks.get(i); + + if (world.isLoaded(blockPos)) { + //check itemstack empty + if (itemStack.isEmpty()) { + //try to find new stack, otherwise continue + itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); + if (itemStack.isEmpty()) continue; + } + SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, Direction.UP, hitVec, false, false, false); + } + } + + //find actual new blockstates for undo + List newBlockStates = new ArrayList<>(coordinates.size()); + for (BlockPos coordinate : coordinates) { + newBlockStates.add(world.getBlockState(coordinate)); + } + + //Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work + //(Block is placed by the time it gets here, and unplaced after this) + if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.defaultBlockState()); + + //If all new blockstates are air then no use in adding it, no block was actually placed + //Can happen when e.g. placing one block in yourself + if (Collections.frequency(newBlockStates, Blocks.AIR.defaultBlockState()) != newBlockStates.size()) { + //add to undo stack + BlockPos firstPos = coordinates.get(0); + BlockPos secondPos = coordinates.get(coordinates.size() - 1); + UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos)); + } + } + + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java index a22b6e7..656259d 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/ReachHelper.java @@ -2,28 +2,28 @@ package nl.requios.effortlessbuilding.helper; import net.minecraft.world.entity.player.Player; import net.minecraft.util.Mth; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; public class ReachHelper { public static int getMaxReach(Player player) { - if (player.isCreative()) return BuildConfig.reach.maxReachCreative.get(); + if (player.isCreative()) return CommonConfig.reach.maxReachCreative.get(); - if (!BuildConfig.reach.enableReachUpgrades.get()) return BuildConfig.reach.maxReachLevel3.get(); + if (!CommonConfig.reach.enableReachUpgrades.get()) return CommonConfig.reach.maxReachLevel3.get(); //Check buildsettings for reachUpgrade int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade(); switch (reachUpgrade) { case 0: - return BuildConfig.reach.maxReachLevel0.get(); + return CommonConfig.reach.maxReachLevel0.get(); case 1: - return BuildConfig.reach.maxReachLevel1.get(); + return CommonConfig.reach.maxReachLevel1.get(); case 2: - return BuildConfig.reach.maxReachLevel2.get(); + return CommonConfig.reach.maxReachLevel2.get(); case 3: - return BuildConfig.reach.maxReachLevel3.get(); + return CommonConfig.reach.maxReachLevel3.get(); } - return BuildConfig.reach.maxReachLevel0.get(); + return CommonConfig.reach.maxReachLevel0.get(); } public static int getPlacementReach(Player player) { diff --git a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java index 64434a6..19d9650 100644 --- a/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/helper/SurvivalHelper.java @@ -23,7 +23,7 @@ import net.minecraft.world.level.material.Material; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.event.ForgeEventFactory; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.compatibility.CompatHelper; @@ -187,17 +187,21 @@ public class SurvivalHelper { */ public static boolean canPlace(Level world, Player player, BlockPos pos, BlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, Direction sidePlacedOn) { - //Check if itemstack is correct - if (!(itemStack.getItem() instanceof BlockItem) || Block.byItem(itemStack.getItem()) != newBlockState.getBlock()) { -// EffortlessBuilding.log(player, "Cannot (re)place block", true); -// EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString()); - //Happens when breaking blocks, no need to notify in that case - return false; + if (!player.isCreative()) { + //Check if itemstack is correct + if (itemStack.isEmpty() || !(itemStack.getItem() instanceof BlockItem) || + Block.byItem(itemStack.getItem()) != newBlockState.getBlock()) { + return false; + } } - Block block = ((BlockItem) itemStack.getItem()).getBlock(); + Block block = null; + if (itemStack != null && !itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) + block = ((BlockItem) itemStack.getItem()).getBlock(); + else //In creative we might not have an itemstack + block = newBlockState.getBlock(); - return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) && + return canPlayerEdit(player, world, pos, itemStack) && mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) && canReplace(world, player, pos); } @@ -208,7 +212,7 @@ public class SurvivalHelper { BlockState state = world.getBlockState(pos); - int miningLevel = BuildConfig.survivalBalancers.quickReplaceMiningLevel.get(); + int miningLevel = CommonConfig.survivalBalancers.quickReplaceMiningLevel.get(); switch (miningLevel) { case -1: return !state.requiresCorrectToolForDrops(); @@ -245,7 +249,7 @@ public class SurvivalHelper { //From World#mayPlace private static boolean mayPlace(Level world, Block blockIn, BlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, Direction sidePlacedOn, @Nullable Entity placer) { - BlockState iblockstate1 = world.getBlockState(pos); + BlockState currentBlockState = world.getBlockState(pos); VoxelShape voxelShape = skipCollisionCheck ? null : blockIn.defaultBlockState().getCollisionShape(world, pos); if (voxelShape != null && !world.isUnobstructed(placer, voxelShape)) { @@ -259,22 +263,20 @@ public class SurvivalHelper { //Check if same block //Necessary otherwise extra items will be dropped - if (iblockstate1 == newBlockState) { + if (currentBlockState == newBlockState) { return false; } - //TODO 1.14 check what Material.CIRCUITS has become - if (iblockstate1.getMaterial() == Material.BUILDABLE_GLASS && blockIn == Blocks.ANVIL) { + if (currentBlockState.getMaterial() == Material.BUILDABLE_GLASS && blockIn == Blocks.ANVIL) { return true; } //Check quickreplace - if (placer instanceof Player && ModifierSettingsManager.getModifierSettings(((Player) placer)).doQuickReplace()) { + if (placer != null && ModifierSettingsManager.getModifierSettings(((Player) placer)).doQuickReplace()) { return true; } - //TODO 1.13 replaceable - return iblockstate1.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/; + return currentBlockState.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/; } diff --git a/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java b/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java index aa9eb22..0617705 100644 --- a/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java +++ b/src/main/java/nl/requios/effortlessbuilding/item/AbstractRandomizerBagItem.java @@ -136,7 +136,7 @@ public abstract class AbstractRandomizerBagItem extends Item { //Only place manually if in normal vanilla mode BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); - if (buildMode != BuildModes.BuildModeEnum.NORMAL || modifierSettings.doQuickReplace()) { + if (buildMode != BuildModes.BuildModeEnum.DISABLED || modifierSettings.doQuickReplace()) { return InteractionResult.FAIL; } diff --git a/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade1Item.java b/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade1Item.java index cd78755..8caef7a 100644 --- a/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade1Item.java +++ b/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade1Item.java @@ -9,7 +9,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.network.chat.Component; import net.minecraft.ChatFormatting; import net.minecraft.world.level.Level; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.helper.ReachHelper; @@ -63,7 +63,7 @@ public class ReachUpgrade1Item extends Item { @Override public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel1.get())); + tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + CommonConfig.reach.maxReachLevel1.get())); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade2Item.java b/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade2Item.java index 17fbdce..5ac62ed 100644 --- a/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade2Item.java +++ b/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade2Item.java @@ -9,14 +9,13 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.network.chat.Component; import net.minecraft.ChatFormatting; import net.minecraft.world.level.Level; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.helper.ReachHelper; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import java.awt.*; import java.util.List; import net.minecraft.resources.ResourceLocation; @@ -68,7 +67,7 @@ public class ReachUpgrade2Item extends Item { @Override public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel2.get())); + tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + CommonConfig.reach.maxReachLevel2.get())); tooltip.add(Component.literal(ChatFormatting.GRAY + "Previous upgrades need to be consumed first")); } } diff --git a/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade3Item.java b/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade3Item.java index 7aedbc6..2ed5a91 100644 --- a/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade3Item.java +++ b/src/main/java/nl/requios/effortlessbuilding/item/ReachUpgrade3Item.java @@ -9,7 +9,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.network.chat.Component; import net.minecraft.ChatFormatting; import net.minecraft.world.level.Level; -import nl.requios.effortlessbuilding.BuildConfig; +import nl.requios.effortlessbuilding.CommonConfig; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.helper.ReachHelper; @@ -70,7 +70,7 @@ public class ReachUpgrade3Item extends Item { @Override public void appendHoverText(ItemStack stack, @Nullable Level world, List tooltip, TooltipFlag flag) { - tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel3.get())); + tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + CommonConfig.reach.maxReachLevel3.get())); tooltip.add(Component.literal(ChatFormatting.GRAY + "Previous upgrades need to be consumed first")); } diff --git a/src/main/java/nl/requios/effortlessbuilding/network/AddUndoMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/AddUndoMessage.java index 4a639b2..4a99723 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/AddUndoMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/AddUndoMessage.java @@ -14,7 +14,6 @@ import net.minecraftforge.network.NetworkEvent; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.BlockSet; import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; -import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import java.util.ArrayList; import java.util.function.Supplier; diff --git a/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java index 2d68d31..f588936 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/BlockPlacedMessage.java @@ -12,7 +12,7 @@ import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.network.NetworkEvent; import nl.requios.effortlessbuilding.buildmode.BuildModes; -import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; +import nl.requios.effortlessbuilding.render.BlockPreviews; import java.util.function.Supplier; @@ -112,7 +112,7 @@ public class BlockPlacedMessage { public static class ClientHandler { public static void handle(BlockPlacedMessage message, Supplier ctx) { //Nod RenderHandler to do the dissolve shader effect - BlockPreviewRenderer.onBlocksPlaced(); + BlockPreviews.onBlocksPlaced(); } } } diff --git a/src/main/java/nl/requios/effortlessbuilding/network/ClearUndoMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/ClearUndoMessage.java index 0bd946c..1358242 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/ClearUndoMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/ClearUndoMessage.java @@ -9,7 +9,6 @@ import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.network.NetworkEvent; import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; -import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import java.util.function.Supplier; diff --git a/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java index d7f960b..093dcce 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/RequestLookAtMessage.java @@ -11,8 +11,6 @@ import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.network.NetworkEvent; import nl.requios.effortlessbuilding.ClientEvents; import nl.requios.effortlessbuilding.EffortlessBuilding; -import nl.requios.effortlessbuilding.proxy.ClientProxy; -import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import java.util.function.Supplier; diff --git a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java deleted file mode 100644 index 99284be..0000000 --- a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java +++ /dev/null @@ -1,412 +0,0 @@ -package nl.requios.effortlessbuilding.render; - -import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.blaze3d.vertex.VertexConsumer; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.block.BlockRenderDispatcher; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.core.Direction; -import net.minecraft.sounds.SoundSource; -import net.minecraft.core.BlockPos; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.util.Mth; -import net.minecraft.world.phys.HitResult; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import nl.requios.effortlessbuilding.BuildConfig; -import nl.requios.effortlessbuilding.ClientEvents; -import nl.requios.effortlessbuilding.EffortlessBuilding; -import nl.requios.effortlessbuilding.EffortlessBuildingClient; -import nl.requios.effortlessbuilding.buildmode.BuildModes; -import nl.requios.effortlessbuilding.buildmode.IBuildMode; -import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; -import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings; -import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; -import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; -import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; -import nl.requios.effortlessbuilding.compatibility.CompatHelper; -import nl.requios.effortlessbuilding.create.AllSpecialTextures; -import nl.requios.effortlessbuilding.create.CreateClient; -import nl.requios.effortlessbuilding.create.foundation.utility.Color; -import nl.requios.effortlessbuilding.helper.ReachHelper; -import nl.requios.effortlessbuilding.helper.SurvivalHelper; -import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; -import nl.requios.effortlessbuilding.proxy.ClientProxy; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -@OnlyIn(Dist.CLIENT) -public class BlockPreviewRenderer { - private static final List placedDataList = new ArrayList<>(); - private static List previousCoordinates; - private static List previousBlockStates; - private static List previousItemStacks; - private static BlockPos previousFirstPos; - private static BlockPos previousSecondPos; - private static int soundTime = 0; - - public static void render(PoseStack ms, MultiBufferSource.BufferSource buffer, Player player, ModifierSettings modifierSettings, ModeSettings modeSettings) { - - //Render placed blocks with dissolve effect - //Use fancy shader if config allows, otherwise no dissolve - if (BuildConfig.visuals.useShaders.get()) { - for (int i = 0; i < placedDataList.size(); i++) { - PlacedData placed = placedDataList.get(i); - if (placed.coordinates != null && !placed.coordinates.isEmpty()) { - - double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get(); - float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime; - renderBlockPreviews(ms, buffer, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking); - } - } - } - //Expire - placedDataList.removeIf(placed -> { - double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get(); - return placed.time + totalTime < ClientEvents.ticksInGame; - }); - - //Render block previews - HitResult lookingAt = ClientEvents.getLookingAt(player); - if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.NORMAL) - lookingAt = Minecraft.getInstance().hitResult; - - ItemStack mainhand = player.getMainHandItem(); - boolean noBlockInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand)); - - BlockPos startPos = null; - Direction sideHit = null; - Vec3 hitVec = null; - - //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) - if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) { - BlockHitResult blockLookingAt = (BlockHitResult) lookingAt; - startPos = blockLookingAt.getBlockPos(); - - //Check if tool (or none) in hand - //TODO 1.13 replaceable - boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable(); - boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, blockLookingAt.getDirection()); - if (!modifierSettings.doQuickReplace() && !noBlockInHand && !replaceable && !becomesDoubleSlab) { - startPos = startPos.relative(blockLookingAt.getDirection()); - } - - //Get under tall grass and other replaceable blocks - if (modifierSettings.doQuickReplace() && !noBlockInHand && replaceable) { - startPos = startPos.below(); - } - - sideHit = blockLookingAt.getDirection(); - hitVec = blockLookingAt.getLocation(); - } - - //Dont render if in normal mode and modifiers are disabled - //Unless alwaysShowBlockPreview is true in config - if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) { - - //Keep blockstate the same for every block in the buildmode - //So dont rotate blocks when in the middle of placing wall etc. - if (BuildModes.isActive(player)) { - IBuildMode buildModeInstance = modeSettings.getBuildMode().instance; - if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player); - if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player); - } - - if (sideHit != null) { - - //Should be red? - boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player); - - //get coordinates - List startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace()); - - //Remember first and last point for the shader - BlockPos firstPos = BlockPos.ZERO, secondPos = BlockPos.ZERO; - if (!startCoordinates.isEmpty()) { - firstPos = startCoordinates.get(0); - secondPos = startCoordinates.get(startCoordinates.size() - 1); - } - - //Limit number of blocks you can place - int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); - if (startCoordinates.size() > limit) { - startCoordinates = startCoordinates.subList(0, limit); - } - - List newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); - - sortOnDistanceToPlayer(newCoordinates, player); - - hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), - Math.abs(hitVec.z - ((int) hitVec.z))); - - //Get blockstates - List itemStacks = new ArrayList<>(); - List blockStates = new ArrayList<>(); - if (breaking) { - //Find blockstate of world - for (BlockPos coordinate : newCoordinates) { - blockStates.add(player.level.getBlockState(coordinate)); - } - } else { - blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); - } - - - //Check if they are different from previous - //TODO fix triggering when moving player - if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) { - previousCoordinates = newCoordinates; - //remember the rest for placed blocks - previousBlockStates = blockStates; - previousItemStacks = itemStacks; - previousFirstPos = firstPos; - previousSecondPos = secondPos; - - //if so, renew randomness of randomizer bag - AbstractRandomizerBagItem.renewRandomness(); - //and play sound (max once every tick) - if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientEvents.ticksInGame - 0) { - soundTime = ClientEvents.ticksInGame; - - if (blockStates.get(0) != null) { - SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.level, - newCoordinates.get(0), player); - player.level.playSound(player, player.blockPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(), - SoundSource.BLOCKS, 0.3f, 0.8f); - } - } - } - - //Render block previews - if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) { - int blockCount; - - if (!breaking) { - //Use fancy shader if config allows, otherwise outlines - if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderThreshold.get()) { - blockCount = renderBlockPreviews(ms, buffer, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking); - - CreateClient.OUTLINER.showCluster("blockpreviews", newCoordinates) - .withFaceTexture(AllSpecialTextures.CHECKERED) - .disableNormals() - .lineWidth(1 / 32f) - .colored(new Color(1f, 1f, 1f, 1f)); - } else { -// VertexConsumer vc = RenderHandler.beginLines(buffer); -// -// Vec3 color = new Vec3(1f, 1f, 1f); -// if (breaking) color = new Vec3(1f, 0f, 0f); -// -// for (int i = newCoordinates.size() - 1; i >= 0; i--) { -// VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.level, newCoordinates.get(i)); -// RenderHandler.renderBlockOutline(ms, vc, newCoordinates.get(i), collisionShape, color); -// } -// -// RenderHandler.endLines(buffer); - - CreateClient.OUTLINER.showCluster("blockpreviews", newCoordinates) - .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED) - .disableNormals() - .lineWidth(1 / 16f) - .colored(new Color(1f, 1f, 1f, 1f)); - - blockCount = newCoordinates.size(); - } - - } else { - //Breaking - CreateClient.OUTLINER.showCluster("blockpreviews", newCoordinates) - .withFaceTexture(AllSpecialTextures.THIN_CHECKERED) - .disableNormals() - .lineWidth(1 / 16f) - .colored(new Color(0.8f, 0.1f, 0.1f, 1f)); - blockCount = newCoordinates.size(); - } - - //Display block count and dimensions in actionbar - if (BuildModes.isActive(player)) { - - //Find min and max values (not simply firstPos and secondPos because that doesn't work with circles) - int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE; - int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE; - int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE; - for (BlockPos pos : startCoordinates) { - if (pos.getX() < minX) minX = pos.getX(); - if (pos.getX() > maxX) maxX = pos.getX(); - if (pos.getY() < minY) minY = pos.getY(); - if (pos.getY() > maxY) maxY = pos.getY(); - if (pos.getZ() < minZ) minZ = pos.getZ(); - if (pos.getZ() > maxZ) maxZ = pos.getZ(); - } - BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1); - - String dimensions = "("; - if (dim.getX() > 1) dimensions += dim.getX() + "x"; - if (dim.getZ() > 1) dimensions += dim.getZ() + "x"; - if (dim.getY() > 1) dimensions += dim.getY() + "x"; - dimensions = dimensions.substring(0, dimensions.length() - 1); - if (dimensions.length() > 1) dimensions += ")"; - - EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true); - } - } - - - } - - //Draw outlines if no block in hand - //Find proper raytrace: either normal range or increased range depending on canBreakFar -// VertexConsumer vc = RenderHandler.beginLines(buffer); -// HitResult objectMouseOver = Minecraft.getInstance().hitResult; -// HitResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver; -// -// if (player.isCreative() && noBlockInHand && breakingRaytrace != null && breakingRaytrace.getType() == HitResult.Type.BLOCK) { -// BlockHitResult blockBreakingRaytrace = (BlockHitResult) breakingRaytrace; -// List breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getBlockPos()); -// -// //Only render first outline if further than normal reach -// boolean excludeFirst = objectMouseOver != null && objectMouseOver.getType() == HitResult.Type.BLOCK; -// for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) { -// BlockPos coordinate = breakCoordinates.get(i); -// -// BlockState blockState = player.level.getBlockState(coordinate); -// if (!blockState.isAir()) { -// if (SurvivalHelper.canBreak(player.level, player, coordinate) || i == 0) { -// VoxelShape collisionShape = blockState.getCollisionShape(player.level, coordinate); -// RenderHandler.renderBlockOutline(ms, vc, coordinate, collisionShape, new Vec3(0f, 0f, 0f)); -// } -// } -// } -// } -// RenderHandler.endLines(buffer); - } - } - - //Whether to draw any block previews or outlines - public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) { - return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.NORMAL || - (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) || - BuildConfig.visuals.alwaysShowBlockPreview.get(); - } - - protected static int renderBlockPreviews(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, List coordinates, List blockStates, - List itemStacks, float dissolve, BlockPos firstPos, - BlockPos secondPos, boolean checkCanPlace, boolean red) { - Player player = Minecraft.getInstance().player; - ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); - BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer(); - int blocksValid = 0; - - if (coordinates.isEmpty()) return blocksValid; - - for (int i = coordinates.size() - 1; i >= 0; i--) { - BlockPos blockPos = coordinates.get(i); - BlockState blockState = blockStates.get(i); - ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i); - if (CompatHelper.isItemBlockProxy(itemstack)) - itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); - - //Check if we can place - //If check is turned off, check if blockstate is the same (for dissolve effect) - if ((!checkCanPlace && player.level.getBlockState(blockPos) == blockState) || //TODO enable (breaks the breaking shader) - SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP)) { - - RenderHandler.renderBlockPreview(matrixStack, renderTypeBuffer, dispatcher, blockPos, blockState, dissolve, firstPos, secondPos, red); - blocksValid++; - } - } - return blocksValid; - } - - public static void onBlocksPlaced() { - onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos); - } - - public static void onBlocksPlaced(List coordinates, List itemStacks, List blockStates, - BlockPos firstPos, BlockPos secondPos) { - LocalPlayer player = Minecraft.getInstance().player; - ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); - ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); - - //Check if block previews are enabled - if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) { - - //Save current coordinates, blockstates and itemstacks - if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() && - coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderThreshold.get()) { - - placedDataList.add(new PlacedData(ClientEvents.ticksInGame, coordinates, blockStates, - itemStacks, firstPos, secondPos, false)); - } - } - - } - - public static void onBlocksBroken() { - onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos); - } - - public static void onBlocksBroken(List coordinates, List itemStacks, List blockStates, - BlockPos firstPos, BlockPos secondPos) { - LocalPlayer player = Minecraft.getInstance().player; - ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); - ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); - - //Check if block previews are enabled - if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) { - - //Save current coordinates, blockstates and itemstacks - if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() && - coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderThreshold.get()) { - - sortOnDistanceToPlayer(coordinates, player); - - placedDataList.add(new PlacedData(ClientEvents.ticksInGame, coordinates, blockStates, - itemStacks, firstPos, secondPos, true)); - } - } - - } - - private static void sortOnDistanceToPlayer(List coordinates, Player player) { - - Collections.sort(coordinates, (lhs, rhs) -> { - // -1 - less than, 1 - greater than, 0 - equal - double lhsDistanceToPlayer = Vec3.atLowerCornerOf(lhs).subtract(player.getEyePosition(1f)).lengthSqr(); - double rhsDistanceToPlayer = Vec3.atLowerCornerOf(rhs).subtract(player.getEyePosition(1f)).lengthSqr(); - return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer); - }); - - } - - static class PlacedData { - float time; - List coordinates; - List blockStates; - List itemStacks; - BlockPos firstPos; - BlockPos secondPos; - boolean breaking; - - public PlacedData(float time, List coordinates, List blockStates, - List itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) { - this.time = time; - this.coordinates = coordinates; - this.blockStates = blockStates; - this.itemStacks = itemStacks; - this.firstPos = firstPos; - this.secondPos = secondPos; - this.breaking = breaking; - } - } -} diff --git a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java new file mode 100644 index 0000000..1e20aca --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java @@ -0,0 +1,414 @@ +package nl.requios.effortlessbuilding.render; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.SoundType; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.core.Direction; +import net.minecraft.sounds.SoundSource; +import net.minecraft.core.BlockPos; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import nl.requios.effortlessbuilding.ClientConfig; +import nl.requios.effortlessbuilding.ClientEvents; +import nl.requios.effortlessbuilding.CommonConfig; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.buildmode.BuildModes; +import nl.requios.effortlessbuilding.buildmode.IBuildMode; +import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; +import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings; +import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; +import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; +import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; +import nl.requios.effortlessbuilding.compatibility.CompatHelper; +import nl.requios.effortlessbuilding.create.AllSpecialTextures; +import nl.requios.effortlessbuilding.create.CreateClient; +import nl.requios.effortlessbuilding.create.foundation.utility.Color; +import nl.requios.effortlessbuilding.helper.ReachHelper; +import nl.requios.effortlessbuilding.helper.SurvivalHelper; +import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +@OnlyIn(Dist.CLIENT) +public class BlockPreviews { + private static final List placedDataList = new ArrayList<>(); + private static List previousCoordinates; + private static List previousBlockStates; + private static List previousItemStacks; + private static BlockPos previousFirstPos; + private static BlockPos previousSecondPos; + private static int soundTime = 0; + + public static void drawPlacedBlocks(Player player, ModifierSettings modifierSettings) { + //Render placed blocks with appear animation + if (ClientConfig.visuals.showBlockPreviews.get()) { + for (PlacedData placed : placedDataList) { + if (placed.coordinates != null && !placed.coordinates.isEmpty()) { + + int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get(); + if (totalTime <= 0) continue; + + float dissolve = (ClientEvents.ticksInGame - placed.time) / (float) totalTime; + renderBlockPreviews(player, modifierSettings, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking); + + CreateClient.OUTLINER.showCluster(placed.time, placed.coordinates); + } + } + } + + //Expire + placedDataList.removeIf(placed -> { + int totalTime = placed.breaking ? CommonConfig.visuals.breakAnimationLength.get() : CommonConfig.visuals.appearAnimationLength.get(); + return placed.time + totalTime < ClientEvents.ticksInGame; + }); + } + + public static void drawLookAtPreview(Player player, ModeSettings modeSettings, ModifierSettings modifierSettings, BlockPos startPos, Direction sideHit, Vec3 hitVec) { + if (!doShowBlockPreviews(modifierSettings, modeSettings, startPos)) return; + + //Keep blockstate the same for every block in the buildmode + //So dont rotate blocks when in the middle of placing wall etc. + if (BuildModes.isActive(player)) { + IBuildMode buildModeInstance = modeSettings.getBuildMode().instance; + if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player); + if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player); + } + + if (sideHit == null) return; + + //Should be red? + boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player); + + //get coordinates + List startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace()); + + //Remember first and last point for the shader + BlockPos firstPos = BlockPos.ZERO, secondPos = BlockPos.ZERO; + if (!startCoordinates.isEmpty()) { + firstPos = startCoordinates.get(0); + secondPos = startCoordinates.get(startCoordinates.size() - 1); + } + + //Limit number of blocks you can place + int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); + if (startCoordinates.size() > limit) { + startCoordinates = startCoordinates.subList(0, limit); + } + + List newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); + + sortOnDistanceToPlayer(newCoordinates, player); + + hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), + Math.abs(hitVec.z - ((int) hitVec.z))); + + //Get blockstates + List itemStacks = new ArrayList<>(); + List blockStates = new ArrayList<>(); + if (breaking) { + //Find blockstate of world + for (BlockPos coordinate : newCoordinates) { + blockStates.add(player.level.getBlockState(coordinate)); + } + } else { + blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); + } + + + //Check if they are different from previous + //TODO fix triggering when moving player + if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) { + previousCoordinates = newCoordinates; + //remember the rest for placed blocks + previousBlockStates = blockStates; + previousItemStacks = itemStacks; + previousFirstPos = firstPos; + previousSecondPos = secondPos; + + //if so, renew randomness of randomizer bag + AbstractRandomizerBagItem.renewRandomness(); + //and play sound (max once every tick) + if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientEvents.ticksInGame - 0) { + soundTime = ClientEvents.ticksInGame; + + if (blockStates.get(0) != null) { + SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.level, + newCoordinates.get(0), player); + player.level.playSound(player, player.blockPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(), + SoundSource.BLOCKS, 0.3f, 0.8f); + } + } + } + + if (blockStates.size() == 0 || newCoordinates.size() != blockStates.size()) return; + + int blockCount; + + Object outlineID = firstPos; + //Dont fade out the outline if we are still determining where to place + //Every outline with same ID will not fade out (because it gets replaced) + if (newCoordinates.size() == 1 || BuildModifiers.isEnabled(modifierSettings, firstPos)) outlineID = "single"; + + if (!breaking) { + //Use fancy shader if config allows, otherwise outlines + if (ClientConfig.visuals.showBlockPreviews.get() && newCoordinates.size() < ClientConfig.visuals.maxBlockPreviews.get()) { + blockCount = renderBlockPreviews(player, modifierSettings, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking); + + CreateClient.OUTLINER.showCluster(outlineID, newCoordinates) + .withFaceTexture(AllSpecialTextures.CHECKERED) + .disableNormals() + .lineWidth(1 / 32f) + .colored(new Color(1f, 1f, 1f, 1f)); + } else { + //Thicker outline without block previews + CreateClient.OUTLINER.showCluster(outlineID, newCoordinates) + .withFaceTexture(AllSpecialTextures.HIGHLIGHT_CHECKERED) + .disableNormals() + .lineWidth(1 / 16f) + .colored(new Color(1f, 1f, 1f, 1f)); + + blockCount = newCoordinates.size(); + } + + } else { + //Breaking + CreateClient.OUTLINER.showCluster(outlineID, newCoordinates) + .withFaceTexture(AllSpecialTextures.THIN_CHECKERED) + .disableNormals() + .lineWidth(1 / 16f) + .colored(new Color(0.8f, 0.1f, 0.1f, 1f)); + blockCount = newCoordinates.size(); + } + + //Display block count and dimensions in actionbar + if (BuildModes.isActive(player)) { + + //Find min and max values (not simply firstPos and secondPos because that doesn't work with circles) + int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE; + int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE; + int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE; + for (BlockPos pos : startCoordinates) { + if (pos.getX() < minX) minX = pos.getX(); + if (pos.getX() > maxX) maxX = pos.getX(); + if (pos.getY() < minY) minY = pos.getY(); + if (pos.getY() > maxY) maxY = pos.getY(); + if (pos.getZ() < minZ) minZ = pos.getZ(); + if (pos.getZ() > maxZ) maxZ = pos.getZ(); + } + BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1); + + String dimensions = "("; + if (dim.getX() > 1) dimensions += dim.getX() + "x"; + if (dim.getZ() > 1) dimensions += dim.getZ() + "x"; + if (dim.getY() > 1) dimensions += dim.getY() + "x"; + dimensions = dimensions.substring(0, dimensions.length() - 1); + if (dimensions.length() > 1) dimensions += ")"; + + EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true); + } + } + + public static void drawOutlinesIfNoBlockInHand(Player player, HitResult lookingAt) { + //Draw outlines if no block in hand + //Find proper raytrace: either normal range or increased range depending on canBreakFar + HitResult objectMouseOver = Minecraft.getInstance().hitResult; + HitResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver; + + if (player.isCreative() && breakingRaytrace != null && breakingRaytrace.getType() == HitResult.Type.BLOCK) { + BlockHitResult blockBreakingRaytrace = (BlockHitResult) breakingRaytrace; + List breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getBlockPos()); + + //Only render first outline if further than normal reach + if (objectMouseOver != null && objectMouseOver.getType() == HitResult.Type.BLOCK) + breakCoordinates.remove(0); + + breakCoordinates.removeIf(pos -> { + BlockState blockState = player.level.getBlockState(pos); + if (blockState.isAir() || blockState.getMaterial().isLiquid()) return true; + return !SurvivalHelper.canBreak(player.level, player, pos); + }); + + if (!breakCoordinates.isEmpty()) { + CreateClient.OUTLINER.showCluster("break", breakCoordinates) + .disableNormals() + .lineWidth(1 / 64f) + .colored(0x222222); + } + } + } + + //Whether to draw any block previews or outlines + public static boolean doShowBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) { + if (!ClientConfig.visuals.showBlockPreviews.get()) return false; + return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.DISABLED || + (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) || + ClientConfig.visuals.alwaysShowBlockPreview.get(); + } + + protected static int renderBlockPreviews(Player player, ModifierSettings modifierSettings, List coordinates, + List blockStates, List itemStacks, float dissolve, + BlockPos firstPos, BlockPos secondPos, boolean checkCanPlace, boolean red) { + int blocksValid = 0; + + if (coordinates.isEmpty()) return blocksValid; + + for (int i = coordinates.size() - 1; i >= 0; i--) { + BlockPos blockPos = coordinates.get(i); + BlockState blockState = blockStates.get(i); + ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i); + if (CompatHelper.isItemBlockProxy(itemstack)) + itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); + + //Check if we can place + boolean canPlace = true; + if (checkCanPlace) { + canPlace = SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP); + } else { + //If check is turned off, check if blockstate is the same (for dissolve effect) + canPlace = player.level.getBlockState(blockPos) != blockState; + } + + if (canPlace) { + renderBlockPreview(blockPos, blockState, dissolve, firstPos, secondPos, red); + blocksValid++; + } + } + return blocksValid; + } + + protected static void renderBlockPreview(BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean breaking) { + if (blockState == null) return; + + float scale = 0.5f; + float alpha = 0.7f; + if (dissolve > 0f) { + float animationLength = 0.7f; + + double firstToSecond = secondPos.distSqr(firstPos); + double place = 0; + if (firstToSecond > 0.5) { + double placeFromFirst = firstPos.distSqr(blockPos) / firstToSecond; + double placeFromSecond = secondPos.distSqr(blockPos) / firstToSecond; + place = (placeFromFirst + (1.0 - placeFromSecond)) / 2.0; + } //else only one block + + //Scale place so we start first animation at 0 and end last animation at 1 + place *= 1f - animationLength; + float diff = dissolve - (float) place; + float t = diff / animationLength; + t = Mth.clamp(t, 0, 1); + //Now we got a usable t value for this block + + float sine = Mth.sin((t + (1/7f) * t) * Mth.TWO_PI - (3/4f) * Mth.PI); // -1 to 1 + sine = (sine + 1f) / 2f; // 0 to 1 + +// scale = 1f + (sine * 0.5f); + + t = (float) Mth.smoothstep(t); + if (!breaking) { + scale = 0.5f + (t * 0.3f); + alpha = 0.7f + (t * 0.3f); + } else { + t = 1f - t; + scale = 0.5f + (t * 0.5f); + alpha = t; + } + } + + CreateClient.GHOST_BLOCKS.showGhostState(blockPos.toShortString(), blockState) + .at(blockPos) + .alpha(alpha) + .scale(scale); + } + + public static void onBlocksPlaced() { + onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos); + } + + public static void onBlocksPlaced(List coordinates, List itemStacks, List blockStates, + BlockPos firstPos, BlockPos secondPos) { + LocalPlayer player = Minecraft.getInstance().player; + ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); + ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); + + //Check if block previews are enabled + if (doShowBlockPreviews(modifierSettings, modeSettings, firstPos)) { + + //Save current coordinates, blockstates and itemstacks + if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() && + coordinates.size() > 1 && coordinates.size() < ClientConfig.visuals.maxBlockPreviews.get()) { + + placedDataList.add(new PlacedData(ClientEvents.ticksInGame, coordinates, blockStates, + itemStacks, firstPos, secondPos, false)); + } + } + + } + + public static void onBlocksBroken() { + onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos); + } + + public static void onBlocksBroken(List coordinates, List itemStacks, List blockStates, + BlockPos firstPos, BlockPos secondPos) { + LocalPlayer player = Minecraft.getInstance().player; + ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); + ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); + + //Check if block previews are enabled + if (doShowBlockPreviews(modifierSettings, modeSettings, firstPos)) { + + //Save current coordinates, blockstates and itemstacks + if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() && + coordinates.size() > 1 && coordinates.size() < ClientConfig.visuals.maxBlockPreviews.get()) { + + sortOnDistanceToPlayer(coordinates, player); + + placedDataList.add(new PlacedData(ClientEvents.ticksInGame, coordinates, blockStates, + itemStacks, firstPos, secondPos, true)); + } + } + + } + + private static void sortOnDistanceToPlayer(List coordinates, Player player) { + + Collections.sort(coordinates, (lhs, rhs) -> { + // -1 - less than, 1 - greater than, 0 - equal + double lhsDistanceToPlayer = Vec3.atLowerCornerOf(lhs).subtract(player.getEyePosition(1f)).lengthSqr(); + double rhsDistanceToPlayer = Vec3.atLowerCornerOf(rhs).subtract(player.getEyePosition(1f)).lengthSqr(); + return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer); + }); + + } + + static class PlacedData { + float time; + List coordinates; + List blockStates; + List itemStacks; + BlockPos firstPos; + BlockPos secondPos; + boolean breaking; + + public PlacedData(float time, List coordinates, List blockStates, + List itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) { + this.time = time; + this.coordinates = coordinates; + this.blockStates = blockStates; + this.itemStacks = itemStacks; + this.firstPos = firstPos; + this.secondPos = secondPos; + this.breaking = breaking; + } + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java b/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java index 0f2e5e6..65c5668 100644 --- a/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java +++ b/src/main/java/nl/requios/effortlessbuilding/render/RenderHandler.java @@ -5,32 +5,25 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.Tesselator; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.Sheets; -import net.minecraft.client.renderer.block.BlockRenderDispatcher; -import net.minecraft.client.renderer.texture.OverlayTexture; -import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.client.event.RenderLevelLastEvent; import net.minecraftforge.client.event.RenderLevelStageEvent; -import net.minecraftforge.client.model.data.ModelData; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod.EventBusSubscriber; -import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.ClientEvents; +import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; -import nl.requios.effortlessbuilding.create.CreateClient; -import nl.requios.effortlessbuilding.create.events.ClientEvents; +import nl.requios.effortlessbuilding.compatibility.CompatHelper; +import nl.requios.effortlessbuilding.helper.SurvivalHelper; /*** * Main render class for Effortless Building @@ -40,26 +33,64 @@ public class RenderHandler { @SubscribeEvent public static void onTick(TickEvent.ClientTickEvent event) { - if (!ClientEvents.isGameActive()) return; + if (!nl.requios.effortlessbuilding.create.events.ClientEvents.isGameActive()) return; - Player player = Minecraft.getInstance().player; - ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); - ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); + var player = Minecraft.getInstance().player; + var modeSettings = ModeSettingsManager.getModeSettings(player); + var modifierSettings = ModifierSettingsManager.getModifierSettings(player); - BlockPreviewRenderer.render(null, null, player, modifierSettings, modeSettings); + BlockPreviews.drawPlacedBlocks(player, modifierSettings); + + + HitResult lookingAt = ClientEvents.getLookingAt(player); + if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.DISABLED) + lookingAt = Minecraft.getInstance().hitResult; + + ItemStack mainhand = player.getMainHandItem(); + boolean noBlockInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand)); + + //Find start position, side hit and hit vector + BlockPos startPos = null; + Direction sideHit = null; + Vec3 hitVec = null; + + //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) + if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) { + BlockHitResult blockLookingAt = (BlockHitResult) lookingAt; + startPos = blockLookingAt.getBlockPos(); + + //Check if tool (or none) in hand + boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable(); + boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, blockLookingAt.getDirection()); + if (!modifierSettings.doQuickReplace() && !noBlockInHand && !replaceable && !becomesDoubleSlab) { + startPos = startPos.relative(blockLookingAt.getDirection()); + } + + //Get under tall grass and other replaceable blocks + if (modifierSettings.doQuickReplace() && !noBlockInHand && replaceable) { + startPos = startPos.below(); + } + + sideHit = blockLookingAt.getDirection(); + hitVec = blockLookingAt.getLocation(); + } + + + BlockPreviews.drawLookAtPreview(player, modeSettings, modifierSettings, startPos, sideHit, hitVec); + + if (noBlockInHand) BlockPreviews.drawOutlinesIfNoBlockInHand(player, lookingAt); } @SubscribeEvent - public static void onRender(RenderLevelLastEvent event) { + public static void onRender(RenderLevelStageEvent event) { + if (event.getStage() != RenderLevelStageEvent.Stage.AFTER_TRANSLUCENT_BLOCKS) return; + Vec3 cameraPos = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition(); -// float pt = AnimationTickHolder.getPartialTicks(); PoseStack ms = event.getPoseStack(); BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder(); MultiBufferSource.BufferSource buffer = MultiBufferSource.immediate(bufferBuilder); -// SuperRenderTypeBuffer superBuffer = SuperRenderTypeBuffer.getInstance(); - Player player = Minecraft.getInstance().player; ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); @@ -70,15 +101,6 @@ public class RenderHandler { //Mirror and radial mirror lines and areas ModifierRenderer.render(ms, buffer, modifierSettings); - //Render block previews - BlockPreviewRenderer.render(ms, buffer, player, modifierSettings, modeSettings); - - //Create -// CreateClient.GHOST_BLOCKS.renderAll(ms, superBuffer); -// EffortlessBuildingClient.OUTLINER.renderOutlines(ms, superBuffer, pt); -// superBuffer.draw(); -// RenderSystem.enableCull(); - ms.popPose(); } @@ -98,82 +120,4 @@ public class RenderHandler { renderTypeBuffer.endBatch(); } - protected static void renderBlockPreview(PoseStack ms, MultiBufferSource.BufferSource buffer, BlockRenderDispatcher dispatcher, - BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean red) { - if (blockState == null) return; - - CreateClient.GHOST_BLOCKS.showGhostState(blockPos.toShortString(), blockState) -// .breathingAlpha() - .alpha(0.7f) - .at(blockPos); - -// ms.pushPose(); -// ms.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ()); -//// ms.rotate(Vector3f.YP.rotationDegrees(-90f)); -// ms.translate(-0.01f, -0.01f, -0.01f); -// ms.scale(1.02f, 1.02f, 1.02f); -// -// //Begin block preview rendering -// RenderType blockPreviewRenderType = BuildRenderTypes.getBlockPreviewRenderType(dissolve, blockPos, firstPos, secondPos, red); -// VertexConsumer vc = buffer.getBuffer(blockPreviewRenderType); -// -// try { -// BakedModel model = dispatcher.getBlockModel(blockState); -// dispatcher.getModelRenderer().renderModel(ms.last(), vc, blockState, model, -// 1f, 1f, 1f, 0, OverlayTexture.NO_OVERLAY, ModelData.EMPTY, blockPreviewRenderType); -// } catch (NullPointerException e) { -// EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString()); -// -// //Render outline as backup, escape out of the current renderstack -// ms.popPose(); -// buffer.endBatch(); -// VertexConsumer lineBuffer = beginLines(buffer); -// renderBlockOutline(ms, lineBuffer, blockPos, new Vec3(1f, 1f, 1f)); -// endLines(buffer); -// vc = buffer.getBuffer(Sheets.translucentCullBlockSheet()); //any type will do, as long as we have something on the stack -// ms.pushPose(); -// } -// -// buffer.endBatch(); -// ms.popPose(); - } - - protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, Vec3 color) { - renderBlockOutline(matrixStack, buffer, pos, pos, color); - } - - //Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z - protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos1, BlockPos pos2, Vec3 color) { - AABB aabb = new AABB(pos1, pos2.offset(1, 1, 1)).inflate(0.0020000000949949026); - - LevelRenderer.renderLineBox(matrixStack, buffer, aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f); -// WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f); - } - - //Renders outline with given bounding box - protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, VoxelShape collisionShape, Vec3 color) { -// WorldRenderer.drawShape(collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f); - LevelRenderer.renderVoxelShape(matrixStack, buffer, collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f); - } - - //TODO - //Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken -// @Override -// public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { -// Minecraft mc = Minecraft.getInstance(); -// -// ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); -// if (!BuildModifiers.isEnabled(modifierSettings, pos)) return; -// -// List coordinates = BuildModifiers.findCoordinates(mc.player, pos); -// for (int i = 1; i < coordinates.size(); i++) { -// BlockPos coordinate = coordinates.get(i); -// if (SurvivalHelper.canBreak(mc.world, mc.player, coordinate)) { -// //Send i as entity id because only one block can be broken per id -// //Unless i happens to be the player id, then take something else -// int fakeId = mc.player.getEntityId() != i ? i : coordinates.size(); -// mc.renderGlobal.sendBlockBreakProgress(fakeId, coordinate, progress); -// } -// } -// } } diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/normal.png b/src/main/resources/assets/effortlessbuilding/textures/icons/disabled.png similarity index 100% rename from src/main/resources/assets/effortlessbuilding/textures/icons/normal.png rename to src/main/resources/assets/effortlessbuilding/textures/icons/disabled.png diff --git a/src/main/resources/assets/effortlessbuilding/textures/icons/normal_plus.png b/src/main/resources/assets/effortlessbuilding/textures/icons/single.png similarity index 100% rename from src/main/resources/assets/effortlessbuilding/textures/icons/normal_plus.png rename to src/main/resources/assets/effortlessbuilding/textures/icons/single.png