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 69c14c23..dac41140 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/items/ItemArchitectsWand.java @@ -1,5 +1,7 @@ package com.fouristhenumber.utilitiesinexcess.common.items; +import static com.fouristhenumber.utilitiesinexcess.utils.ArchitectsWandUtils.getItemStackToPlace; + import java.util.List; import java.util.Set; @@ -8,10 +10,12 @@ 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; import net.minecraft.util.StatCollector; +import net.minecraft.util.Vec3; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -50,20 +54,28 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool return; } - if (!isSelected) return; + if (!isSelected) { + return; + } - MovingObjectPosition mop = Minecraft.getMinecraft().objectMouseOver; + // I'm pretty sure this will never determine whether we render or not but I'm not certain + MovingObjectPosition movingObjectPosition = Minecraft.getMinecraft().objectMouseOver; // Check if player is looking at a block. - if (mop == null || mop.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) { + if (movingObjectPosition == null + || movingObjectPosition.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) { WireframeRenderer.clearCandidatePositions(); return; } - int x = mop.blockX; - int y = mop.blockY; - int z = mop.blockZ; - int side = mop.sideHit; + // 1. Target block location + BlockPos target = new BlockPos( + movingObjectPosition.blockX, + movingObjectPosition.blockY, + movingObjectPosition.blockZ); + + // 2. Side + int side = movingObjectPosition.sideHit; ForgeDirection forgeSide = ForgeDirection.getOrientation(side); if (forgeSide == ForgeDirection.UNKNOWN) { UtilitiesInExcess.LOG @@ -71,26 +83,23 @@ public void onUpdate(ItemStack stack, World world, Entity entity, int slot, bool return; } - Block blockToPlace = world.getBlock(x, y, z); - if (blockToPlace == null) return; - int metaToPlace = world.getBlockMetadata(x, y, z); - ItemStack itemStack = new ItemStack(Item.getItemFromBlock(blockToPlace), 1, metaToPlace); - - int inventoryBlockCount = ArchitectsWandUtils.countItemInInventory(player, itemStack); - if (!player.capabilities.isCreativeMode && inventoryBlockCount == 0) { + // 4. Target block to place + ItemStack itemStackToPlace = getItemStackToPlace(world, target, movingObjectPosition, player); + if (itemStackToPlace == null || !(itemStackToPlace.getItem() instanceof ItemBlock)) { WireframeRenderer.clearCandidatePositions(); return; } + + // 3. Total amount to place int placeCount = player.capabilities.isCreativeMode ? this.buildLimit - : Math.min(inventoryBlockCount, this.buildLimit); + : Math.min(ArchitectsWandUtils.countItemInInventory(player, itemStackToPlace), this.buildLimit); Set blocksToPlace = ArchitectsWandUtils - .findAdjacentBlocks(world, blockToPlace, metaToPlace, placeCount, forgeSide, new BlockPos(x, y, z)); + .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, movingObjectPosition, player); WireframeRenderer.clearCandidatePositions(); for (BlockPos pos : blocksToPlace) { WireframeRenderer.addCandidatePosition(pos.offset(forgeSide.offsetX, forgeSide.offsetY, forgeSide.offsetZ)); } - } @Override @@ -104,28 +113,44 @@ public boolean onItemUse(ItemStack itemstack, EntityPlayer player, World world, return false; } - Block blockToPlace = world.getBlock(x, y, z); - if (blockToPlace == null) return false; - int metaToPlace = world.getBlockMetadata(x, y, z); - ItemStack itemStack = new ItemStack(Item.getItemFromBlock(blockToPlace), 1, metaToPlace); + 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); + 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); - int inventoryBlockCount = ArchitectsWandUtils.countItemInInventory(player, itemStack); + 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, blockToPlace, metaToPlace, placeCount, forgeSide, new BlockPos(x, y, z)); + .findAdjacentBlocks(world, itemStackToPlace, placeCount, forgeSide, target, mop, player); + 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. - if (player.capabilities.isCreativeMode || ArchitectsWandUtils.decreaseFromInventory(player, itemStack)) { - world.setBlock( - pos.x + forgeSide.offsetX, - pos.y + forgeSide.offsetY, - pos.z + forgeSide.offsetZ, - blockToPlace, - metaToPlace, - 3); + 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); + } } } return true; diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/renderers/WireframeRenderer.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/renderers/WireframeRenderer.java index 74ab244d..d270d623 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/common/renderers/WireframeRenderer.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/common/renderers/WireframeRenderer.java @@ -34,7 +34,7 @@ public static void addCandidatePosition(BlockPos pos) { } public static void clearCandidatePositions() { - if (!candidatePositions.isEmpty()) candidatePositions.clear(); + candidatePositions.clear(); } @EventBusSubscriber.Condition diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java index 6c7306f2..dde01397 100644 --- a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/ArchitectsWandUtils.java @@ -1,5 +1,7 @@ package com.fouristhenumber.utilitiesinexcess.utils; +import static com.fouristhenumber.utilitiesinexcess.utils.MovingObjectPositionUtil.TranslateMovingObjectPoistionToLocation; + import java.util.HashSet; import java.util.LinkedList; import java.util.Queue; @@ -8,6 +10,7 @@ import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition; import net.minecraft.world.World; import net.minecraftforge.common.util.ForgeDirection; @@ -60,19 +63,18 @@ public static boolean decreaseFromInventory(EntityPlayer player, ItemStack itemS } /** - * Finds the blocks adjacent to the start position that are connected cardinally - * and have air infront of them relative to the side clicked on. + * 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 blockToFind The block that is being found - * @param metaToFind The metadata of the block that is being found + * @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, Block blockToFind, int metaToFind, int findCount, - ForgeDirection clickedSide, BlockPos startPos) { + public static Set findAdjacentBlocks(World world, ItemStack itemStackToPlace, int findCount, + ForgeDirection clickedSide, BlockPos startPos, MovingObjectPosition mop, EntityPlayer player) { Set region = new HashSet<>(); if (findCount <= 0) { return region; @@ -84,27 +86,26 @@ public static Set findAdjacentBlocks(World world, Block blockToFind, i 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 } }; + 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 } }; + 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 } }; + 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"); }; - int sx = startPos.x; - int sy = startPos.y; - int sz = startPos.z; + // translate the mop + TranslateMovingObjectPoistionToLocation(mop, startPos); // Base case - if (world.getBlock(sx, sy, sz) == blockToFind && world.getBlockMetadata(sx, sy, sz) == metaToFind - && world.isAirBlock(sx + clickedSide.offsetX, sy + clickedSide.offsetY, sz + clickedSide.offsetZ)) { - - BlockPos neighbor = new BlockPos(sx, sy, sz); - region.add(neighbor); - queue.add(neighbor); + if (IsValidForWireFrame(world, itemStackToPlace, startPos, mop, player, clickedSide)) { + region.add(startPos); + queue.add(startPos); visited.add(startPos); } else { return region; @@ -113,33 +114,23 @@ public static Set findAdjacentBlocks(World world, Block blockToFind, i // Flood-fill the contiguous region in the allowed plane. while (!queue.isEmpty() && region.size() < findCount) { BlockPos current = queue.poll(); - int cx = current.x; - int cy = current.y; - int cz = current.z; for (int[] off : allowedOffsets) { - // Check if already visited - int nx = cx + off[0]; - int ny = cy + off[1]; - int nz = cz + off[2]; + if (region.size() >= findCount) { + break; + } - BlockPos key = new BlockPos(nx, ny, nz); + BlockPos key = current.offset(off[0], off[1], off[2]); if (visited.contains(key)) { continue; } visited.add(key); - // Check and add to region+queue - int airx = nx + clickedSide.offsetX; - int airy = ny + clickedSide.offsetY; - int airz = nz + clickedSide.offsetZ; - - if (world.getBlock(nx, ny, nz) == blockToFind && world.getBlockMetadata(nx, ny, nz) == metaToFind - && world.isAirBlock(airx, airy, airz)) { - - BlockPos neighbor = new BlockPos(nx, ny, nz); - region.add(neighbor); - queue.add(neighbor); + // translate the mop + TranslateMovingObjectPoistionToLocation(mop, key); + if (IsValidForWireFrame(world, itemStackToPlace, key, mop, player, clickedSide)) { + region.add(key); + queue.add(key); } } } @@ -147,4 +138,41 @@ public static Set findAdjacentBlocks(World world, Block blockToFind, i return region; } + private static boolean IsValidForWireFrame(World world, ItemStack itemStackToPlace, BlockPos targetLocation, + MovingObjectPosition movingObjectPosition, EntityPlayer player, ForgeDirection clickedSide) { + ItemStack stack = getItemStackToPlace(world, targetLocation, movingObjectPosition, player); + if (stack != null) { + Block block = Block.getBlockFromItem(stack.getItem()); + return ItemStack.areItemStacksEqual(stack, itemStackToPlace) + && 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, + stack); + } + return false; + } + + public static ItemStack getItemStackToPlace(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); + } + return null; + } } diff --git a/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/MovingObjectPositionUtil.java b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/MovingObjectPositionUtil.java new file mode 100644 index 00000000..2ab8a5fa --- /dev/null +++ b/src/main/java/com/fouristhenumber/utilitiesinexcess/utils/MovingObjectPositionUtil.java @@ -0,0 +1,23 @@ +package com.fouristhenumber.utilitiesinexcess.utils; + +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; + +import com.gtnewhorizon.gtnhlib.blockpos.BlockPos; + +public class MovingObjectPositionUtil { + + public static void TranslateMovingObjectPoistionToLocation(MovingObjectPosition movingObjectPosition, + BlockPos location) { + double offsetXn = movingObjectPosition.hitVec.xCoord - movingObjectPosition.blockX; + double offsetYn = movingObjectPosition.hitVec.yCoord - movingObjectPosition.blockY; + double offsetZn = movingObjectPosition.hitVec.zCoord - movingObjectPosition.blockZ; + + movingObjectPosition.blockX = location.x; + movingObjectPosition.blockY = location.y; + movingObjectPosition.blockZ = location.z; + + movingObjectPosition.hitVec = Vec3 + .createVectorHelper(location.x + offsetXn, location.y + offsetYn, location.z + offsetZn); + } +}