forked from SteamWar/SteamWar
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
This commit is contained in:
+27
-116
@@ -23,15 +23,17 @@ import de.steamwar.bausystem.BauSystem;
|
|||||||
import de.steamwar.bausystem.Permission;
|
import de.steamwar.bausystem.Permission;
|
||||||
import de.steamwar.entity.*;
|
import de.steamwar.entity.*;
|
||||||
import de.steamwar.linkage.Linked;
|
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.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
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.BlockData;
|
||||||
import org.bukkit.block.data.type.Piston;
|
import org.bukkit.block.data.type.Piston;
|
||||||
|
import org.bukkit.craftbukkit.CraftWorld;
|
||||||
import org.bukkit.entity.Display;
|
import org.bukkit.entity.Display;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.entity.TextDisplay;
|
import org.bukkit.entity.TextDisplay;
|
||||||
@@ -170,7 +172,7 @@ public class PistonCalculator implements Listener {
|
|||||||
private boolean pulling = false;
|
private boolean pulling = false;
|
||||||
private List<Location> movedBlocks = new ArrayList<>();
|
private List<Location> movedBlocks = new ArrayList<>();
|
||||||
private List<Location> brokenBlocks = new ArrayList<>();
|
private List<Location> brokenBlocks = new ArrayList<>();
|
||||||
private Set<Location> immovableBlocks = new HashSet<>();
|
private boolean blocked = false;
|
||||||
|
|
||||||
public PistOrder(Block piston) {
|
public PistOrder(Block piston) {
|
||||||
this.piston = piston;
|
this.piston = piston;
|
||||||
@@ -179,7 +181,7 @@ public class PistonCalculator implements Listener {
|
|||||||
public void calculate() {
|
public void calculate() {
|
||||||
movedBlocks.clear();
|
movedBlocks.clear();
|
||||||
brokenBlocks.clear();
|
brokenBlocks.clear();
|
||||||
immovableBlocks.clear();
|
blocked = false;
|
||||||
|
|
||||||
if (piston.isEmpty()) {
|
if (piston.isEmpty()) {
|
||||||
Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> {
|
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());
|
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(movedBlocks);
|
||||||
Collections.reverse(brokenBlocks);
|
Collections.reverse(brokenBlocks);
|
||||||
@@ -207,86 +209,23 @@ public class PistonCalculator implements Listener {
|
|||||||
visualize();
|
visualize();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculate(Block origin, BlockFace facing, BlockFace direction) {
|
private void resolve(BlockFace facing) {
|
||||||
Block calcOrigin = origin;
|
PistonStructureResolver resolver = new PistonStructureResolver(
|
||||||
if (facing != direction) calcOrigin = origin.getRelative(facing, 3);
|
((CraftWorld) piston.getWorld()).getHandle(),
|
||||||
|
new BlockPos(piston.getX(), piston.getY(), piston.getZ()),
|
||||||
List<Block> toCalc = new LinkedList<>();
|
Direction.valueOf(facing.name()),
|
||||||
calcDirection(origin, null, calcOrigin, facing != direction ? origin.getRelative(facing) : null, facing, direction, toCalc);
|
!pulling
|
||||||
|
);
|
||||||
while (!toCalc.isEmpty()) {
|
if (!resolver.resolve()) {
|
||||||
Block current = toCalc.remove(0);
|
blocked = true;
|
||||||
if (!movedBlocks.contains(current.getLocation())) {
|
return;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
resolver.getToPush().forEach(pos -> movedBlocks.add(toLocation(pos)));
|
||||||
movedBlocks.remove(origin.getLocation());
|
resolver.getToDestroy().forEach(pos -> brokenBlocks.add(toLocation(pos)));
|
||||||
if (facing != direction) movedBlocks.remove(origin.getRelative(facing, 1).getLocation());
|
|
||||||
if (pulling) immovableBlocks.remove(origin.getRelative(facing).getLocation());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcDirection(Block origin, Block blockOrigin, Block calcOrigin, Block ignore, BlockFace facing, BlockFace direction, List<Block> toCalc) {
|
private Location toLocation(BlockPos pos) {
|
||||||
for (int i = 1; i < 24; i++) {
|
return new Location(piston.getWorld(), pos.getX(), pos.getY(), pos.getZ());
|
||||||
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 void visualize() {
|
private void visualize() {
|
||||||
@@ -321,21 +260,11 @@ public class PistonCalculator implements Listener {
|
|||||||
textDisplay.setBrightness(new Display.Brightness(15, 15));
|
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);
|
CWireframe wireframe = new CWireframe(server);
|
||||||
wireframe.setPos1(piston.getLocation());
|
wireframe.setPos1(piston.getLocation());
|
||||||
wireframe.setPos2(piston.getLocation());
|
wireframe.setPos2(piston.getLocation());
|
||||||
if (!immovableBlocks.isEmpty()) {
|
if (blocked) {
|
||||||
wireframe.setBlock(Material.RED_CONCRETE.createBlockData());
|
wireframe.setBlock(Material.RED_CONCRETE.createBlockData());
|
||||||
} else if (movedBlocks.size() > 12) {
|
|
||||||
wireframe.setBlock(Material.YELLOW_CONCRETE.createBlockData());
|
|
||||||
} else {
|
} else {
|
||||||
wireframe.setBlock(Material.LIME_CONCRETE.createBlockData());
|
wireframe.setBlock(Material.LIME_CONCRETE.createBlockData());
|
||||||
}
|
}
|
||||||
@@ -348,7 +277,11 @@ public class PistonCalculator implements Listener {
|
|||||||
} else {
|
} else {
|
||||||
text.append("§ePush\n");
|
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.setText(text.toString());
|
||||||
textDisplay.setBillboard(Display.Billboard.CENTER);
|
textDisplay.setBillboard(Display.Billboard.CENTER);
|
||||||
textDisplay.setAlignment(TextDisplay.TextAlignment.CENTER);
|
textDisplay.setAlignment(TextDisplay.TextAlignment.CENTER);
|
||||||
@@ -358,26 +291,4 @@ public class PistonCalculator implements Listener {
|
|||||||
textDisplay.setBrightness(new Display.Brightness(15, 15));
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user