From cd0f6fea08ea60168579e51c330731d1307fabb9 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Tue, 17 Feb 2026 18:26:25 +0100 Subject: [PATCH 1/9] architects wand builds with off hand blocks --- dependencies.gradle | 2 + .../common/items/ItemArchitectsWand.java | 21 ++++++--- .../utilitiesinexcess/compat/Mods.java | 3 +- .../utils/ArchitectsWandUtils.java | 43 ++++++++++++++----- 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 4f9733dc..6eda82b3 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -45,12 +45,14 @@ dependencies { compileOnly('com.github.GTNewHorizons:Angelica:1.0.0-beta68a:dev') compileOnly("com.github.GTNewHorizons:FindIt:1.4.0:dev") compileOnly('com.github.GTNewHorizons:TinkersConstruct:1.14.14-GTNH:dev') + compileOnly("com.github.GTNewHorizons:Backhand:1.8.2:dev") devOnlyNonPublishable("com.github.GTNewHorizons:Baubles-Expanded:2.2.4-GTNH:dev") devOnlyNonPublishable("io.github.legacymoddingmc:unimixins:0.1.23:dev") runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.8.40-GTNH:dev") + runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev") // For testing NBT data (/nbtedit) // runtimeOnlyNonPublishable("com.github.GTNewHorizons:ServerUtilities:2.2.6:dev") diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java index 21ae871a..c78037df 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java @@ -1,6 +1,7 @@ package com.fouristhenumber.utilitiesinexcess.common.items; import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils.getItemStackToPlace; +import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils.getPatternBlock; import java.util.List; import java.util.Set; @@ -85,7 +86,9 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool } // 4. Target block to place - ItemStack itemStackToPlace = getItemStackToPlace(world, target, movingObjectPosition, player); + // TODO + ItemStack patternBlock = getPatternBlock(world, target, movingObjectPosition, player); + ItemStack itemStackToPlace = getItemStackToPlace(player, patternBlock); if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) { WireframeRenderer.clearCandidatePositions(); return; @@ -95,8 +98,15 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool int placeCount = player.capabilities.isCreativeMode ? this.buildLimit : Math.min(ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace), this.buildLimit); - Set blocksToPlace = ArchitectsWandUtils - .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, movingObjectPosition, player); + Set blocksToPlace = ArchitectsWandUtils.findAdjacentBlocks( + world, + itemStackToPlace, + placeCount, + forgeSide, + target, + movingObjectPosition, + player, + patternBlock); WireframeRenderer.clearCandidatePositions(); for (BlockPos pos : blocksToPlace) { WireframeRenderer.addCandidatePosition(pos.offset(forgeSide.offsetX, forgeSide.offsetY, forgeSide.offsetZ)); @@ -116,7 +126,8 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, BlockPos target = new BlockPos(x, y, z); MovingObjectPosition mop = new MovingObjectPosition(x, y, z, side, Vec3.createVectorHelper(hitX, hitY, hitZ)); - ItemStack itemStackToPlace = getItemStackToPlace(world, target, mop, player); + ItemStack patternBlock = getPatternBlock(world, target, mop, player); + ItemStack itemStackToPlace = getItemStackToPlace(player, patternBlock); if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) return false; // This block is here because some mods want to use TEs to @@ -132,7 +143,7 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, : Math.min(inventoryBlockCount, this.buildLimit); Set blocksToPlace = ArchitectsWandUtils - .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player); + .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player, patternBlock); itemStackToPlace.stackSize = blocksToPlace.size(); // Since now, we actually create a stack we have to set the // size. Strange kinda... diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java index 6d9235cc..6bdd06b7 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java @@ -13,7 +13,8 @@ public enum Mods { NEI("NotEnoughItems"), CraftTweaker("MineTweaker3"), FindIt("findit"), - Tinkers("TConstruct") + Tinkers("TConstruct"), + Backhand("backhand") ; // spotless:on diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java index dde01397..13ff5317 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java @@ -9,16 +9,22 @@ import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import com.fouristhenumber.utilitiesinexcess.compat.Mods; import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; +import xonin.backhand.api.core.BackhandUtils; + public class ArchitectsWandUtils { - public ArchitectsWandUtils() {}; + public ArchitectsWandUtils() {} + + ; /** * Counts the items of a certain type in a player's inventory @@ -67,14 +73,14 @@ public static boolean decreaseFromInventory(EntityPlayer player, ItemStack itemS * and have air in front of them relative to the side clicked on. * * @param world The world in which to place - * @param * @param findCount The maximum amount of blocks it should search * @param clickedSide The side of the block that was clicked * @param startPos The position to start * @return The set of 1<=x<=findCount adjacent blocks with air on their face */ public static Set findAdjacentBlocks(World world, ItemStack itemStackToPlace, int findCount, - ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player) { + ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player, + ItemStack patternBlock) { Set region = new HashSet<>(); if (findCount <= 0) { return region; @@ -103,7 +109,7 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT TranslateMovingObjectPoistionToLocation(mop, startPos); // Base case - if (IsValidForWireFrame(world, itemStackToPlace, startPos, mop, player, clickedSide)) { + if (IsValidForWireFrame(world, itemStackToPlace, startPos, mop, player, clickedSide, patternBlock)) { region.add(startPos); queue.add(startPos); visited.add(startPos); @@ -128,7 +134,7 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT // translate the mop TranslateMovingObjectPoistionToLocation(mop, key); - if (IsValidForWireFrame(world, itemStackToPlace, key, mop, player, clickedSide)) { + if (IsValidForWireFrame(world, itemStackToPlace, key, mop, player, clickedSide, patternBlock)) { region.add(key); queue.add(key); } @@ -139,11 +145,13 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT } private static boolean IsValidForWireFrame(World world, ItemStack itemStackToPlace, BlockPos targetLocation, - MovingObjectPosition movingObjectPosition, EntityPlayer player, ForgeDirection clickedSide) { - ItemStack stack = getItemStackToPlace(world, targetLocation, movingObjectPosition, player); + MovingObjectPosition movingObjectPosition, EntityPlayer player, ForgeDirection clickedSide, + ItemStack patternStack) { + ItemStack stack = getPatternBlock(world, targetLocation, movingObjectPosition, player); if (stack != null) { - Block block = Block.getBlockFromItem(stack.getItem()); - return ItemStack.areItemStacksEqual(stack, itemStackToPlace) + Block block = Block.getBlockFromItem(itemStackToPlace.getItem()); + return (ItemStack.areItemStacksEqual(stack, patternStack) + || ItemStack.areItemStacksEqual(stack, itemStackToPlace)) && world.isAirBlock( targetLocation.x + clickedSide.offsetX, targetLocation.y + clickedSide.offsetY, @@ -162,12 +170,25 @@ private static boolean IsValidForWireFrame(World world, ItemStack itemStackToPla false, clickedSide.ordinal(), null, - stack); + itemStackToPlace); } return false; } - public static ItemStack getItemStackToPlace(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, + public static ItemStack getItemStackToPlace(EntityPlayer player, ItemStack patternBlock) { + if (Mods.Backhand.isLoaded()) { + ItemStack offHandItem = BackhandUtils.getOffhandItem(player); + if (offHandItem != null && offHandItem.getItem() instanceof ItemBlock) { + return offHandItem.copy(); + } + } + return patternBlock; + } + + /** + * @return The block whose structure the wand must follow. + */ + public static ItemStack getPatternBlock(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, EntityPlayer player) { Block block = world.getBlock(pos.x, pos.y, pos.z); if (block != null) { From 8a2346c8be48bfad181b6195f4179f3c9127fca8 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Tue, 17 Feb 2026 21:57:24 +0100 Subject: [PATCH 2/9] works, but buggy --- dependencies.gradle | 3 + .../common/items/ItemArchitectsWand.java | 57 ++++--- .../utilitiesinexcess/compat/Mods.java | 3 +- .../utils/ArchitectsWandUtils.java | 159 ++++++++++++------ 4 files changed, 146 insertions(+), 76 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 6eda82b3..10eb86d5 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -46,6 +46,7 @@ dependencies { compileOnly("com.github.GTNewHorizons:FindIt:1.4.0:dev") compileOnly('com.github.GTNewHorizons:TinkersConstruct:1.14.14-GTNH:dev') compileOnly("com.github.GTNewHorizons:Backhand:1.8.2:dev") + compileOnly('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.296:dev') devOnlyNonPublishable("com.github.GTNewHorizons:Baubles-Expanded:2.2.4-GTNH:dev") @@ -53,6 +54,8 @@ dependencies { runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.8.40-GTNH:dev") runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev") + runtimeOnlyNonPublishable('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.296:dev') + // For testing NBT data (/nbtedit) // runtimeOnlyNonPublishable("com.github.GTNewHorizons:ServerUtilities:2.2.6:dev") diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java index c78037df..fbafa5c3 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; +import java.util.concurrent.ThreadLocalRandom; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; @@ -28,6 +29,7 @@ import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; +import org.jetbrains.annotations.NotNull; public class ItemArchitectsWand extends Item implements ITranslucentItem { @@ -87,7 +89,7 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool // 4. Target block to place // TODO - ItemStack patternBlock = getPatternBlock(world, target, movingObjectPosition, player); + Set patternBlock = getPatternBlock(world, target, movingObjectPosition, player); ItemStack itemStackToPlace = getItemStackToPlace(player, patternBlock); if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) { WireframeRenderer.clearCandidatePositions(); @@ -113,6 +115,29 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool } } + private void placeBlock(World world, EntityPlayer player, @NotNull ItemStack itemStack, BlockPos pos, int side, + float hitX, float hitY, float hitZ, ForgeDirection forgeSide, boolean skipCompact){ + // This block is here because some mods want to use TEs to + + Block comparisonBlock = world.getBlock(pos.x, pos.y, pos.z); + int comparisonMeta = world.getBlockMetadata(pos.x, pos.y, pos.z); + ItemStack comparisonItemStack = new ItemStack(comparisonBlock, 1, comparisonMeta); + + boolean useCompatPlacement = !ItemStack.areItemStacksEqual(itemStack, comparisonItemStack); + if (useCompatPlacement && !skipCompact) { + itemStack.getItem() + .onItemUse(itemStack, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ); + } else { + world.setBlock( + pos.x + forgeSide.offsetX, + pos.y + forgeSide.offsetY, + pos.z + forgeSide.offsetZ, + Block.getBlockFromItem(itemStack.getItem()), + comparisonMeta, + 3); + } + } + @Override public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) { @@ -126,44 +151,26 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, BlockPos target = new BlockPos(x, y, z); MovingObjectPosition mop = new MovingObjectPosition(x, y, z, side, Vec3.createVectorHelper(hitX, hitY, hitZ)); - ItemStack patternBlock = getPatternBlock(world, target, mop, player); - ItemStack itemStackToPlace = getItemStackToPlace(player, patternBlock); + Set selectedBlocks = getPatternBlock(world, target, mop, player); + ItemStack itemStackToPlace = getItemStackToPlace(player, selectedBlocks); if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) return false; - // This block is here because some mods want to use TEs to - Block comparisonBlock = world.getBlock(x, y, z); - int comparisonMeta = world.getBlockMetadata(x, y, z); - ItemStack comparisonItemStack = new ItemStack(comparisonBlock, 1, comparisonMeta); - - boolean useCompatPlacement = !ItemStack.areItemStacksEqual(itemStackToPlace, comparisonItemStack); - int inventoryBlockCount = ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace); if (!player.capabilities.isCreativeMode && inventoryBlockCount == 0) return false; int placeCount = player.capabilities.isCreativeMode ? this.buildLimit : Math.min(inventoryBlockCount, this.buildLimit); Set blocksToPlace = ArchitectsWandUtils - .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player, patternBlock); + .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player, selectedBlocks); itemStackToPlace.stackSize = blocksToPlace.size(); // Since now, we actually create a stack we have to set the // size. Strange kinda... for (BlockPos pos : blocksToPlace) { - // TODO: Group these by a bigger number instead of decreasing by 1 every time. + ItemStack randomBlockToPlace = selectedBlocks.toArray(new ItemStack[0])[ThreadLocalRandom.current().nextInt(selectedBlocks.size())]; if (player.capabilities.isCreativeMode - || ArchitectsWandUtils.decreaseFromInventory(player, itemStackToPlace)) { - if (useCompatPlacement) { - itemStackToPlace.getItem() - .onItemUse(itemStackToPlace, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ); - } else { - world.setBlock( - pos.x + forgeSide.offsetX, - pos.y + forgeSide.offsetY, - pos.z + forgeSide.offsetZ, - comparisonBlock, - comparisonMeta, - 3); + || ArchitectsWandUtils.decreaseFromInventory(player, randomBlockToPlace)) { + placeBlock(world, player, randomBlockToPlace, pos, side, hitX, hitY, hitZ, forgeSide, selectedBlocks.size() > 1); } - } } return true; } diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java index 6bdd06b7..feef322c 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java @@ -14,7 +14,8 @@ public enum Mods { CraftTweaker("MineTweaker3"), FindIt("findit"), Tinkers("TConstruct"), - Backhand("backhand") + Backhand("backhand"), + GT("gregtech") ; // spotless:on diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java index 13ff5317..9ff3a3ae 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java @@ -2,13 +2,15 @@ import static com.fouristhenumber.utilitiesinexcess.utils.MovingObjectPositionUtil.TranslateMovingObjectPoistionToLocation; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Queue; -import java.util.Set; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; +import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; +import gregtech.api.items.MetaGeneratedTool; +import gregtech.common.tools.ToolTrowel; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; @@ -18,11 +20,13 @@ import com.fouristhenumber.utilitiesinexcess.compat.Mods; import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; +import org.jetbrains.annotations.Nullable; import xonin.backhand.api.core.BackhandUtils; public class ArchitectsWandUtils { - public ArchitectsWandUtils() {} + public ArchitectsWandUtils() { + } ; @@ -72,15 +76,16 @@ public static boolean decreaseFromInventory(EntityPlayer player, ItemStack itemS * Finds the blocks adjacent to the start position that are connected cardinally, or diagonally * and have air in front of them relative to the side clicked on. * - * @param world The world in which to place - * @param findCount The maximum amount of blocks it should search - * @param clickedSide The side of the block that was clicked - * @param startPos The position to start + * @param world The world in which to place + * @param findCount The maximum amount of blocks it should search + * @param clickedSide The side of the block that was clicked + * @param startPos The position to start + * @param selectedBlocks The pattern used to search adjacent blocks * @return The set of 1<=x<=findCount adjacent blocks with air on their face */ public static Set findAdjacentBlocks(World world, ItemStack itemStackToPlace, int findCount, - ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player, - ItemStack patternBlock) { + ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player, + Set selectedBlocks) { Set region = new HashSet<>(); if (findCount <= 0) { return region; @@ -92,16 +97,16 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT int[][] allowedOffsets = switch (clickedSide) { case UP, DOWN -> // Plane: x/z plane (y remains constant) - new int[][] { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, // Cardinal - { 1, 0, 1 }, { 1, 0, -1 }, { -1, 0, 1 }, { -1, 0, -1 } }; // Diagonal + new int[][]{{1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}, // Cardinal + {1, 0, 1}, {1, 0, -1}, {-1, 0, 1}, {-1, 0, -1}}; // Diagonal case NORTH, SOUTH -> // Plane: x/y plane (z remains constant) - new int[][] { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, // Cardinal - { 1, 1, 0 }, { 1, -1, 0 }, { -1, 1, 0 }, { -1, -1, 0 } }; // Diagonal + new int[][]{{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, // Cardinal + {1, 1, 0}, {1, -1, 0}, {-1, 1, 0}, {-1, -1, 0}}; // Diagonal case EAST, WEST -> // Plane: y/z plane (x remains constant) - new int[][] { { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, // Cardinal - { 0, 1, 1 }, { 0, 1, -1 }, { 0, -1, 1 }, { 0, -1, -1 } }; // Diagonal + new int[][]{{0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}, // Cardinal + {0, 1, 1}, {0, 1, -1}, {0, -1, 1}, {0, -1, -1}}; // Diagonal default -> throw new RuntimeException("UE's BuilderWand's findAdjacentBlocks called with invalid side"); }; @@ -109,7 +114,7 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT TranslateMovingObjectPoistionToLocation(mop, startPos); // Base case - if (IsValidForWireFrame(world, itemStackToPlace, startPos, mop, player, clickedSide, patternBlock)) { + if (IsValidForWireFrame(world, itemStackToPlace, startPos, mop, player, clickedSide, selectedBlocks)) { region.add(startPos); queue.add(startPos); visited.add(startPos); @@ -134,7 +139,7 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT // translate the mop TranslateMovingObjectPoistionToLocation(mop, key); - if (IsValidForWireFrame(world, itemStackToPlace, key, mop, player, clickedSide, patternBlock)) { + if (IsValidForWireFrame(world, itemStackToPlace, key, mop, player, clickedSide, selectedBlocks)) { region.add(key); queue.add(key); } @@ -145,55 +150,109 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT } private static boolean IsValidForWireFrame(World world, ItemStack itemStackToPlace, BlockPos targetLocation, - MovingObjectPosition movingObjectPosition, EntityPlayer player, ForgeDirection clickedSide, - ItemStack patternStack) { - ItemStack stack = getPatternBlock(world, targetLocation, movingObjectPosition, player); - if (stack != null) { + MovingObjectPosition movingObjectPosition, EntityPlayer player, ForgeDirection clickedSide, + Set patternStack) { + ItemStack currentBlock = getBlockByLocation(world, targetLocation, movingObjectPosition, player); + if (currentBlock != null) { Block block = Block.getBlockFromItem(itemStackToPlace.getItem()); - return (ItemStack.areItemStacksEqual(stack, patternStack) - || ItemStack.areItemStacksEqual(stack, itemStackToPlace)) + UtilitiesInExcess.LOG.info("{}{}: {}", currentBlock, patternStack, patternStack.stream().filter(Objects::nonNull).anyMatch(selectedBlock -> ItemStack.areItemStacksEqual(selectedBlock, currentBlock))); + return (patternStack.stream().filter(Objects::nonNull).anyMatch(selectedBlock -> selectedBlock.getItem() == currentBlock.getItem()) || ItemStack.areItemStacksEqual(currentBlock, itemStackToPlace)) && world.isAirBlock( - targetLocation.x + clickedSide.offsetX, - targetLocation.y + clickedSide.offsetY, - targetLocation.z + clickedSide.offsetZ) + targetLocation.x + clickedSide.offsetX, + targetLocation.y + clickedSide.offsetY, + targetLocation.z + clickedSide.offsetZ) && block.canPlaceBlockOnSide( - world, - targetLocation.x + clickedSide.offsetX, - targetLocation.y + clickedSide.offsetY, - targetLocation.z + clickedSide.offsetZ, - clickedSide.ordinal()) + world, + targetLocation.x + clickedSide.offsetX, + targetLocation.y + clickedSide.offsetY, + targetLocation.z + clickedSide.offsetZ, + clickedSide.ordinal()) && world.canPlaceEntityOnSide( - block, - targetLocation.x + clickedSide.offsetX, - targetLocation.y + clickedSide.offsetY, - targetLocation.z + clickedSide.offsetZ, - false, - clickedSide.ordinal(), - null, - itemStackToPlace); + block, + targetLocation.x + clickedSide.offsetX, + targetLocation.y + clickedSide.offsetY, + targetLocation.z + clickedSide.offsetZ, + false, + clickedSide.ordinal(), + null, + itemStackToPlace); } return false; } - public static ItemStack getItemStackToPlace(EntityPlayer player, ItemStack patternBlock) { + private static boolean isTrowel(@Nullable ItemStack stack) { + if (stack == null) { + return false; + } + if (stack.getItem() instanceof MetaGeneratedTool metaGeneratedTool) { + return metaGeneratedTool.getToolStats(stack) instanceof ToolTrowel; + } + return false; + } + + private static List HotbarBlocks(EntityPlayer player) { + List candidates = new ArrayList<>(); + + for (int i = 0; i < 9; i++) { + if (i == player.inventory.currentItem) { + continue; + } + ItemStack item = player.inventory.mainInventory[i]; + if (item == null || !(item.getItem() instanceof ItemBlock)) { + continue; + } + candidates.add(item); + } + return candidates; + } + + private static ItemStack randomHotbarItem(EntityPlayer player) { + List candidates = HotbarBlocks(player); + if (candidates.isEmpty()) { + return null; + } + return candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); + } + + public static ItemStack getItemStackToPlace(EntityPlayer player, Set patternBlock) { if (Mods.Backhand.isLoaded()) { ItemStack offHandItem = BackhandUtils.getOffhandItem(player); - if (offHandItem != null && offHandItem.getItem() instanceof ItemBlock) { + if (offHandItem == null) { + return patternBlock.stream().findFirst().orElse(null); + } + if (Mods.GT.isLoaded() && isTrowel(offHandItem)) { + ItemStack randomItem = randomHotbarItem(player); + return randomItem != null ? randomItem.copy() : null; + } + + if (offHandItem.getItem() instanceof ItemBlock) { return offHandItem.copy(); } } - return patternBlock; + + return patternBlock.stream().findFirst().orElse(null); + } + + public static ItemStack getBlockByLocation(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, + EntityPlayer player) { + Block block = world.getBlock(pos.x, pos.y, pos.z); + if (block == null) { + return null; + } + + return block.getPickBlock(movingObjectPosition, world, pos.x, pos.y, pos.z, player); } /** * @return The block whose structure the wand must follow. */ - public static ItemStack getPatternBlock(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, - EntityPlayer player) { - Block block = world.getBlock(pos.x, pos.y, pos.z); - if (block != null) { - return block.getPickBlock(movingObjectPosition, world, pos.x, pos.y, pos.z, player); + public static Set getPatternBlock(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, + EntityPlayer player) { + if (Mods.GT.isLoaded() && Mods.Backhand.isLoaded() && isTrowel(BackhandUtils.getOffhandItem(player))) { + HashSet patternBlocks = new HashSet<>(HotbarBlocks(player)); +// patternBlocks.add(getBlockByLocation(world, pos, movingObjectPosition, player)); + return patternBlocks; } - return null; + return Collections.singleton(getBlockByLocation(world, pos, movingObjectPosition, player)); } } From 5c898acc39664f729509efc9a7e6021a28222830 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 15:03:10 +0100 Subject: [PATCH 3/9] fix placemnt of block entities --- .../common/items/ItemArchitectsWand.java | 65 ++++---- .../utils/ArchitectsSelection.java | 140 ++++++++++++++++++ .../utils/ArchitectsWandUtils.java | 121 +++------------ 3 files changed, 192 insertions(+), 134 deletions(-) create mode 100644 src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java index fbafa5c3..087bc026 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java @@ -1,12 +1,10 @@ package com.fouristhenumber.utilitiesinexcess.common.items; -import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils.getItemStackToPlace; -import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils.getPatternBlock; - import java.util.List; import java.util.Set; import java.util.concurrent.ThreadLocalRandom; +import com.fouristhenumber.utilitiesinexcess.utils.ArchitectsSelection; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; @@ -88,17 +86,11 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool } // 4. Target block to place - // TODO - Set patternBlock = getPatternBlock(world, target, movingObjectPosition, player); - ItemStack itemStackToPlace = getItemStackToPlace(player, patternBlock); - if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) { - WireframeRenderer.clearCandidatePositions(); - return; - } + ArchitectsSelection selection = new ArchitectsSelection(player, world, movingObjectPosition); + List itemStackToPlace = selection.blockToPlace(player); // 3. Total amount to place - int placeCount = player.capabilities.isCreativeMode ? this.buildLimit - : Math.min(ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace), this.buildLimit); + int placeCount = selection.maxPlaceCount(player, buildLimit); Set blocksToPlace = ArchitectsWandUtils.findAdjacentBlocks( world, @@ -108,7 +100,7 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool target, movingObjectPosition, player, - patternBlock); + selection); WireframeRenderer.clearCandidatePositions(); for (BlockPos pos : blocksToPlace) { WireframeRenderer.addCandidatePosition(pos.offset(forgeSide.offsetX, forgeSide.offsetY, forgeSide.offsetZ)); @@ -116,31 +108,32 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool } private void placeBlock(World world, EntityPlayer player, @NotNull ItemStack itemStack, BlockPos pos, int side, - float hitX, float hitY, float hitZ, ForgeDirection forgeSide, boolean skipCompact){ + float hitX, float hitY, float hitZ, ForgeDirection forgeSide) { // This block is here because some mods want to use TEs to - + ItemStack itemCopy = itemStack.copy(); + itemCopy.stackSize = 1; Block comparisonBlock = world.getBlock(pos.x, pos.y, pos.z); int comparisonMeta = world.getBlockMetadata(pos.x, pos.y, pos.z); ItemStack comparisonItemStack = new ItemStack(comparisonBlock, 1, comparisonMeta); - boolean useCompatPlacement = !ItemStack.areItemStacksEqual(itemStack, comparisonItemStack); - if (useCompatPlacement && !skipCompact) { + boolean useCompatPlacement = !ItemStack.areItemStacksEqual(itemCopy, comparisonItemStack); + if (useCompatPlacement) { itemStack.getItem() - .onItemUse(itemStack, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ); + .onItemUse(itemCopy, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ); } else { world.setBlock( pos.x + forgeSide.offsetX, pos.y + forgeSide.offsetY, pos.z + forgeSide.offsetZ, - Block.getBlockFromItem(itemStack.getItem()), + Block.getBlockFromItem(itemCopy.getItem()), comparisonMeta, 3); - } + } } @Override public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side, - float hitX, float hitY, float hitZ) { + float hitX, float hitY, float hitZ) { // TODO: Prevent player from placing blocks into themself / other entities? ForgeDirection forgeSide = ForgeDirection.getOrientation(side); if (forgeSide == ForgeDirection.UNKNOWN) { @@ -151,26 +144,28 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, BlockPos target = new BlockPos(x, y, z); MovingObjectPosition mop = new MovingObjectPosition(x, y, z, side, Vec3.createVectorHelper(hitX, hitY, hitZ)); - Set selectedBlocks = getPatternBlock(world, target, mop, player); - ItemStack itemStackToPlace = getItemStackToPlace(player, selectedBlocks); - if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) return false; + ArchitectsSelection selection = new ArchitectsSelection(player, world, mop); - int inventoryBlockCount = ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace); - if (!player.capabilities.isCreativeMode && inventoryBlockCount == 0) return false; - int placeCount = player.capabilities.isCreativeMode ? this.buildLimit - : Math.min(inventoryBlockCount, this.buildLimit); + List itemStackToPlace = selection.blockToPlace(player); + + int placeCount = selection.maxPlaceCount(player, buildLimit); Set blocksToPlace = ArchitectsWandUtils - .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player, selectedBlocks); - itemStackToPlace.stackSize = blocksToPlace.size(); // Since now, we actually create a stack we have to set the - // size. Strange kinda... + .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player, selection); + + ItemStack nowPlacing; for (BlockPos pos : blocksToPlace) { - ItemStack randomBlockToPlace = selectedBlocks.toArray(new ItemStack[0])[ThreadLocalRandom.current().nextInt(selectedBlocks.size())]; + List candidates = selection.blockToPlace(player); + if (candidates.size() == 1){ + nowPlacing = candidates.get(0); + } else { + nowPlacing = candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); + } if (player.capabilities.isCreativeMode - || ArchitectsWandUtils.decreaseFromInventory(player, randomBlockToPlace)) { - placeBlock(world, player, randomBlockToPlace, pos, side, hitX, hitY, hitZ, forgeSide, selectedBlocks.size() > 1); - } + || ArchitectsWandUtils.decreaseFromInventory(player, nowPlacing)) { + placeBlock(world, player, nowPlacing, pos, side, hitX, hitY, hitZ, forgeSide); + } } return true; } diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java new file mode 100644 index 00000000..fc599e92 --- /dev/null +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java @@ -0,0 +1,140 @@ +package com.fouristhenumber.utilitiesinexcess.utils; + +import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; +import com.fouristhenumber.utilitiesinexcess.compat.Mods; +import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; +import gregtech.api.items.MetaGeneratedTool; +import gregtech.common.tools.ToolTrowel; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; +import xonin.backhand.api.core.BackhandUtils; + +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + + +public class ArchitectsSelection { + private final Set validBlocks; + private final ItemStack backhand; + private final ItemStack lookAtBlock; + + public ArchitectsSelection(EntityPlayer player, World world, MovingObjectPosition movingObjectPosition) { + this.validBlocks = new HashSet<>(); + backhand = Mods.Backhand.isLoaded() ? BackhandUtils.getOffhandItem(player) : null; + lookAtBlock = getBlockByLocation(world, movingObjectPosition, player); + + // No logic is executed if we don't look at any block, no need to bother checking other cases + if (lookAtBlock == null){ + return; + } + + this.validBlocks.add(lookAtBlock); // Clicked block is always valid + + if (backhand == null) { + return; + } + if (isValidBlock(backhand)) { + this.validBlocks.add(backhand.copy()); + return; + } + if (isTrowel(backhand)) { + this.validBlocks.addAll(hotbarBlocks(player)); + } + } + + /** + * + * @param player + * @return Always a valid block list or null + */ + public List blockToPlace(EntityPlayer player) { + boolean isCreative = player.capabilities.isCreativeMode; + + if (backhand == null) { + return Collections.singletonList((lookAtBlock)); + } + if (isValidBlock(backhand)){ + return Collections.singletonList(backhand); + } + if (isTrowel(backhand)){ + return hotbarBlocks(player); + } + UtilitiesInExcess.LOG.warn("Could not determent a block to place."); + return null; + } + + public int maxPlaceCount(EntityPlayer player, int wandLimit){ + if (player.capabilities.isCreativeMode) return wandLimit; + int count = 0; + for (ItemStack block : blockToPlace(player)){ + count += ArchitectsWandUtils.countItemInInventory(player, block); + } + return Math.min(count, wandLimit); + } + + public boolean matches(ItemStack other) { + if (other == null) return false; + return this.validBlocks.stream().anyMatch(validBlock -> + validBlock.getItem() == other.getItem() && + ItemStack.areItemStackTagsEqual(validBlock, other)); + } + + private static boolean isTrowel(@Nullable ItemStack stack) { + if (stack == null) { + return false; + } + if (stack.getItem() instanceof MetaGeneratedTool metaGeneratedTool) { + return metaGeneratedTool.getToolStats(stack) instanceof ToolTrowel; + } + return false; + } + + private static boolean isValidBlock(@Nullable ItemStack stack) { + return (stack != null && stack.getItem() instanceof ItemBlock); + } + + private static List hotbarBlocks(EntityPlayer player) { + List candidates = new ArrayList<>(); + + for (int i = 0; i < 9; i++) { + if (i == player.inventory.currentItem) { + continue; + } + ItemStack item = player.inventory.mainInventory[i]; + if (!isValidBlock(item)) { + continue; + } + candidates.add(item); + } + return candidates; + } + + private static ItemStack randomHotbarBlock(EntityPlayer player) { + List candidates = hotbarBlocks(player); + if (candidates.isEmpty()) { + return null; + } + return candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); + } + + public static ItemStack getBlockByLocation(World world, MovingObjectPosition movingObjectPosition, + EntityPlayer player) { + + + BlockPos blockPos = new BlockPos( + movingObjectPosition.blockX, + movingObjectPosition.blockY, + movingObjectPosition.blockZ); + + Block block = world.getBlock(blockPos.x, blockPos.y, blockPos.z); + if (block == null) { + return null; + } + return block.getPickBlock(movingObjectPosition, world, blockPos.x, blockPos.y, blockPos.z, player); + } +} diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java index 9ff3a3ae..0dc3ddd0 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java @@ -1,27 +1,23 @@ package com.fouristhenumber.utilitiesinexcess.utils; +import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsSelection.getBlockByLocation; import static com.fouristhenumber.utilitiesinexcess.utils.MovingObjectPositionUtil.TranslateMovingObjectPoistionToLocation; import java.util.*; -import java.util.concurrent.ThreadLocalRandom; import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; import gregtech.api.items.MetaGeneratedTool; import gregtech.common.tools.ToolTrowel; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.Item; -import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; -import com.fouristhenumber.utilitiesinexcess.compat.Mods; import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; import org.jetbrains.annotations.Nullable; -import xonin.backhand.api.core.BackhandUtils; public class ArchitectsWandUtils { @@ -76,16 +72,16 @@ public static boolean decreaseFromInventory(EntityPlayer player, ItemStack itemS * Finds the blocks adjacent to the start position that are connected cardinally, or diagonally * and have air in front of them relative to the side clicked on. * - * @param world The world in which to place - * @param findCount The maximum amount of blocks it should search - * @param clickedSide The side of the block that was clicked - * @param startPos The position to start - * @param selectedBlocks The pattern used to search adjacent blocks + * @param world The world in which to place + * @param findCount The maximum amount of blocks it should search + * @param clickedSide The side of the block that was clicked + * @param startPos The position to start + * @param architectsSelection The pattern used to search adjacent blocks * @return The set of 1<=x<=findCount adjacent blocks with air on their face */ - public static Set findAdjacentBlocks(World world, ItemStack itemStackToPlace, int findCount, + public static Set findAdjacentBlocks(World world, List possiblePlacements, int findCount, ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player, - Set selectedBlocks) { + ArchitectsSelection architectsSelection) { Set region = new HashSet<>(); if (findCount <= 0) { return region; @@ -114,7 +110,7 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT TranslateMovingObjectPoistionToLocation(mop, startPos); // Base case - if (IsValidForWireFrame(world, itemStackToPlace, startPos, mop, player, clickedSide, selectedBlocks)) { + if (IsValidForWireFrame(world, possiblePlacements, startPos, mop, player, clickedSide, architectsSelection)) { region.add(startPos); queue.add(startPos); visited.add(startPos); @@ -139,7 +135,7 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT // translate the mop TranslateMovingObjectPoistionToLocation(mop, key); - if (IsValidForWireFrame(world, itemStackToPlace, key, mop, player, clickedSide, selectedBlocks)) { + if (IsValidForWireFrame(world, possiblePlacements, key, mop, player, clickedSide, architectsSelection)) { region.add(key); queue.add(key); } @@ -149,14 +145,18 @@ public static Set findAdjacentBlocks(World world, ItemStack itemStackT return region; } - private static boolean IsValidForWireFrame(World world, ItemStack itemStackToPlace, BlockPos targetLocation, - MovingObjectPosition movingObjectPosition, EntityPlayer player, ForgeDirection clickedSide, - Set patternStack) { - ItemStack currentBlock = getBlockByLocation(world, targetLocation, movingObjectPosition, player); - if (currentBlock != null) { + private static boolean IsValidForWireFrame(World world, List possibleBlocks, BlockPos targetLocation, + MovingObjectPosition mop, EntityPlayer player, ForgeDirection clickedSide, + ArchitectsSelection selection) { + ItemStack currentBlock = getBlockByLocation(world, mop, player); + + if (currentBlock == null) return false; + + return possibleBlocks.stream().allMatch(itemStackToPlace -> { + if (itemStackToPlace == null) return false; + Block block = Block.getBlockFromItem(itemStackToPlace.getItem()); - UtilitiesInExcess.LOG.info("{}{}: {}", currentBlock, patternStack, patternStack.stream().filter(Objects::nonNull).anyMatch(selectedBlock -> ItemStack.areItemStacksEqual(selectedBlock, currentBlock))); - return (patternStack.stream().filter(Objects::nonNull).anyMatch(selectedBlock -> selectedBlock.getItem() == currentBlock.getItem()) || ItemStack.areItemStacksEqual(currentBlock, itemStackToPlace)) + return selection.matches(currentBlock) && world.isAirBlock( targetLocation.x + clickedSide.offsetX, targetLocation.y + clickedSide.offsetY, @@ -176,83 +176,6 @@ private static boolean IsValidForWireFrame(World world, ItemStack itemStackToPla clickedSide.ordinal(), null, itemStackToPlace); - } - return false; - } - - private static boolean isTrowel(@Nullable ItemStack stack) { - if (stack == null) { - return false; - } - if (stack.getItem() instanceof MetaGeneratedTool metaGeneratedTool) { - return metaGeneratedTool.getToolStats(stack) instanceof ToolTrowel; - } - return false; - } - - private static List HotbarBlocks(EntityPlayer player) { - List candidates = new ArrayList<>(); - - for (int i = 0; i < 9; i++) { - if (i == player.inventory.currentItem) { - continue; - } - ItemStack item = player.inventory.mainInventory[i]; - if (item == null || !(item.getItem() instanceof ItemBlock)) { - continue; - } - candidates.add(item); - } - return candidates; - } - - private static ItemStack randomHotbarItem(EntityPlayer player) { - List candidates = HotbarBlocks(player); - if (candidates.isEmpty()) { - return null; - } - return candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); - } - - public static ItemStack getItemStackToPlace(EntityPlayer player, Set patternBlock) { - if (Mods.Backhand.isLoaded()) { - ItemStack offHandItem = BackhandUtils.getOffhandItem(player); - if (offHandItem == null) { - return patternBlock.stream().findFirst().orElse(null); - } - if (Mods.GT.isLoaded() && isTrowel(offHandItem)) { - ItemStack randomItem = randomHotbarItem(player); - return randomItem != null ? randomItem.copy() : null; - } - - if (offHandItem.getItem() instanceof ItemBlock) { - return offHandItem.copy(); - } - } - - return patternBlock.stream().findFirst().orElse(null); - } - - public static ItemStack getBlockByLocation(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, - EntityPlayer player) { - Block block = world.getBlock(pos.x, pos.y, pos.z); - if (block == null) { - return null; - } - - return block.getPickBlock(movingObjectPosition, world, pos.x, pos.y, pos.z, player); - } - - /** - * @return The block whose structure the wand must follow. - */ - public static Set getPatternBlock(World world, BlockPos pos, MovingObjectPosition movingObjectPosition, - EntityPlayer player) { - if (Mods.GT.isLoaded() && Mods.Backhand.isLoaded() && isTrowel(BackhandUtils.getOffhandItem(player))) { - HashSet patternBlocks = new HashSet<>(HotbarBlocks(player)); -// patternBlocks.add(getBlockByLocation(world, pos, movingObjectPosition, player)); - return patternBlocks; - } - return Collections.singleton(getBlockByLocation(world, pos, movingObjectPosition, player)); + }); } } From 76ea28b6d5910249047f91492416f40934021f7e Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 15:04:20 +0100 Subject: [PATCH 4/9] spotless --- .../common/items/ItemArchitectsWand.java | 19 ++-- .../utils/ArchitectsSelection.java | 43 +++++---- .../utils/ArchitectsWandUtils.java | 87 ++++++++++--------- 3 files changed, 78 insertions(+), 71 deletions(-) diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java index 087bc026..a25d6a5c 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java @@ -4,13 +4,11 @@ import java.util.Set; import java.util.concurrent.ThreadLocalRandom; -import com.fouristhenumber.utilitiesinexcess.utils.ArchitectsSelection; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; -import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.MovingObjectPosition; @@ -19,15 +17,17 @@ import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; +import org.jetbrains.annotations.NotNull; + import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; import com.fouristhenumber.utilitiesinexcess.common.renderers.WireframeRenderer; +import com.fouristhenumber.utilitiesinexcess.utils.ArchitectsSelection; import com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils; import com.gtnewhorizon.gtnhlib.api.ITranslucentItem; import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; -import org.jetbrains.annotations.NotNull; public class ItemArchitectsWand extends Item implements ITranslucentItem { @@ -108,7 +108,7 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool } private void placeBlock(World world, EntityPlayer player, @NotNull ItemStack itemStack, BlockPos pos, int side, - float hitX, float hitY, float hitZ, ForgeDirection forgeSide) { + float hitX, float hitY, float hitZ, ForgeDirection forgeSide) { // This block is here because some mods want to use TEs to ItemStack itemCopy = itemStack.copy(); itemCopy.stackSize = 1; @@ -133,7 +133,7 @@ private void placeBlock(World world, EntityPlayer player, @NotNull ItemStack ite @Override public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, int x, int y, int z, int side, - float hitX, float hitY, float hitZ) { + float hitX, float hitY, float hitZ) { // TODO: Prevent player from placing blocks into themself / other entities? ForgeDirection forgeSide = ForgeDirection.getOrientation(side); if (forgeSide == ForgeDirection.UNKNOWN) { @@ -157,13 +157,14 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, for (BlockPos pos : blocksToPlace) { List candidates = selection.blockToPlace(player); - if (candidates.size() == 1){ + if (candidates.size() == 1) { nowPlacing = candidates.get(0); } else { - nowPlacing = candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); + nowPlacing = candidates.get( + ThreadLocalRandom.current() + .nextInt(candidates.size())); } - if (player.capabilities.isCreativeMode - || ArchitectsWandUtils.decreaseFromInventory(player, nowPlacing)) { + if (player.capabilities.isCreativeMode || ArchitectsWandUtils.decreaseFromInventory(player, nowPlacing)) { placeBlock(world, player, nowPlacing, pos, side, hitX, hitY, hitZ, forgeSide); } } diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java index fc599e92..61677bbf 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java @@ -1,24 +1,27 @@ package com.fouristhenumber.utilitiesinexcess.utils; -import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; -import com.fouristhenumber.utilitiesinexcess.compat.Mods; -import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; -import gregtech.api.items.MetaGeneratedTool; -import gregtech.common.tools.ToolTrowel; +import java.util.*; +import java.util.concurrent.ThreadLocalRandom; + import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemStack; import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; + import org.jetbrains.annotations.Nullable; -import xonin.backhand.api.core.BackhandUtils; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; +import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; +import com.fouristhenumber.utilitiesinexcess.compat.Mods; +import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; +import gregtech.api.items.MetaGeneratedTool; +import gregtech.common.tools.ToolTrowel; +import xonin.backhand.api.core.BackhandUtils; public class ArchitectsSelection { + private final Set validBlocks; private final ItemStack backhand; private final ItemStack lookAtBlock; @@ -29,7 +32,7 @@ public ArchitectsSelection(EntityPlayer player, World world, MovingObjectPositio lookAtBlock = getBlockByLocation(world, movingObjectPosition, player); // No logic is executed if we don't look at any block, no need to bother checking other cases - if (lookAtBlock == null){ + if (lookAtBlock == null) { return; } @@ -58,20 +61,20 @@ public List blockToPlace(EntityPlayer player) { if (backhand == null) { return Collections.singletonList((lookAtBlock)); } - if (isValidBlock(backhand)){ + if (isValidBlock(backhand)) { return Collections.singletonList(backhand); } - if (isTrowel(backhand)){ + if (isTrowel(backhand)) { return hotbarBlocks(player); } UtilitiesInExcess.LOG.warn("Could not determent a block to place."); return null; } - public int maxPlaceCount(EntityPlayer player, int wandLimit){ + public int maxPlaceCount(EntityPlayer player, int wandLimit) { if (player.capabilities.isCreativeMode) return wandLimit; int count = 0; - for (ItemStack block : blockToPlace(player)){ + for (ItemStack block : blockToPlace(player)) { count += ArchitectsWandUtils.countItemInInventory(player, block); } return Math.min(count, wandLimit); @@ -79,9 +82,10 @@ public int maxPlaceCount(EntityPlayer player, int wandLimit){ public boolean matches(ItemStack other) { if (other == null) return false; - return this.validBlocks.stream().anyMatch(validBlock -> - validBlock.getItem() == other.getItem() && - ItemStack.areItemStackTagsEqual(validBlock, other)); + return this.validBlocks.stream() + .anyMatch( + validBlock -> validBlock.getItem() == other.getItem() + && ItemStack.areItemStackTagsEqual(validBlock, other)); } private static boolean isTrowel(@Nullable ItemStack stack) { @@ -119,12 +123,13 @@ private static ItemStack randomHotbarBlock(EntityPlayer player) { if (candidates.isEmpty()) { return null; } - return candidates.get(ThreadLocalRandom.current().nextInt(candidates.size())); + return candidates.get( + ThreadLocalRandom.current() + .nextInt(candidates.size())); } public static ItemStack getBlockByLocation(World world, MovingObjectPosition movingObjectPosition, - EntityPlayer player) { - + EntityPlayer player) { BlockPos blockPos = new BlockPos( movingObjectPosition.blockX, diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java index 0dc3ddd0..d04d4588 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java @@ -5,9 +5,6 @@ import java.util.*; -import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; -import gregtech.api.items.MetaGeneratedTool; -import gregtech.common.tools.ToolTrowel; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -17,12 +14,9 @@ import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; -import org.jetbrains.annotations.Nullable; - public class ArchitectsWandUtils { - public ArchitectsWandUtils() { - } + public ArchitectsWandUtils() {} ; @@ -80,8 +74,8 @@ public static boolean decreaseFromInventory(EntityPlayer player, ItemStack itemS * @return The set of 1<=x<=findCount adjacent blocks with air on their face */ public static Set findAdjacentBlocks(World world, List possiblePlacements, int findCount, - ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player, - ArchitectsSelection architectsSelection) { + ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player, + ArchitectsSelection architectsSelection) { Set region = new HashSet<>(); if (findCount <= 0) { return region; @@ -93,16 +87,16 @@ public static Set findAdjacentBlocks(World world, List poss int[][] allowedOffsets = switch (clickedSide) { case UP, DOWN -> // Plane: x/z plane (y remains constant) - new int[][]{{1, 0, 0}, {-1, 0, 0}, {0, 0, 1}, {0, 0, -1}, // Cardinal - {1, 0, 1}, {1, 0, -1}, {-1, 0, 1}, {-1, 0, -1}}; // Diagonal + new int[][] { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, // Cardinal + { 1, 0, 1 }, { 1, 0, -1 }, { -1, 0, 1 }, { -1, 0, -1 } }; // Diagonal case NORTH, SOUTH -> // Plane: x/y plane (z remains constant) - new int[][]{{1, 0, 0}, {-1, 0, 0}, {0, 1, 0}, {0, -1, 0}, // Cardinal - {1, 1, 0}, {1, -1, 0}, {-1, 1, 0}, {-1, -1, 0}}; // Diagonal + new int[][] { { 1, 0, 0 }, { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, // Cardinal + { 1, 1, 0 }, { 1, -1, 0 }, { -1, 1, 0 }, { -1, -1, 0 } }; // Diagonal case EAST, WEST -> // Plane: y/z plane (x remains constant) - new int[][]{{0, 1, 0}, {0, -1, 0}, {0, 0, 1}, {0, 0, -1}, // Cardinal - {0, 1, 1}, {0, 1, -1}, {0, -1, 1}, {0, -1, -1}}; // Diagonal + new int[][] { { 0, 1, 0 }, { 0, -1, 0 }, { 0, 0, 1 }, { 0, 0, -1 }, // Cardinal + { 0, 1, 1 }, { 0, 1, -1 }, { 0, -1, 1 }, { 0, -1, -1 } }; // Diagonal default -> throw new RuntimeException("UE's BuilderWand's findAdjacentBlocks called with invalid side"); }; @@ -135,7 +129,14 @@ public static Set findAdjacentBlocks(World world, List poss // translate the mop TranslateMovingObjectPoistionToLocation(mop, key); - if (IsValidForWireFrame(world, possiblePlacements, key, mop, player, clickedSide, architectsSelection)) { + if (IsValidForWireFrame( + world, + possiblePlacements, + key, + mop, + player, + clickedSide, + architectsSelection)) { region.add(key); queue.add(key); } @@ -146,36 +147,36 @@ public static Set findAdjacentBlocks(World world, List poss } private static boolean IsValidForWireFrame(World world, List possibleBlocks, BlockPos targetLocation, - MovingObjectPosition mop, EntityPlayer player, ForgeDirection clickedSide, - ArchitectsSelection selection) { + MovingObjectPosition mop, EntityPlayer player, ForgeDirection clickedSide, ArchitectsSelection selection) { ItemStack currentBlock = getBlockByLocation(world, mop, player); if (currentBlock == null) return false; - return possibleBlocks.stream().allMatch(itemStackToPlace -> { - if (itemStackToPlace == null) return false; - - Block block = Block.getBlockFromItem(itemStackToPlace.getItem()); - return selection.matches(currentBlock) - && world.isAirBlock( - targetLocation.x + clickedSide.offsetX, - targetLocation.y + clickedSide.offsetY, - targetLocation.z + clickedSide.offsetZ) - && block.canPlaceBlockOnSide( - world, - targetLocation.x + clickedSide.offsetX, - targetLocation.y + clickedSide.offsetY, - targetLocation.z + clickedSide.offsetZ, - clickedSide.ordinal()) - && world.canPlaceEntityOnSide( - block, - targetLocation.x + clickedSide.offsetX, - targetLocation.y + clickedSide.offsetY, - targetLocation.z + clickedSide.offsetZ, - false, - clickedSide.ordinal(), - null, - itemStackToPlace); - }); + return possibleBlocks.stream() + .allMatch(itemStackToPlace -> { + if (itemStackToPlace == null) return false; + + Block block = Block.getBlockFromItem(itemStackToPlace.getItem()); + return selection.matches(currentBlock) + && world.isAirBlock( + targetLocation.x + clickedSide.offsetX, + targetLocation.y + clickedSide.offsetY, + targetLocation.z + clickedSide.offsetZ) + && block.canPlaceBlockOnSide( + world, + targetLocation.x + clickedSide.offsetX, + targetLocation.y + clickedSide.offsetY, + targetLocation.z + clickedSide.offsetZ, + clickedSide.ordinal()) + && world.canPlaceEntityOnSide( + block, + targetLocation.x + clickedSide.offsetX, + targetLocation.y + clickedSide.offsetY, + targetLocation.z + clickedSide.offsetZ, + false, + clickedSide.ordinal(), + null, + itemStackToPlace); + }); } } From 8a48b06c78eb94543fc921952857a478a20096c6 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 15:07:01 +0100 Subject: [PATCH 5/9] remove dep --- dependencies.gradle | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dependencies.gradle b/dependencies.gradle index 10eb86d5..8da8697c 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -53,13 +53,14 @@ dependencies { devOnlyNonPublishable("io.github.legacymoddingmc:unimixins:0.1.23:dev") runtimeOnlyNonPublishable("com.github.GTNewHorizons:NotEnoughItems:2.8.40-GTNH:dev") - runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev") - runtimeOnlyNonPublishable('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.296:dev') - // For testing NBT data (/nbtedit) // runtimeOnlyNonPublishable("com.github.GTNewHorizons:ServerUtilities:2.2.6:dev") // For testing glove // runtimeOnlyNonPublishable("com.github.GTNewHorizons:Translocators:1.4.0:dev") // runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev") + + // For testing trowel + wand + // runtimeOnlyNonPublishable("com.github.GTNewHorizons:Backhand:1.8.2:dev") + // runtimeOnlyNonPublishable('com.github.GTNewHorizons:GT5-Unofficial:5.09.52.296:dev') } From a1eec2ac5171439a15d24b7f947fcc52d85aa105 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 15:47:01 +0100 Subject: [PATCH 6/9] style --- .../utils/ArchitectsSelection.java | 17 +++++------------ .../utils/ArchitectsWandUtils.java | 6 +++++- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java index 61677bbf..b501a717 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java @@ -1,7 +1,10 @@ package com.fouristhenumber.utilitiesinexcess.utils; -import java.util.*; -import java.util.concurrent.ThreadLocalRandom; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; @@ -118,16 +121,6 @@ private static List hotbarBlocks(EntityPlayer player) { return candidates; } - private static ItemStack randomHotbarBlock(EntityPlayer player) { - List candidates = hotbarBlocks(player); - if (candidates.isEmpty()) { - return null; - } - return candidates.get( - ThreadLocalRandom.current() - .nextInt(candidates.size())); - } - public static ItemStack getBlockByLocation(World world, MovingObjectPosition movingObjectPosition, EntityPlayer player) { diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java index d04d4588..752ccd25 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java @@ -3,7 +3,11 @@ import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsSelection.getBlockByLocation; import static com.fouristhenumber.utilitiesinexcess.utils.MovingObjectPositionUtil.TranslateMovingObjectPoistionToLocation; -import java.util.*; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.Set; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; From 0db5cb4d99692b0c781b67e4d83d49daf6fa39a6 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 16:09:28 +0100 Subject: [PATCH 7/9] added missing is gt loaded check --- .../fouristhenumber/utilitiesinexcess/compat/Mods.java | 2 +- .../utilitiesinexcess/utils/ArchitectsSelection.java | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java index feef322c..c2d13056 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/compat/Mods.java @@ -15,7 +15,7 @@ public enum Mods { FindIt("findit"), Tinkers("TConstruct"), Backhand("backhand"), - GT("gregtech") + GT("gregtech_nh") ; // spotless:on diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java index b501a717..ae479ad6 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java @@ -59,7 +59,6 @@ public ArchitectsSelection(EntityPlayer player, World world, MovingObjectPositio * @return Always a valid block list or null */ public List blockToPlace(EntityPlayer player) { - boolean isCreative = player.capabilities.isCreativeMode; if (backhand == null) { return Collections.singletonList((lookAtBlock)); @@ -67,11 +66,12 @@ public List blockToPlace(EntityPlayer player) { if (isValidBlock(backhand)) { return Collections.singletonList(backhand); } - if (isTrowel(backhand)) { + else if (isTrowel(backhand)) { return hotbarBlocks(player); } - UtilitiesInExcess.LOG.warn("Could not determent a block to place."); - return null; + else { + return Collections.singletonList(lookAtBlock); + } } public int maxPlaceCount(EntityPlayer player, int wandLimit) { @@ -95,7 +95,7 @@ private static boolean isTrowel(@Nullable ItemStack stack) { if (stack == null) { return false; } - if (stack.getItem() instanceof MetaGeneratedTool metaGeneratedTool) { + if (Mods.GT.isLoaded() && stack.getItem() instanceof MetaGeneratedTool metaGeneratedTool) { return metaGeneratedTool.getToolStats(stack) instanceof ToolTrowel; } return false; From dc030b8c0fe6ef95caa80848dee26093e095a161 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 16:27:52 +0100 Subject: [PATCH 8/9] added NEI infopages --- .../utilitiesinexcess/client/IMCForNEI.java | 9 +++++++++ .../utilitiesinexcess/utils/ArchitectsSelection.java | 7 ++----- .../resources/assets/utilitiesinexcess/lang/en_US.lang | 2 ++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/client/IMCForNEI.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/client/IMCForNEI.java index 1466643d..fa70b32d 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/client/IMCForNEI.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/client/IMCForNEI.java @@ -37,10 +37,19 @@ public static void IMCSender() { sendInfoPage("", "nei.infopage.uie.precision_shears.1"); sendInfoPage("", "nei.infopage.uie.etheric_sword.1"); sendInfoPage("", "nei.infopage.uie.reversing_hoe.1"); + sendInfoPage( ",", "nei.infopage.uie.architects_wand.1"); + if (Mods.Backhand.isLoaded()) { + sendInfoPage( + ",", + "nei.infopage.uie.architects_wand.2"); + if (Mods.GT.isLoaded()) sendInfoPage( + ",", + "nei.infopage.uie.architects_wand.3"); + } sendInfoPage("", "nei.infopage.uie.mob_jar.1"); sendInfoPage("utilitiesinexcess:glove", "nei.infopage.uie.glove.1"); diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java index ae479ad6..e34265f0 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsSelection.java @@ -15,7 +15,6 @@ import org.jetbrains.annotations.Nullable; -import com.fouristhenumber.utilitiesinexcess.UtilitiesInExcess; import com.fouristhenumber.utilitiesinexcess.compat.Mods; import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; @@ -65,11 +64,9 @@ public List blockToPlace(EntityPlayer player) { } if (isValidBlock(backhand)) { return Collections.singletonList(backhand); - } - else if (isTrowel(backhand)) { + } else if (isTrowel(backhand)) { return hotbarBlocks(player); - } - else { + } else { return Collections.singletonList(lookAtBlock); } } diff --git a/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang b/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang index dde98b55..c643960c 100644 --- a/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang +++ b/src/main/resources/assets/utilitiesinexcess/lang/en_US.lang @@ -171,6 +171,8 @@ item.architects_wand.name=Architect's Wand tooltip.architects_wand.1=Can place up to %s blocks at once nei.infopage.uie.architects_wand.1=This wand is designed to aid the bearer in construction by placing many blocks at the same time. While looking at a block, you will see a wireframe indicating how a set of blocks will be extended by the wand. +nei.infopage.uie.architects_wand.2=When holding a building block in your off-hand, the wand will try to place it instead. +nei.infopage.uie.architects_wand.3=If, instead of holding a block, you hold a trowel, random blocks from your hotbar will be placed. item.gourmands_axe.name=Gourmand's Axe From 57d298362a006c06e7e6c1c148d746f941c00be3 Mon Sep 17 00:00:00 2001 From: Tomasz Date: Wed, 18 Feb 2026 17:03:51 +0100 Subject: [PATCH 9/9] fix sound --- .../common/items/ItemArchitectsWand.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java index a25d6a5c..efed2778 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java @@ -121,13 +121,22 @@ private void placeBlock(World world, EntityPlayer player, @NotNull ItemStack ite itemStack.getItem() .onItemUse(itemCopy, player, world, pos.x, pos.y, pos.z, side, hitX, hitY, hitZ); } else { + Block block = Block.getBlockFromItem(itemCopy.getItem()); world.setBlock( pos.x + forgeSide.offsetX, pos.y + forgeSide.offsetY, pos.z + forgeSide.offsetZ, - Block.getBlockFromItem(itemCopy.getItem()), + block, comparisonMeta, 3); + + world.playSoundEffect( + pos.x + forgeSide.offsetX, + pos.y + forgeSide.offsetY, + pos.z + forgeSide.offsetZ, + block.stepSound.func_150496_b(), + (block.stepSound.getVolume() + 1.0F) / 2.0F, + block.stepSound.getPitch() * 0.8F); } }