diff --git a/src/main/java/net/countercraft/movecraft/repair/RepairSign.java b/src/main/java/net/countercraft/movecraft/repair/RepairSign.java index 9ba6d1a..5583315 100644 --- a/src/main/java/net/countercraft/movecraft/repair/RepairSign.java +++ b/src/main/java/net/countercraft/movecraft/repair/RepairSign.java @@ -123,10 +123,10 @@ public void onRightClick(Sign sign, @NotNull Player player, PlayerCraft craft) { return; } catch (ProtoRepair.ItemRemovalException e) { player.sendMessage(I18nSupport.getInternationalisedComponent("Repair - Removal exception")); - return; - } catch (ProtoRepair.ProtoRepairExpiredException | ProtoRepair.ProtoRepairLocationException e) { - // Expired or wrong location, go back to first click // ItemRemovalException shouldn't happen, but go back to first click regardless + return; + } catch (ProtoRepair.ProtoRepairExpiredException | ProtoRepair.ProtoRepairLocationException | ProtoRepair.ProtoRepairRotationException e) { + // Expired, wrong location or rotation, go back to first click createProtoRepair(sign, uuid, player, craft); return; } catch (ProtoRepair.CancelledException e) { diff --git a/src/main/java/net/countercraft/movecraft/repair/types/ProtoRepair.java b/src/main/java/net/countercraft/movecraft/repair/types/ProtoRepair.java index ed5949c..fe1a9ef 100644 --- a/src/main/java/net/countercraft/movecraft/repair/types/ProtoRepair.java +++ b/src/main/java/net/countercraft/movecraft/repair/types/ProtoRepair.java @@ -9,6 +9,7 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; import org.bukkit.block.Container; import org.bukkit.block.Sign; @@ -24,6 +25,7 @@ import net.countercraft.movecraft.repair.config.Config; import net.countercraft.movecraft.repair.events.RepairPreStartedEvent; import net.countercraft.movecraft.repair.types.blobs.RepairBlob; +import net.countercraft.movecraft.repair.util.RotationUtils; import net.countercraft.movecraft.util.Counter; import net.countercraft.movecraft.util.MathUtils; import net.countercraft.movecraft.util.Pair; @@ -36,18 +38,20 @@ public class ProtoRepair { private final RepairCounter materials; private final int damagedBlockCount; private final MovecraftLocation origin; + private final BlockFace rotation; private final World world; private final HitBox hitBox; private final long calculationTime; private boolean valid; public ProtoRepair(UUID playerUUID, String name, RepairQueue queue, RepairCounter materials, int damagedBlockCount, - MovecraftLocation origin, World world, HitBox hitBox) { + MovecraftLocation origin, BlockFace rotation, World world, HitBox hitBox) { this.playerUUID = playerUUID; this.name = name; this.queue = queue; this.materials = materials; this.origin = origin; + this.rotation = rotation; this.world = world; this.hitBox = hitBox; this.damagedBlockCount = damagedBlockCount; @@ -75,6 +79,10 @@ public MovecraftLocation getOrigin() { return origin; } + public BlockFace getRotation() { + return rotation; + } + public World getWorld() { return world; } @@ -89,12 +97,14 @@ public boolean isInvalid() { @NotNull public Repair execute(@NotNull Craft craft, Sign sign) - throws ProtoRepairExpiredException, ProtoRepairLocationException, ItemRemovalException, - NotEnoughItemsException, NotEnoughMoneyException { + throws ProtoRepairExpiredException, ProtoRepairLocationException, ProtoRepairRotationException, + ItemRemovalException, NotEnoughItemsException, NotEnoughMoneyException { if (isInvalid()) throw new ProtoRepairExpiredException(); // Check for expired if (!origin.equals(MathUtils.bukkit2MovecraftLoc(sign.getLocation()))) throw new ProtoRepairLocationException(); // Check for origin + if (!rotation.equals(RotationUtils.getRotation(sign.getBlockData()))) + throw new ProtoRepairRotationException(); // Check for rotation // Check for balance double cost = 0; @@ -245,6 +255,9 @@ public static class ProtoRepairExpiredException extends IllegalStateException { public static class ProtoRepairLocationException extends IllegalStateException { } + public static class ProtoRepairRotationException extends IllegalStateException { + } + public static class CancelledException extends IllegalStateException { } } diff --git a/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java b/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java index 36104fe..fdec702 100644 --- a/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java +++ b/src/main/java/net/countercraft/movecraft/repair/types/RepairState.java @@ -50,9 +50,6 @@ public class RepairState { private final UUID playerUUID; private final String name; private final Clipboard schematic; - private final BlockVector3 schematicMinPos; - private final BlockVector3 schematicSignOffset; - private final BlockVector3 size; public RepairState(@NotNull UUID playerUUID, String name) throws FileNotFoundException, IllegalStateException { this.playerUUID = playerUUID; @@ -63,9 +60,6 @@ public RepairState(@NotNull UUID playerUUID, String name) throws FileNotFoundExc throw new IllegalStateException("Unable to create player directory"); schematic = WEUtils.loadSchematic(playerDirectory, name); - schematicMinPos = schematic.getMinimumPoint(); - schematicSignOffset = schematic.getOrigin().subtract(schematicMinPos); - size = schematic.getDimensions(); } public UUID getUUID() { @@ -78,14 +72,10 @@ public String getName() { @NotNull private Clipboard rotate(@NotNull Sign sign) throws WorldEditException { - BlockVector3 signPosition = BlockVector3.at(sign.getX(), sign.getY(), sign.getZ()); - - BlockVector3 offset = signPosition.subtract(schematicSignOffset); - BlockVector3 schematicSignPosition = signPosition.subtract(offset).add(schematicMinPos); - BaseBlock schematicSign = schematic.getFullBlock(schematicSignPosition); + BlockData schematicSign = BukkitAdapter.adapt(schematic.getBlock(schematic.getOrigin())); BlockFace schematicSignFacing = RotationUtils.getRotation(schematicSign); - BlockFace worldSignFacing = RotationUtils.getRotation(sign.getBlock()); + BlockFace worldSignFacing = RotationUtils.getRotation(sign.getBlockData()); int angle = RotationUtils.angleBetweenBlockFaces(worldSignFacing, schematicSignFacing); @@ -95,26 +85,30 @@ private Clipboard rotate(@NotNull Sign sign) throws WorldEditException { @NotNull public ProtoRepair execute(@NotNull Sign sign) throws WorldEditException, ProtoRepairCancelledException { // Rotate repair around the sign - Clipboard clipboard = schematic; - // rotate(sign); + Clipboard clipboard = rotate(sign); // Gather the required materials and tasks - World world = sign.getWorld(); RepairCounter materials = new RepairCounter(); RepairQueue queue = new RepairQueue(); Map blockRepairs = new HashMap<>(); int damagedBlockCount = 0; - Location worldMinPos = sign.getLocation().subtract(schematicSignOffset.getBlockX(), schematicSignOffset.getBlockY(), schematicSignOffset.getBlockZ()); BitmapHitBox hitBox = new BitmapHitBox(); - for (int x = 0; x < size.getBlockX(); x++) { - for (int z = 0; z < size.getBlockZ(); z++) { - for (int y = 0; y < size.getBlockY(); y++) { - BlockVector3 schematicPosition = schematicMinPos.add(x, y, z); + + // We use offsets from the sign (clipboard origin) to calculate actual coordinates + // This is straightforward since we already know the position of the sign in both the schematic and the world + BlockVector3 clipboardOrigin = clipboard.getOrigin(); + BlockVector3 minOffset = clipboard.getMinimumPoint().subtract(clipboardOrigin); + BlockVector3 maxOffset = clipboard.getMaximumPoint().subtract(clipboardOrigin); + + for (int x = minOffset.x(); x <= maxOffset.x(); x++) { + for (int z = minOffset.z(); z <= maxOffset.z(); z++) { + for (int y = minOffset.y(); y <= maxOffset.y(); y++) { + BlockVector3 schematicPosition = clipboardOrigin.add(x, y, z); BaseBlock schematicBlock = clipboard.getFullBlock(schematicPosition); Material schematicMaterial = BukkitAdapter.adapt(schematicBlock.getBlockType()); BlockData schematicData = BukkitAdapter.adapt(schematicBlock); - Location worldPosition = new Location(world, x, y, z).add(worldMinPos); + Location worldPosition = sign.getLocation().add(x, y, z); Block worldBlock = worldPosition.getBlock(); Material worldMaterial = worldBlock.getType(); BlockState worldState = worldBlock.getState(); @@ -184,7 +178,7 @@ public ProtoRepair execute(@NotNull Sign sign) throws WorldEditException, ProtoR } } - ProtoRepair result = new ProtoRepair(playerUUID, name, queue, materials, damagedBlockCount, MathUtils.bukkit2MovecraftLoc(sign.getLocation()), sign.getWorld(), hitBox); + ProtoRepair result = new ProtoRepair(playerUUID, name, queue, materials, damagedBlockCount, MathUtils.bukkit2MovecraftLoc(sign.getLocation()), RotationUtils.getRotation(sign.getBlockData()), sign.getWorld(), hitBox); ProtoRepairCreateEvent event = new ProtoRepairCreateEvent(result); Bukkit.getPluginManager().callEvent(event); diff --git a/src/main/java/net/countercraft/movecraft/repair/util/RotationUtils.java b/src/main/java/net/countercraft/movecraft/repair/util/RotationUtils.java index 9770e00..eeb1565 100644 --- a/src/main/java/net/countercraft/movecraft/repair/util/RotationUtils.java +++ b/src/main/java/net/countercraft/movecraft/repair/util/RotationUtils.java @@ -2,10 +2,12 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; +import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Directional; import org.bukkit.block.data.Rotatable; import org.jetbrains.annotations.Nullable; +import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.world.block.BaseBlock; public class RotationUtils { @@ -17,48 +19,7 @@ public class RotationUtils { */ @Nullable public static BlockFace getRotation(BaseBlock block) { - for (var e : block.getStates().entrySet()) { - if (!e.getKey().getName().equals("rotation")) - continue; - - switch ((int) e.getValue()) { - case 0: - return BlockFace.SOUTH; - case 1: - return BlockFace.SOUTH_SOUTH_WEST; - case 2: - return BlockFace.SOUTH_WEST; - case 3: - return BlockFace.WEST_SOUTH_WEST; - case 4: - return BlockFace.WEST; - case 5: - return BlockFace.WEST_NORTH_WEST; - case 6: - return BlockFace.NORTH_WEST; - case 7: - return BlockFace.NORTH_NORTH_WEST; - case 8: - return BlockFace.NORTH; - case 9: - return BlockFace.NORTH_NORTH_EAST; - case 10: - return BlockFace.NORTH_EAST; - case 11: - return BlockFace.EAST_NORTH_EAST; - case 12: - return BlockFace.EAST; - case 13: - return BlockFace.EAST_SOUTH_EAST; - case 14: - return BlockFace.SOUTH_EAST; - case 15: - return BlockFace.SOUTH_SOUTH_EAST; - default: - return null; - } - } - return null; + return getRotation(BukkitAdapter.adapt(block)); } /** @@ -69,11 +30,24 @@ public static BlockFace getRotation(BaseBlock block) { */ @Nullable public static BlockFace getRotation(Block block) { - if (block.getBlockData() instanceof Rotatable) { - return ((Rotatable) block.getBlockData()).getRotation(); + return getRotation(block.getBlockData()); + } + + /** + * Get the rotation of a Spigot block data + * + * @param blockData Block data to check + * @return Spigot BlockFace to represent the rotation + */ + @Nullable + public static BlockFace getRotation(BlockData blockData) { + if (blockData instanceof Rotatable) { + // Applies to "floor" signs + return ((Rotatable) blockData).getRotation(); } - if (block.getBlockData() instanceof Directional) { - return ((Directional) block.getBlockData()).getFacing().getOppositeFace(); + if (blockData instanceof Directional) { + // Applies to wall signs + return ((Directional) blockData).getFacing(); } return null; }