From cd3afbbb82f09b56dc0be45788970c8180317138 Mon Sep 17 00:00:00 2001 From: Christian Knaapen Date: Tue, 17 Jan 2023 02:30:08 +0100 Subject: [PATCH] Overhauled block previews to work with ticks. Added place and break animation. Added DelayedBlockPlacer to play appear animation, then place. Split BuildConfig into CommonConfig and ClientConfig. Fixed itemstack not found error in creative. Added scale and color options to ghost blocks. --- .../effortlessbuilding/ClientConfig.java | 36 ++ .../effortlessbuilding/ClientEvents.java | 6 +- .../{BuildConfig.java => CommonConfig.java} | 37 +- .../effortlessbuilding/CommonEvents.java | 14 +- .../EffortlessBuilding.java | 6 +- .../buildmode/BuildModes.java | 9 +- .../buildmode/ModeSettingsManager.java | 2 +- .../{NormalPlus.java => Disabled.java} | 2 +- .../buildmodes/{Normal.java => Single.java} | 2 +- .../buildmodifier/BuildModifiers.java | 57 +-- .../ModifierSettingsManager.java | 10 +- .../buildmodifier/UndoRedo.java | 12 +- .../capability/ModeCapabilityManager.java | 2 +- .../utility/ghost/GhostBlockParams.java | 33 ++ .../utility/ghost/GhostBlockRenderer.java | 19 +- .../foundation/utility/ghost/GhostBlocks.java | 7 + .../helper/DelayedBlockPlacer.java | 108 +++++ .../helper/ReachHelper.java | 16 +- .../helper/SurvivalHelper.java | 36 +- .../item/AbstractRandomizerBagItem.java | 2 +- .../item/ReachUpgrade1Item.java | 4 +- .../item/ReachUpgrade2Item.java | 5 +- .../item/ReachUpgrade3Item.java | 4 +- .../network/AddUndoMessage.java | 1 - .../network/BlockPlacedMessage.java | 4 +- .../network/ClearUndoMessage.java | 1 - .../network/RequestLookAtMessage.java | 2 - .../render/BlockPreviewRenderer.java | 412 ----------------- .../render/BlockPreviews.java | 414 ++++++++++++++++++ .../render/RenderHandler.java | 166 +++---- .../icons/{normal.png => disabled.png} | Bin .../icons/{normal_plus.png => single.png} | Bin 32 files changed, 761 insertions(+), 668 deletions(-) create mode 100644 src/main/java/nl/requios/effortlessbuilding/ClientConfig.java rename src/main/java/nl/requios/effortlessbuilding/{BuildConfig.java => CommonConfig.java} (74%) rename src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/{NormalPlus.java => Disabled.java} (95%) rename src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/{Normal.java => Single.java} (95%) create mode 100644 src/main/java/nl/requios/effortlessbuilding/helper/DelayedBlockPlacer.java delete mode 100644 src/main/java/nl/requios/effortlessbuilding/render/BlockPreviewRenderer.java create mode 100644 src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java rename src/main/resources/assets/effortlessbuilding/textures/icons/{normal.png => disabled.png} (100%) rename src/main/resources/assets/effortlessbuilding/textures/icons/{normal_plus.png => single.png} (100%) 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