Skip to content

Commit d471e1e

Browse files
Rotate repair states based on the rotation of the sign (#51)
* Add support for directional blocks to getRotation functions in RotationUtils * Simplify calculation of schematic sign position * Rotate repair state based on the rotation of the sign * Use WorldEdit's BukkitAdapter to determine the rotation of schematic blocks * Check sign rotation before using cached ProtoRepairs Fixes an edge case that occurred if a repair sign was precisely on the craft's center of rotation. The issue occurred if a player right-clicked the sign once, rotated the craft, and then right-clicked the sign again in quick succession. This caused the repair to begin as if the craft had not been rotated. * Expand exceptions to add rotation * Clean up offset math --------- Co-authored-by: TylerS1066 <TylerS1066@users.noreply.github.com>
1 parent ea9ece2 commit d471e1e

File tree

4 files changed

+55
-74
lines changed

4 files changed

+55
-74
lines changed

src/main/java/net/countercraft/movecraft/repair/RepairSign.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,10 +123,10 @@ public void onRightClick(Sign sign, @NotNull Player player, PlayerCraft craft) {
123123
return;
124124
} catch (ProtoRepair.ItemRemovalException e) {
125125
player.sendMessage(I18nSupport.getInternationalisedComponent("Repair - Removal exception"));
126-
return;
127-
} catch (ProtoRepair.ProtoRepairExpiredException | ProtoRepair.ProtoRepairLocationException e) {
128-
// Expired or wrong location, go back to first click
129126
// ItemRemovalException shouldn't happen, but go back to first click regardless
127+
return;
128+
} catch (ProtoRepair.ProtoRepairExpiredException | ProtoRepair.ProtoRepairLocationException | ProtoRepair.ProtoRepairRotationException e) {
129+
// Expired, wrong location or rotation, go back to first click
130130
createProtoRepair(sign, uuid, player, craft);
131131
return;
132132
} catch (ProtoRepair.CancelledException e) {

src/main/java/net/countercraft/movecraft/repair/types/ProtoRepair.java

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.bukkit.Material;
1010
import org.bukkit.World;
1111
import org.bukkit.block.Block;
12+
import org.bukkit.block.BlockFace;
1213
import org.bukkit.block.BlockState;
1314
import org.bukkit.block.Container;
1415
import org.bukkit.block.Sign;
@@ -24,6 +25,7 @@
2425
import net.countercraft.movecraft.repair.config.Config;
2526
import net.countercraft.movecraft.repair.events.RepairPreStartedEvent;
2627
import net.countercraft.movecraft.repair.types.blobs.RepairBlob;
28+
import net.countercraft.movecraft.repair.util.RotationUtils;
2729
import net.countercraft.movecraft.util.Counter;
2830
import net.countercraft.movecraft.util.MathUtils;
2931
import net.countercraft.movecraft.util.Pair;
@@ -36,18 +38,20 @@ public class ProtoRepair {
3638
private final RepairCounter materials;
3739
private final int damagedBlockCount;
3840
private final MovecraftLocation origin;
41+
private final BlockFace rotation;
3942
private final World world;
4043
private final HitBox hitBox;
4144
private final long calculationTime;
4245
private boolean valid;
4346

4447
public ProtoRepair(UUID playerUUID, String name, RepairQueue queue, RepairCounter materials, int damagedBlockCount,
45-
MovecraftLocation origin, World world, HitBox hitBox) {
48+
MovecraftLocation origin, BlockFace rotation, World world, HitBox hitBox) {
4649
this.playerUUID = playerUUID;
4750
this.name = name;
4851
this.queue = queue;
4952
this.materials = materials;
5053
this.origin = origin;
54+
this.rotation = rotation;
5155
this.world = world;
5256
this.hitBox = hitBox;
5357
this.damagedBlockCount = damagedBlockCount;
@@ -75,6 +79,10 @@ public MovecraftLocation getOrigin() {
7579
return origin;
7680
}
7781

82+
public BlockFace getRotation() {
83+
return rotation;
84+
}
85+
7886
public World getWorld() {
7987
return world;
8088
}
@@ -89,12 +97,14 @@ public boolean isInvalid() {
8997

9098
@NotNull
9199
public Repair execute(@NotNull Craft craft, Sign sign)
92-
throws ProtoRepairExpiredException, ProtoRepairLocationException, ItemRemovalException,
93-
NotEnoughItemsException, NotEnoughMoneyException {
100+
throws ProtoRepairExpiredException, ProtoRepairLocationException, ProtoRepairRotationException,
101+
ItemRemovalException, NotEnoughItemsException, NotEnoughMoneyException {
94102
if (isInvalid())
95103
throw new ProtoRepairExpiredException(); // Check for expired
96104
if (!origin.equals(MathUtils.bukkit2MovecraftLoc(sign.getLocation())))
97105
throw new ProtoRepairLocationException(); // Check for origin
106+
if (!rotation.equals(RotationUtils.getRotation(sign.getBlockData())))
107+
throw new ProtoRepairRotationException(); // Check for rotation
98108

99109
// Check for balance
100110
double cost = 0;
@@ -245,6 +255,9 @@ public static class ProtoRepairExpiredException extends IllegalStateException {
245255
public static class ProtoRepairLocationException extends IllegalStateException {
246256
}
247257

258+
public static class ProtoRepairRotationException extends IllegalStateException {
259+
}
260+
248261
public static class CancelledException extends IllegalStateException {
249262
}
250263
}

src/main/java/net/countercraft/movecraft/repair/types/RepairState.java

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -50,9 +50,6 @@ public class RepairState {
5050
private final UUID playerUUID;
5151
private final String name;
5252
private final Clipboard schematic;
53-
private final BlockVector3 schematicMinPos;
54-
private final BlockVector3 schematicSignOffset;
55-
private final BlockVector3 size;
5653

5754
public RepairState(@NotNull UUID playerUUID, String name) throws FileNotFoundException, IllegalStateException {
5855
this.playerUUID = playerUUID;
@@ -63,9 +60,6 @@ public RepairState(@NotNull UUID playerUUID, String name) throws FileNotFoundExc
6360
throw new IllegalStateException("Unable to create player directory");
6461

6562
schematic = WEUtils.loadSchematic(playerDirectory, name);
66-
schematicMinPos = schematic.getMinimumPoint();
67-
schematicSignOffset = schematic.getOrigin().subtract(schematicMinPos);
68-
size = schematic.getDimensions();
6963
}
7064

7165
public UUID getUUID() {
@@ -78,14 +72,10 @@ public String getName() {
7872

7973
@NotNull
8074
private Clipboard rotate(@NotNull Sign sign) throws WorldEditException {
81-
BlockVector3 signPosition = BlockVector3.at(sign.getX(), sign.getY(), sign.getZ());
82-
83-
BlockVector3 offset = signPosition.subtract(schematicSignOffset);
84-
BlockVector3 schematicSignPosition = signPosition.subtract(offset).add(schematicMinPos);
85-
BaseBlock schematicSign = schematic.getFullBlock(schematicSignPosition);
75+
BlockData schematicSign = BukkitAdapter.adapt(schematic.getBlock(schematic.getOrigin()));
8676
BlockFace schematicSignFacing = RotationUtils.getRotation(schematicSign);
8777

88-
BlockFace worldSignFacing = RotationUtils.getRotation(sign.getBlock());
78+
BlockFace worldSignFacing = RotationUtils.getRotation(sign.getBlockData());
8979

9080
int angle = RotationUtils.angleBetweenBlockFaces(worldSignFacing, schematicSignFacing);
9181

@@ -95,26 +85,30 @@ private Clipboard rotate(@NotNull Sign sign) throws WorldEditException {
9585
@NotNull
9686
public ProtoRepair execute(@NotNull Sign sign) throws WorldEditException, ProtoRepairCancelledException {
9787
// Rotate repair around the sign
98-
Clipboard clipboard = schematic;
99-
// rotate(sign);
88+
Clipboard clipboard = rotate(sign);
10089

10190
// Gather the required materials and tasks
102-
World world = sign.getWorld();
10391
RepairCounter materials = new RepairCounter();
10492
RepairQueue queue = new RepairQueue();
10593
Map<Location, BlockRepair> blockRepairs = new HashMap<>();
10694
int damagedBlockCount = 0;
107-
Location worldMinPos = sign.getLocation().subtract(schematicSignOffset.getBlockX(), schematicSignOffset.getBlockY(), schematicSignOffset.getBlockZ());
10895
BitmapHitBox hitBox = new BitmapHitBox();
109-
for (int x = 0; x < size.getBlockX(); x++) {
110-
for (int z = 0; z < size.getBlockZ(); z++) {
111-
for (int y = 0; y < size.getBlockY(); y++) {
112-
BlockVector3 schematicPosition = schematicMinPos.add(x, y, z);
96+
97+
// We use offsets from the sign (clipboard origin) to calculate actual coordinates
98+
// This is straightforward since we already know the position of the sign in both the schematic and the world
99+
BlockVector3 clipboardOrigin = clipboard.getOrigin();
100+
BlockVector3 minOffset = clipboard.getMinimumPoint().subtract(clipboardOrigin);
101+
BlockVector3 maxOffset = clipboard.getMaximumPoint().subtract(clipboardOrigin);
102+
103+
for (int x = minOffset.x(); x <= maxOffset.x(); x++) {
104+
for (int z = minOffset.z(); z <= maxOffset.z(); z++) {
105+
for (int y = minOffset.y(); y <= maxOffset.y(); y++) {
106+
BlockVector3 schematicPosition = clipboardOrigin.add(x, y, z);
113107
BaseBlock schematicBlock = clipboard.getFullBlock(schematicPosition);
114108
Material schematicMaterial = BukkitAdapter.adapt(schematicBlock.getBlockType());
115109
BlockData schematicData = BukkitAdapter.adapt(schematicBlock);
116110

117-
Location worldPosition = new Location(world, x, y, z).add(worldMinPos);
111+
Location worldPosition = sign.getLocation().add(x, y, z);
118112
Block worldBlock = worldPosition.getBlock();
119113
Material worldMaterial = worldBlock.getType();
120114
BlockState worldState = worldBlock.getState();
@@ -184,7 +178,7 @@ public ProtoRepair execute(@NotNull Sign sign) throws WorldEditException, ProtoR
184178
}
185179
}
186180

187-
ProtoRepair result = new ProtoRepair(playerUUID, name, queue, materials, damagedBlockCount, MathUtils.bukkit2MovecraftLoc(sign.getLocation()), sign.getWorld(), hitBox);
181+
ProtoRepair result = new ProtoRepair(playerUUID, name, queue, materials, damagedBlockCount, MathUtils.bukkit2MovecraftLoc(sign.getLocation()), RotationUtils.getRotation(sign.getBlockData()), sign.getWorld(), hitBox);
188182

189183
ProtoRepairCreateEvent event = new ProtoRepairCreateEvent(result);
190184
Bukkit.getPluginManager().callEvent(event);

src/main/java/net/countercraft/movecraft/repair/util/RotationUtils.java

Lines changed: 20 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
import org.bukkit.block.Block;
44
import org.bukkit.block.BlockFace;
5+
import org.bukkit.block.data.BlockData;
56
import org.bukkit.block.data.Directional;
67
import org.bukkit.block.data.Rotatable;
78
import org.jetbrains.annotations.Nullable;
89

10+
import com.sk89q.worldedit.bukkit.BukkitAdapter;
911
import com.sk89q.worldedit.world.block.BaseBlock;
1012

1113
public class RotationUtils {
@@ -17,48 +19,7 @@ public class RotationUtils {
1719
*/
1820
@Nullable
1921
public static BlockFace getRotation(BaseBlock block) {
20-
for (var e : block.getStates().entrySet()) {
21-
if (!e.getKey().getName().equals("rotation"))
22-
continue;
23-
24-
switch ((int) e.getValue()) {
25-
case 0:
26-
return BlockFace.SOUTH;
27-
case 1:
28-
return BlockFace.SOUTH_SOUTH_WEST;
29-
case 2:
30-
return BlockFace.SOUTH_WEST;
31-
case 3:
32-
return BlockFace.WEST_SOUTH_WEST;
33-
case 4:
34-
return BlockFace.WEST;
35-
case 5:
36-
return BlockFace.WEST_NORTH_WEST;
37-
case 6:
38-
return BlockFace.NORTH_WEST;
39-
case 7:
40-
return BlockFace.NORTH_NORTH_WEST;
41-
case 8:
42-
return BlockFace.NORTH;
43-
case 9:
44-
return BlockFace.NORTH_NORTH_EAST;
45-
case 10:
46-
return BlockFace.NORTH_EAST;
47-
case 11:
48-
return BlockFace.EAST_NORTH_EAST;
49-
case 12:
50-
return BlockFace.EAST;
51-
case 13:
52-
return BlockFace.EAST_SOUTH_EAST;
53-
case 14:
54-
return BlockFace.SOUTH_EAST;
55-
case 15:
56-
return BlockFace.SOUTH_SOUTH_EAST;
57-
default:
58-
return null;
59-
}
60-
}
61-
return null;
22+
return getRotation(BukkitAdapter.adapt(block));
6223
}
6324

6425
/**
@@ -69,11 +30,24 @@ public static BlockFace getRotation(BaseBlock block) {
6930
*/
7031
@Nullable
7132
public static BlockFace getRotation(Block block) {
72-
if (block.getBlockData() instanceof Rotatable) {
73-
return ((Rotatable) block.getBlockData()).getRotation();
33+
return getRotation(block.getBlockData());
34+
}
35+
36+
/**
37+
* Get the rotation of a Spigot block data
38+
*
39+
* @param blockData Block data to check
40+
* @return Spigot BlockFace to represent the rotation
41+
*/
42+
@Nullable
43+
public static BlockFace getRotation(BlockData blockData) {
44+
if (blockData instanceof Rotatable) {
45+
// Applies to "floor" signs
46+
return ((Rotatable) blockData).getRotation();
7447
}
75-
if (block.getBlockData() instanceof Directional) {
76-
return ((Directional) block.getBlockData()).getFacing().getOppositeFace();
48+
if (blockData instanceof Directional) {
49+
// Applies to wall signs
50+
return ((Directional) blockData).getFacing();
7751
}
7852
return null;
7953
}

0 commit comments

Comments
 (0)