This commit is contained in:
Brian Neumann-Fopiano
2026-08-10 17:32:44 -04:00
parent 998a5c9f5f
commit dfae45663a
56 changed files with 2194 additions and 191 deletions
@@ -52,6 +52,7 @@ import art.arcane.iris.engine.object.IrisPosition;
import art.arcane.iris.engine.object.IrisStructure;
import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.util.common.director.DirectorExecutor;
import art.arcane.iris.util.common.director.specialhandlers.IrisStructureHandler;
import art.arcane.iris.util.common.format.C;
import art.arcane.iris.util.common.plugin.VolmitSender;
import art.arcane.iris.util.common.scheduling.J;
@@ -118,9 +119,9 @@ public class CommandJigsaw implements DirectorExecutor {
customHandler = JigsawModeHandler.class) String mode,
@Param(description = "iris or vanilla", defaultValue = "iris",
customHandler = JigsawCompatibilityHandler.class) String compatibility,
@Param(description = "Cell width", defaultValue = "16") int width,
@Param(description = "Cell height", defaultValue = "16") int height,
@Param(description = "Cell depth", defaultValue = "16") int depth,
@Param(description = "Cell width", defaultValue = "15") int width,
@Param(description = "Cell height", defaultValue = "15") int height,
@Param(description = "Cell depth", defaultValue = "15") int depth,
@Param(description = "Studio world seed", defaultValue = "1337") long seed
) {
IrisData data = requireData(dimension);
@@ -157,6 +158,16 @@ public class CommandJigsaw implements DirectorExecutor {
}
return;
}
try {
JigsawStudioService.clearAutosaveHistory(
data.getDataFolder().toPath(),
structure);
} catch (IOException exception) {
Iris.reportError("Failed to clear stale Jigsaw Studio history for '" + structure + "'.", exception);
sendError("Jigsaw project was created, but stale autosave history could not be cleared: "
+ exception.getMessage());
return;
}
data.invalidateStructureResources();
sender().sendMessage(C.GREEN + "Created Jigsaw project '" + structure + "' atomically.");
open(dimension, structure, seed);
@@ -208,7 +219,8 @@ public class CommandJigsaw implements DirectorExecutor {
public void open(
@Param(description = "Pack dimension") IrisDimension dimension,
@Param(name = "key", aliases = {"structure", "name"},
description = "Existing key loaded from structures/<key>.json") String structure,
description = "Existing key loaded from structures/<key>.json",
customHandler = IrisStructureHandler.class) String structure,
@Param(description = "Studio world seed", defaultValue = "1337") long seed
) {
openProject(player(), sender(), dimension, structure, seed);
@@ -202,7 +202,7 @@ public class CommandObject implements DirectorExecutor {
//Prevent blocks being set in or bellow bedrock
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
futureBlockChanges.put(block, block.getBlockData());
futureBlockChanges.putIfAbsent(block, block.getBlockData());
if (d instanceof IrisCustomData data) {
block.setBlockData(data.getBase(), false);
@@ -369,7 +369,24 @@ public class CommandStructure implements DirectorExecutor {
}
p.getObject().place(p.getX(), p.getY(), p.getZ(), placer, config, rng, null, null, data);
}
sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_STRUCTURE_PLACED_PIECES_AT_YOUR_LOCATION, MessageArgument.untrusted("structure", structure), MessageArgument.untrusted("value", pieces.size())));
int blockChanges = 0;
for (Map.Entry<Block, BlockData> entry : future.entrySet()) {
if (!entry.getKey().getBlockData().equals(entry.getValue())) {
blockChanges++;
}
}
if (blockChanges == 0) {
sender().sendMessage(IrisLanguage.text(
BukkitCommandMessagesExtended.COMMAND_STRUCTURE_PLACEMENT_CHANGED_NO_BLOCKS,
MessageArgument.untrusted("structure", structure),
MessageArgument.untrusted("value", pieces.size())));
return;
}
sender().sendMessage(IrisLanguage.text(
BukkitCommandMessagesExtended.COMMAND_STRUCTURE_PLACED_PIECES_AT_YOUR_LOCATION,
MessageArgument.untrusted("structure", structure),
MessageArgument.untrusted("value", pieces.size()),
MessageArgument.untrusted("value2", blockChanges)));
}
}
@@ -24,6 +24,7 @@ import art.arcane.iris.engine.object.IrisJigsawConnector;
import art.arcane.iris.engine.object.IrisJigsawPiece;
import art.arcane.iris.engine.object.IrisObject;
import art.arcane.iris.engine.object.IrisPosition;
import art.arcane.iris.util.common.director.specialhandlers.IrisStructureHandler;
import art.arcane.volmlib.util.director.DirectorOrigin;
import art.arcane.volmlib.util.director.annotations.Director;
import art.arcane.volmlib.util.director.annotations.Param;
@@ -219,9 +220,9 @@ public class CommandJigsawContractTest {
assertParameter(parameters[2], "planar", CommandJigsaw.JigsawModeHandler.class);
assertParameter(parameters[3], "iris", CommandJigsaw.JigsawCompatibilityHandler.class);
assertParameter(parameters[4], "16", null);
assertParameter(parameters[5], "16", null);
assertParameter(parameters[6], "16", null);
assertParameter(parameters[4], "15", null);
assertParameter(parameters[5], "15", null);
assertParameter(parameters[6], "15", null);
assertParameter(parameters[7], "1337", null);
}
@@ -249,6 +250,7 @@ public class CommandJigsawContractTest {
assertEquals("key", openKey.name());
assertEquals(List.of("structure", "name"), List.of(openKey.aliases()));
assertEquals("Existing key loaded from structures/<key>.json", openKey.description());
assertEquals(IrisStructureHandler.class, openKey.customHandler());
assertEquals(List.of("edit", "reopen"), List.of(openCommand.aliases()));
}
@@ -267,6 +267,11 @@ public class IrisStructureLocateCommandContractTest {
assertTrue(method.contains("IrisData data = dimension.getLoader()"));
assertTrue(method.contains("PlatformChunkGenerator targetGenerator = IrisToolbelt.access(targetWorld)"));
assertTrue(method.contains("CommandObject.createPlacer(targetWorld, future, targetEngine)"));
assertTrue(method.contains("if (blockChanges == 0)"));
assertTrue(method.contains("COMMAND_STRUCTURE_PLACEMENT_CHANGED_NO_BLOCKS"));
Path structureSource = Path.of(System.getProperty("iris.commandStructureSource"));
String objectSource = Files.readString(structureSource.resolveSibling("CommandObject.java"));
assertTrue(objectSource.contains("futureBlockChanges.putIfAbsent(block, block.getBlockData())"));
assertFalse(method.contains("data.getEngine()"));
}