From 617fc8211479e2421cc58d942f24d11166b30e82 Mon Sep 17 00:00:00 2001 From: Christian Knaapen Date: Sat, 21 Jan 2023 01:41:00 +0100 Subject: [PATCH] Overhaul continues. Updated build modes, determining blockstates. Everything compiles and runs. --- .../effortlessbuilding/ClientEvents.java | 2 +- .../buildmode/BaseBuildMode.java | 10 - .../buildmode/IBuildMode.java | 17 +- .../buildmode/ThreeClicksBuildMode.java | 116 ++++--- .../buildmode/TwoClicksBuildMode.java | 55 ++-- .../buildmode/buildmodes/Disabled.java | 26 +- .../buildmode/buildmodes/Single.java | 26 +- .../compatibility/CompatHelper.java | 8 +- .../network/ServerPlaceBlocksMessage.java | 2 +- .../render/BlockPreviews.java | 285 +++++++++--------- .../systems/BuilderChain.java | 68 ++++- .../systems/ServerBlockPlacer.java | 4 + .../utilities/BlockEntry.java | 23 +- 13 files changed, 324 insertions(+), 318 deletions(-) diff --git a/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java b/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java index 804c4da..4e0714c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java +++ b/src/main/java/nl/requios/effortlessbuilding/ClientEvents.java @@ -263,7 +263,7 @@ public class ClientEvents { public static boolean isKeybindDown(int keybindIndex) { return InputConstants.isKeyDown( Minecraft.getInstance().getWindow().getWindow(), - keyBindings[2].getKey().getValue()); + keyBindings[keybindIndex].getKey().getValue()); } public static BlockHitResult getLookingAt(Player player) { diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/BaseBuildMode.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/BaseBuildMode.java index feb2f82..77490d2 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/BaseBuildMode.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/BaseBuildMode.java @@ -22,14 +22,4 @@ public abstract class BaseBuildMode implements IBuildMode { clicks++; return false; } - - @Override @Deprecated - public Direction getSideHit(Player player) { - return Direction.UP; - } - - @Override @Deprecated - public Vec3 getHitVec(Player player) { - return new Vec3(0.5, 0.5, 0.5); - } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java index 0d25f07..51e41d7 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/IBuildMode.java @@ -10,26 +10,11 @@ import java.util.List; public interface IBuildMode { - //Fired when a player selects a buildmode and when it needs to initializeMode + //Reset values here, start over void initialize(); - //Fired when a block would be placed - //Return a list of coordinates where you want to place blocks - @Deprecated - List onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace); - //Returns if we should place blocks now boolean onClick(List blocks); - //Fired continuously for visualization purposes - @Deprecated - List findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace); - void findCoordinates(List blocks); - - @Deprecated - Direction getSideHit(Player player); - - @Deprecated - Vec3 getHitVec(Player player); } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/ThreeClicksBuildMode.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/ThreeClicksBuildMode.java index 0208d31..7f923b1 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/ThreeClicksBuildMode.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/ThreeClicksBuildMode.java @@ -1,81 +1,73 @@ package nl.requios.effortlessbuilding.buildmode; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.core.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; +import nl.requios.effortlessbuilding.utilities.BlockEntry; import nl.requios.effortlessbuilding.utilities.ReachHelper; import java.util.*; public abstract class ThreeClicksBuildMode extends BaseBuildMode { - protected Dictionary secondPosTable = new Hashtable<>(); + protected BlockEntry firstBlockEntry; + protected BlockEntry secondBlockEntry; //Finds height after floor has been chosen in buildmodes with 3 clicks @Override - public void initialize(Player player) { - super.initialize(player); - secondPosTable.put(player.getUUID(), BlockPos.ZERO); + public void initialize() { + super.initialize(); + firstBlockEntry = null; + secondBlockEntry = null; } @Override - public List onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) { - List list = new ArrayList<>(); - - Dictionary rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable; - int rightClickNr = rightClickTable.get(player.getUUID()); - rightClickNr++; - rightClickTable.put(player.getUUID(), rightClickNr); - - if (rightClickNr == 1) { - //If clicking in air, reset and try again - if (blockPos == null) { - rightClickTable.put(player.getUUID(), 0); - return list; - } + public boolean onClick(List blocks) { + super.onClick(blocks); + if (clicks == 1) { //First click, remember starting position - firstPosTable.put(player.getUUID(), blockPos); - sideHitTable.put(player.getUUID(), sideHit); - hitVecTable.put(player.getUUID(), hitVec); - //Keep list empty, dont place any blocks yet - } else if (rightClickNr == 2) { - //Second click, find other floor point - BlockPos firstPos = firstPosTable.get(player.getUUID()); - BlockPos secondPos = findSecondPos(player, firstPos, true); - if (secondPos == null) { - rightClickTable.put(player.getUUID(), 1); - return list; + //If clicking in air, reset and try again + if (blocks.size() == 0) { + clicks = 0; + return false; } - secondPosTable.put(player.getUUID(), secondPos); + firstBlockEntry = blocks.get(0); + } else if (clicks == 2) { + //Second click, find second position + //If clicking in air, reset and try again + if (blocks.size() == 0) { + clicks = 0; + return false; + } + + var player = Minecraft.getInstance().player; + var secondPos = findSecondPos(player, firstBlockEntry.blockPos, true); + secondBlockEntry = new BlockEntry(secondPos); } else { - //Third click, place diagonal wall with height - list = findCoordinates(player, blockPos, skipRaytrace); - rightClickTable.put(player.getUUID(), 0); + //Third click, place blocks + clicks = 0; + return true; } - - return list; + return false; } @Override - public List findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) { - List list = new ArrayList<>(); - Dictionary rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable; - int rightClickNr = rightClickTable.get(player.getUUID()); + public void findCoordinates(List blocks) { + if (clicks == 0) return; - if (rightClickNr == 0) { - if (blockPos != null) - list.add(blockPos); - } else if (rightClickNr == 1) { - BlockPos firstPos = firstPosTable.get(player.getUUID()); + if (clicks == 1) { + var player = Minecraft.getInstance().player; + var firstPos = firstBlockEntry.blockPos; + var secondPos = findSecondPos(player, firstBlockEntry.blockPos, true); + if (secondPos == null) return; - BlockPos secondPos = findSecondPos(player, firstPos, true); - if (secondPos == null) return list; - - //Limit amount of blocks you can place per row + //Limit amount of blocks we can place per row int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); int x1 = firstPos.getX(), x2 = secondPos.getX(); @@ -90,15 +82,16 @@ public abstract class ThreeClicksBuildMode extends BaseBuildMode { if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; - //Add diagonal line from first to second - list.addAll(getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2)); - + blocks.clear(); + for (BlockPos pos : getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2)) { + blocks.add(new BlockEntry(pos)); + } } else { - BlockPos firstPos = firstPosTable.get(player.getUUID()); - BlockPos secondPos = secondPosTable.get(player.getUUID()); - - BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, skipRaytrace); - if (thirdPos == null) return list; + var player = Minecraft.getInstance().player; + BlockPos firstPos = firstBlockEntry.blockPos; + BlockPos secondPos = secondBlockEntry.blockPos; + BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, true); + if (thirdPos == null) return; //Limit amount of blocks you can place per row int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); @@ -122,11 +115,11 @@ public abstract class ThreeClicksBuildMode extends BaseBuildMode { if (z3 - z1 >= axisLimit) z3 = z1 + axisLimit - 1; if (z1 - z3 >= axisLimit) z3 = z1 - axisLimit + 1; - //Add diagonal line from first to third - list.addAll(getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3)); + blocks.clear(); + for (BlockPos pos : getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3)) { + blocks.add(new BlockEntry(pos)); + } } - - return list; } public static BlockPos findHeight(Player player, BlockPos secondPos, boolean skipRaytrace) { @@ -172,7 +165,10 @@ public abstract class ThreeClicksBuildMode extends BaseBuildMode { return new BlockPos(selected.lineBound); } +// protected abstract BlockEntry findSecondPos(List blocks); + //Finds the place of the second block pos +// @Deprecated protected abstract BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace); //Finds the place of the third block pos diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/TwoClicksBuildMode.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/TwoClicksBuildMode.java index 3e5f366..eab1c81 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/TwoClicksBuildMode.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/TwoClicksBuildMode.java @@ -1,5 +1,7 @@ package nl.requios.effortlessbuilding.buildmode; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.core.Direction; import net.minecraft.core.BlockPos; @@ -16,6 +18,12 @@ public abstract class TwoClicksBuildMode extends BaseBuildMode { protected BlockEntry firstBlockEntry; + @Override + public void initialize() { + super.initialize(); + firstBlockEntry = null; + } + @Override public boolean onClick(List blocks) { super.onClick(blocks); @@ -39,38 +47,33 @@ public abstract class TwoClicksBuildMode extends BaseBuildMode { } @Override - public List findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) { - List list = new ArrayList<>(); - Dictionary rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable; - int rightClickNr = rightClickTable.get(player.getUUID()); - BlockPos firstPos = firstPosTable.get(player.getUUID()); + public void findCoordinates(List blocks) { + if (clicks == 0) return; - if (rightClickNr == 0) { - if (blockPos != null) - list.add(blockPos); - } else { - BlockPos secondPos = findSecondPos(player, firstPos, skipRaytrace); - if (secondPos == null) return list; + var player = Minecraft.getInstance().player; + var firstPos = firstBlockEntry.blockPos; + var secondPos = findSecondPos(player, firstBlockEntry.blockPos, true); + if (secondPos == null) return; - //Limit amount of blocks we can place per row - int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); + //Limit amount of blocks we can place per row + int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); - int x1 = firstPos.getX(), x2 = secondPos.getX(); - int y1 = firstPos.getY(), y2 = secondPos.getY(); - int z1 = firstPos.getZ(), z2 = secondPos.getZ(); + int x1 = firstPos.getX(), x2 = secondPos.getX(); + int y1 = firstPos.getY(), y2 = secondPos.getY(); + int z1 = firstPos.getZ(), z2 = secondPos.getZ(); - //limit axis - if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; - if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; - if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1; - if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1; - if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; - if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; + //limit axis + if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; + if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; + if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1; + if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1; + if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; + if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; - list.addAll(getAllBlocks(player, x1, y1, z1, x2, y2, z2)); + blocks.clear(); + for (BlockPos pos : getAllBlocks(player, x1, y1, z1, x2, y2, z2)) { + blocks.add(new BlockEntry(pos)); } - - return list; } //Finds the place of the second block pos based on criteria (floor must be on same height as first click, wall on same plane etc) diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java index 5ffee68..70cfbc0 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Disabled.java @@ -5,37 +5,25 @@ import net.minecraft.core.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; import nl.requios.effortlessbuilding.buildmode.IBuildMode; +import nl.requios.effortlessbuilding.utilities.BlockEntry; import java.util.ArrayList; import java.util.List; public class Disabled implements IBuildMode { + @Override - public void initialize(Player player) { + public void initialize() { } @Override - public List onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) { - List list = new ArrayList<>(); - if (blockPos != null) list.add(blockPos); - return list; + public boolean onClick(List blocks) { + return true; } @Override - public List findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) { - List list = new ArrayList<>(); - if (blockPos != null) list.add(blockPos); - return list; - } - - @Override - public Direction getSideHit(Player player) { - return null; - } - - @Override - public Vec3 getHitVec(Player player) { - return null; + public void findCoordinates(List blocks) { + //Do nothing } } diff --git a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java index e68b6f7..7752bf1 100644 --- a/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java +++ b/src/main/java/nl/requios/effortlessbuilding/buildmode/buildmodes/Single.java @@ -5,37 +5,25 @@ import net.minecraft.core.Direction; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.Vec3; import nl.requios.effortlessbuilding.buildmode.IBuildMode; +import nl.requios.effortlessbuilding.utilities.BlockEntry; import java.util.ArrayList; import java.util.List; public class Single implements IBuildMode { + @Override - public void initialize(Player player) { + public void initialize() { } @Override - public List onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) { - List list = new ArrayList<>(); - if (blockPos != null) list.add(blockPos); - return list; + public boolean onClick(List blocks) { + return true; } @Override - public List findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) { - List list = new ArrayList<>(); - if (blockPos != null) list.add(blockPos); - return list; - } - - @Override - public Direction getSideHit(Player player) { - return null; - } - - @Override - public Vec3 getHitVec(Player player) { - return null; + public void findCoordinates(List blocks) { + //Do nothing } } diff --git a/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java b/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java index e8ec96e..51ec9bf 100644 --- a/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java +++ b/src/main/java/nl/requios/effortlessbuilding/compatibility/CompatHelper.java @@ -13,12 +13,16 @@ public class CompatHelper { } + public static boolean isItemBlockProxy(ItemStack stack) { + return isItemBlockProxy(stack, true); + } + // Check if the item given is a proxy for blocks. For now, we check for the randomizer bag, // /dank/null, or plain old blocks. - public static boolean isItemBlockProxy(ItemStack stack) { + public static boolean isItemBlockProxy(ItemStack stack, boolean seeBlockItemsAsProxies) { Item item = stack.getItem(); if (item instanceof BlockItem) - return true; + return seeBlockItemsAsProxies; return item instanceof AbstractRandomizerBagItem; } diff --git a/src/main/java/nl/requios/effortlessbuilding/network/ServerPlaceBlocksMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/ServerPlaceBlocksMessage.java index e085214..c134868 100644 --- a/src/main/java/nl/requios/effortlessbuilding/network/ServerPlaceBlocksMessage.java +++ b/src/main/java/nl/requios/effortlessbuilding/network/ServerPlaceBlocksMessage.java @@ -30,7 +30,7 @@ public class ServerPlaceBlocksMessage { public static ServerPlaceBlocksMessage decode(FriendlyByteBuf buf) { ServerPlaceBlocksMessage message = new ServerPlaceBlocksMessage(); message.blocks = buf.readList(BlockEntry::decode); - return new ServerPlaceBlocksMessage(); + return message; } diff --git a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java index 7f73c72..573ab6c 100644 --- a/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java +++ b/src/main/java/nl/requios/effortlessbuilding/render/BlockPreviews.java @@ -21,6 +21,7 @@ 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.buildmodifier.BuildModifiers; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; @@ -71,148 +72,148 @@ public class BlockPreviews { } 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); - } +// 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) { diff --git a/src/main/java/nl/requios/effortlessbuilding/systems/BuilderChain.java b/src/main/java/nl/requios/effortlessbuilding/systems/BuilderChain.java index 11cd076..8ec9865 100644 --- a/src/main/java/nl/requios/effortlessbuilding/systems/BuilderChain.java +++ b/src/main/java/nl/requios/effortlessbuilding/systems/BuilderChain.java @@ -2,10 +2,14 @@ package nl.requios.effortlessbuilding.systems; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; @@ -45,20 +49,29 @@ public class BuilderChain { public void onRightClick() { + var player = Minecraft.getInstance().player; + if (state == State.BREAKING) { cancel(); return; } + //Check if we have a BlockItem in hand + var itemStack = player.getItemInHand(InteractionHand.MAIN_HAND); + boolean blockInHand = CompatHelper.isItemBlockProxy(itemStack); + if (!blockInHand) { + if (state == State.PLACING) cancel(); + return; + } + if (state == State.IDLE) { state = State.PLACING; } - var player = Minecraft.getInstance().player; var buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); //Find out if we should place blocks now - if (buildMode.instance.onClick()) { + if (buildMode.instance.onClick(blocks)) { state = State.IDLE; PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksMessage(blocks)); } @@ -76,12 +89,15 @@ public class BuilderChain { if (state == State.IDLE){ state = State.BREAKING; + + //Recalculate block positions, because start position has changed + onTick(); } var buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); //Find out if we should break blocks now - if (buildMode.instance.onClick()) { + if (buildMode.instance.onClick(blocks)) { state = State.IDLE; PacketHandler.INSTANCE.sendToServer(new ServerPlaceBlocksMessage(blocks)); } @@ -115,8 +131,23 @@ public class BuilderChain { EffortlessBuildingClient.BUILD_MODES.findCoordinates(blocks, player, buildMode); EffortlessBuildingClient.BUILD_MODIFIERS.findCoordinates(blocks, player, modifierSettings); - if (state == State.PLACING) { - //TODO find block states + if (blockInHand && state != State.BREAKING) { + //find block states + + if (itemStack.getItem() instanceof BlockItem) { + + for (BlockEntry blockEntry : blocks) { + blockEntry.blockState = getBlockState(player, InteractionHand.MAIN_HAND, itemStack, blockEntry); + } + + } else if (CompatHelper.isItemBlockProxy(itemStack, false)) { + + for (BlockEntry blockEntry : blocks) { + ItemStack itemBlockStack = CompatHelper.getItemBlockFromStack(itemStack); + if (itemBlockStack == null || itemBlockStack.isEmpty()) continue; + blockEntry.blockState = getBlockState(player, InteractionHand.MAIN_HAND, itemBlockStack, blockEntry); + } + } } } @@ -136,16 +167,18 @@ public class BuilderChain { int maxReach = ReachHelper.getMaxReach(player); if (player.blockPosition().distSqr(startPos) > maxReach * maxReach) return null; - //Offset in direction of sidehit if not quickreplace and not replaceable - boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable(); - boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos); - if (!doingQuickReplace && !replaceable && !becomesDoubleSlab) { - startPos = startPos.relative(lookingAt.getDirection()); - } + if (state != State.BREAKING) { + //Offset in direction of sidehit if not quickreplace and not replaceable + boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable(); + boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos); + if (!doingQuickReplace && !replaceable && !becomesDoubleSlab) { + startPos = startPos.relative(lookingAt.getDirection()); + } - //Get under tall grass and other replaceable blocks - if (doingQuickReplace && replaceable) { - startPos = startPos.below(); + //Get under tall grass and other replaceable blocks + if (doingQuickReplace && replaceable) { + startPos = startPos.below(); + } } var blockEntry = new BlockEntry(startPos); @@ -161,6 +194,13 @@ public class BuilderChain { return blockEntry; } + public BlockState getBlockState(Player player, InteractionHand hand, ItemStack blockItemStack, BlockEntry blockEntry) { + Block block = Block.byItem(blockItemStack.getItem()); + //TODO convert lookingAt hitvec to relative hitvec + var blockHitResult = new BlockHitResult(Vec3.ZERO, Direction.UP, blockEntry.blockPos, false); + return block.getStateForPlacement(new BlockPlaceContext(player, hand, blockItemStack, blockHitResult)); + } + private void playPlacingSoundIfFurtherThanNormal(Player player, Vec3 location, BlockItem blockItem) { if ((location.subtract(player.getEyePosition(1f))).lengthSqr() > 25f) { diff --git a/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java b/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java index cc591af..ee0d7c3 100644 --- a/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java +++ b/src/main/java/nl/requios/effortlessbuilding/systems/ServerBlockPlacer.java @@ -7,6 +7,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; +import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.utilities.BlockEntry; import java.util.List; @@ -15,6 +16,8 @@ import java.util.List; public class ServerBlockPlacer { public void placeBlocks(Player player, List blocks) { + EffortlessBuilding.log(player, "Placing " + blocks.size() + " blocks"); + for (BlockEntry block : blocks) { placeBlock(player, block); } @@ -26,6 +29,7 @@ public class ServerBlockPlacer { if (block.meansBreakBlock()) { breakBlock(player, block.blockPos); + return; } boolean success = world.setBlock(block.blockPos, block.blockState, 3); diff --git a/src/main/java/nl/requios/effortlessbuilding/utilities/BlockEntry.java b/src/main/java/nl/requios/effortlessbuilding/utilities/BlockEntry.java index 54d2804..c24a6d9 100644 --- a/src/main/java/nl/requios/effortlessbuilding/utilities/BlockEntry.java +++ b/src/main/java/nl/requios/effortlessbuilding/utilities/BlockEntry.java @@ -4,6 +4,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.nbt.NbtUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.state.BlockState; import java.util.BitSet; @@ -13,12 +14,18 @@ public class BlockEntry { public boolean mirrorX; public boolean mirrorY; public boolean mirrorZ; + public Rotation rotation; public BlockState blockState; + public ItemStack itemStack = ItemStack.EMPTY; public BlockEntry(BlockPos blockPos) { this.blockPos = blockPos; } + public boolean meansBreakBlock() { + return blockState == null || blockState.isAir(); + } + public BitSet getMirrorBitSet() { BitSet bitSet = new BitSet(3); bitSet.set(0, mirrorX); @@ -33,20 +40,20 @@ public class BlockEntry { mirrorZ = bitSet.get(2); } - public boolean meansBreakBlock() { - return blockState == null || blockState.isAir(); - } - public static void encode(FriendlyByteBuf buf, BlockEntry block) { buf.writeBlockPos(block.blockPos); - buf.writeBitSet(block.getMirrorBitSet()); - buf.writeNbt(NbtUtils.writeBlockState(block.blockState)); + buf.writeNullable(block.blockState, (buffer, blockState) -> buffer.writeNbt(NbtUtils.writeBlockState(blockState))); + buf.writeItem(block.itemStack); } public static BlockEntry decode(FriendlyByteBuf buf) { BlockEntry block = new BlockEntry(buf.readBlockPos()); - block.setMirrorBitSet(buf.readBitSet()); - block.blockState = NbtUtils.readBlockState(buf.readNbt()); + block.blockState = buf.readNullable(buffer -> { + var nbt = buf.readNbt(); + if (nbt == null) return null; + return NbtUtils.readBlockState(nbt); + }); + block.itemStack = buf.readItem(); return block; }