From 230f8c521a1afa1b1d3518d1ad5fb28036378f04 Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Sun, 18 Oct 2026 18:08:45 +0000 Subject: [PATCH] Use PistonStructureResolver in PistonCalculator Numbering now comes directly from the vanilla resolver instead of a custom breadth-first search, so the order matches the real move order (including backtracking through slime/honey chains). The display of more than 12 blocks is removed; a blocked piston is shown in red. Refs: #158 --- .../features/util/PistonCalculator.java | 143 ++++-------------- 1 file changed, 27 insertions(+), 116 deletions(-) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java index ec191942..59044202 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java @@ -23,15 +23,17 @@ import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.Permission; import de.steamwar.entity.*; import de.steamwar.linkage.Linked; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.level.block.piston.PistonStructureResolver; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.block.PistonMoveReaction; -import org.bukkit.block.TileState; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.type.Piston; +import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.entity.Display; import org.bukkit.entity.Player; import org.bukkit.entity.TextDisplay; @@ -170,7 +172,7 @@ public class PistonCalculator implements Listener { private boolean pulling = false; private List movedBlocks = new ArrayList<>(); private List brokenBlocks = new ArrayList<>(); - private Set immovableBlocks = new HashSet<>(); + private boolean blocked = false; public PistOrder(Block piston) { this.piston = piston; @@ -179,7 +181,7 @@ public class PistonCalculator implements Listener { public void calculate() { movedBlocks.clear(); brokenBlocks.clear(); - immovableBlocks.clear(); + blocked = false; if (piston.isEmpty()) { Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { @@ -199,7 +201,7 @@ public class PistonCalculator implements Listener { pulling = piston.getType() == Material.STICKY_PISTON && (piston.getRelative(pistonData.getFacing()).getType() == Material.AIR || pistonData.isExtended()); - calculate(piston, pistonData.getFacing(), (pulling ? pistonData.getFacing().getOppositeFace() : pistonData.getFacing())); + resolve(pistonData.getFacing()); Collections.reverse(movedBlocks); Collections.reverse(brokenBlocks); @@ -207,86 +209,23 @@ public class PistonCalculator implements Listener { visualize(); } - private void calculate(Block origin, BlockFace facing, BlockFace direction) { - Block calcOrigin = origin; - if (facing != direction) calcOrigin = origin.getRelative(facing, 3); - - List toCalc = new LinkedList<>(); - calcDirection(origin, null, calcOrigin, facing != direction ? origin.getRelative(facing) : null, facing, direction, toCalc); - - while (!toCalc.isEmpty()) { - Block current = toCalc.remove(0); - if (!movedBlocks.contains(current.getLocation())) { - movedBlocks.add(current.getLocation()); - } - - Material type = current.getType(); - if (type != Material.SLIME_BLOCK && type != Material.HONEY_BLOCK) continue; - Material oppositeType = type == Material.SLIME_BLOCK ? Material.HONEY_BLOCK : Material.SLIME_BLOCK; - - for (BlockFace face : FACES) { - Block block = current.getRelative(face); - if (block.getType().isAir()) continue; - if (isImmovable(block) || block.getPistonMoveReaction() == PistonMoveReaction.BREAK) continue; - if (face != direction || face == direction.getOppositeFace()) { - switch (block.getType()) { - case BLACK_GLAZED_TERRACOTTA: - case GRAY_GLAZED_TERRACOTTA: - case BLUE_GLAZED_TERRACOTTA: - case BROWN_GLAZED_TERRACOTTA: - case CYAN_GLAZED_TERRACOTTA: - case GREEN_GLAZED_TERRACOTTA: - case LIGHT_BLUE_GLAZED_TERRACOTTA: - case LIGHT_GRAY_GLAZED_TERRACOTTA: - case LIME_GLAZED_TERRACOTTA: - case MAGENTA_GLAZED_TERRACOTTA: - case ORANGE_GLAZED_TERRACOTTA: - case PINK_GLAZED_TERRACOTTA: - case PURPLE_GLAZED_TERRACOTTA: - case RED_GLAZED_TERRACOTTA: - case WHITE_GLAZED_TERRACOTTA: - case YELLOW_GLAZED_TERRACOTTA: - continue; - default: - break; - } - } - if (block.getType() != oppositeType) { - if (!movedBlocks.contains(block.getLocation())) toCalc.add(block); - calcDirection(null, origin, block, null, facing, direction, toCalc); - } - } + private void resolve(BlockFace facing) { + PistonStructureResolver resolver = new PistonStructureResolver( + ((CraftWorld) piston.getWorld()).getHandle(), + new BlockPos(piston.getX(), piston.getY(), piston.getZ()), + Direction.valueOf(facing.name()), + !pulling + ); + if (!resolver.resolve()) { + blocked = true; + return; } - - movedBlocks.remove(origin.getLocation()); - if (facing != direction) movedBlocks.remove(origin.getRelative(facing, 1).getLocation()); - if (pulling) immovableBlocks.remove(origin.getRelative(facing).getLocation()); + resolver.getToPush().forEach(pos -> movedBlocks.add(toLocation(pos))); + resolver.getToDestroy().forEach(pos -> brokenBlocks.add(toLocation(pos))); } - private void calcDirection(Block origin, Block blockOrigin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, List toCalc) { - for (int i = 1; i < 24; i++) { - Block block = calcOrigin.getRelative(direction, i); - if (block.equals(ignore)) return; - if (block.getPistonMoveReaction() == PistonMoveReaction.BREAK) { - if (!brokenBlocks.contains(block.getLocation())) { - brokenBlocks.add(block.getLocation()); - } - return; - } - if (isImmovable(block)) { - immovableBlocks.add(block.getLocation()); - return; - } - if (block.getType().isAir()) return; - if (facing == direction && block.equals(blockOrigin)) { - immovableBlocks.add(block.getLocation()); - return; - } - if (facing != direction && (block.equals(origin) || block.getRelative(facing.getOppositeFace()).equals(origin))) { - return; - } - if (!movedBlocks.contains(block.getLocation())) toCalc.add(block); - } + private Location toLocation(BlockPos pos) { + return new Location(piston.getWorld(), pos.getX(), pos.getY(), pos.getZ()); } private void visualize() { @@ -321,21 +260,11 @@ public class PistonCalculator implements Listener { textDisplay.setBrightness(new Display.Brightness(15, 15)); } - for (Location location : immovableBlocks) { - CWireframe wireframe = new CWireframe(server); - wireframe.setPos1(location); - wireframe.setPos2(location); - wireframe.setWidth(1 / 32f); - wireframe.setBlock(Material.RED_CONCRETE.createBlockData()); - } - CWireframe wireframe = new CWireframe(server); wireframe.setPos1(piston.getLocation()); wireframe.setPos2(piston.getLocation()); - if (!immovableBlocks.isEmpty()) { + if (blocked) { wireframe.setBlock(Material.RED_CONCRETE.createBlockData()); - } else if (movedBlocks.size() > 12) { - wireframe.setBlock(Material.YELLOW_CONCRETE.createBlockData()); } else { wireframe.setBlock(Material.LIME_CONCRETE.createBlockData()); } @@ -348,7 +277,11 @@ public class PistonCalculator implements Listener { } else { text.append("§ePush\n"); } - text.append("§f").append(movedBlocks.size()).append(" §eBlocks"); + if (blocked) { + text.append("§cBlocked"); + } else { + text.append("§f").append(movedBlocks.size()).append(" §eBlocks"); + } textDisplay.setText(text.toString()); textDisplay.setBillboard(Display.Billboard.CENTER); textDisplay.setAlignment(TextDisplay.TextAlignment.CENTER); @@ -358,26 +291,4 @@ public class PistonCalculator implements Listener { textDisplay.setBrightness(new Display.Brightness(15, 15)); } } - - private boolean isImmovable(Block block) { - if (block.isEmpty() || block.isLiquid()) { - return false; - } - BlockData blockData = block.getBlockData(); - if (blockData instanceof Piston) { - return ((Piston) blockData).isExtended(); - } - if (block.getState() instanceof TileState) { - return true; - } - PistonMoveReaction reaction = block.getPistonMoveReaction(); - if (reaction == PistonMoveReaction.IGNORE) return true; - if (reaction == PistonMoveReaction.BLOCK) return true; - switch (block.getType()) { - case OBSIDIAN: - return true; - default: - return false; - } - } }