mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-11-01 08:50:06 +00:00
Datapack export
- /iris datapack export compiles one pack dimension into a worldgen datapack for Minecraft 26.3 and later - Bukkit and mod loaders take the same version, mode, namespace, output, format, objects and replace arguments - The default overworld mode replaces the Overworld of a new world with the default world type - Preset and dimension modes write a selectable world preset or a separate dimension - The export runs in the background and publishes the zip or folder atomically - Pack compiler stages turn noise, terrain, caves, subterrain, biomes, surface, decoration, objects and structures into a version-neutral IR - Capability lowering fits every field to 26.3 density function ranges - Disjoint min and max nodes fold to the input that always wins - The 26.3 writer emits density functions, noise settings, biomes, features, structures, presets and dimensions - Every export carries the Iris logo as its pack.png - Unused objects, templates and features are pruned from the output - The pruner keeps pack.png without reading references from its bytes - Imported pack datapacks are bundled into the export - Every approximation reports an export limit diagnostic - Generation cost is counted against a node budget and reported as a warning - Cave biomes over the wall palette limit use the closest kept palette - Jigsaw exports share the template encoder, block states, destinations and publisher with the worldgen export - DataVersion carries the pack format minor and world data version - Both platforms expose vanilla data from the server classpath - GoldenHashEngine and the export probes share one chunk spiral scan - Headless 26.3 probes measure export cost and compare column and chunk likeness against Iris - Real-codec tests decode the exported resources with the 26.3 registries - Paper registry tests run in isolated registry scopes - Command help and messages cover the export in every language file
This commit is contained in:
1 parent
b00e28e42e
commit
1ed1044474
385 files changed
+48102
-535
No files matched your search
@@ -18,21 +18,41 @@
|
||||
|
||||
package art.arcane.iris.command;
|
||||
|
||||
import art.arcane.iris.pack.datapack.DatapackIngestService;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.command.handlers.DimensionHandler;
|
||||
import art.arcane.iris.generation.terrain.IrisDimension;
|
||||
import art.arcane.iris.localization.BukkitCommandMessages;
|
||||
import art.arcane.iris.localization.C;
|
||||
import art.arcane.iris.localization.DirectorCommandMessages;
|
||||
import art.arcane.iris.localization.IrisLanguage;
|
||||
import art.arcane.iris.pack.datapack.DataVersion;
|
||||
import art.arcane.iris.pack.datapack.DatapackIngestService;
|
||||
import art.arcane.iris.pack.datapack.export.DatapackExportDestinations;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportMode;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportProgress;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportRequest;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportResult;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportService;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportServices;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportTargets;
|
||||
import art.arcane.iris.pack.datapack.export.ir.ExportDiagnostic;
|
||||
import art.arcane.iris.platform.bukkit.plugin.VolmitSender;
|
||||
import art.arcane.iris.spi.IrisPlatforms;
|
||||
import art.arcane.iris.world.task.J;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.director.annotations.Director;
|
||||
import art.arcane.volmlib.util.director.annotations.Param;
|
||||
import art.arcane.volmlib.util.localization.LanguageAudience;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import art.arcane.volmlib.util.localization.TextKey;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import art.arcane.iris.localization.IrisLanguage;
|
||||
import art.arcane.iris.localization.BukkitCommandMessages;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
@Director(name = "datapack", aliases = {"datapacks", "dp"}, description = "Download & manage external datapack imports", descriptionKey = "iris.director.commanddatapack.director.download_manage_external_datapack_imports_modrinth")
|
||||
public class CommandDatapack implements DirectorExecutor {
|
||||
private static final int RESOURCE_REPORTS = 4;
|
||||
|
||||
@Director(description = "Download/update every datapack listed in a pack dimension's 'datapackImports' and install it into the world so its structures register like vanilla", descriptionKey = "iris.director.commanddatapack.director.download_update_every_datapack_listed_pack_dimension_s_datapackimports_install_it_into", aliases = {"pull"})
|
||||
public void ingest(
|
||||
@Param(description = "Restart the server when new datapacks are installed (required for new structures to register and generate)", descriptionKey = "iris.director.commanddatapack.param.restart_server_when_new_datapacks_are_installed_required_new_structures_register_generate", defaultValue = "false")
|
||||
@@ -71,4 +91,128 @@ public class CommandDatapack implements DirectorExecutor {
|
||||
) {
|
||||
DatapackIngestService.remove(sender(), id);
|
||||
}
|
||||
|
||||
@Director(description = "Export a dimension as a vanilla worldgen datapack", descriptionKey = "iris.director.commanddatapack.director.export_dimension_vanilla_worldgen_datapack")
|
||||
public void export(
|
||||
@Param(name = "dimension", description = "The dimension to export", descriptionKey = "iris.director.commanddatapack.param.export_dimension", customHandler = DimensionHandler.class)
|
||||
IrisDimension dimension,
|
||||
@Param(name = "version", description = "Target Minecraft version, 26.3 or later (blank uses the latest)", descriptionKey = "iris.director.commanddatapack.param.export_version", defaultValue = "")
|
||||
String version,
|
||||
@Param(name = "mode", description = "Output mode: preset, dimension, or overworld", descriptionKey = "iris.director.commanddatapack.param.export_mode", defaultValue = WorldgenExportRequest.DEFAULT_MODE)
|
||||
String mode,
|
||||
@Param(name = "namespace", description = "Namespace for the exported resources", descriptionKey = "iris.director.commanddatapack.param.export_namespace", defaultValue = WorldgenExportRequest.DEFAULT_NAMESPACE)
|
||||
String namespace,
|
||||
@Param(name = "output", description = "Output name in the datapack exports folder (blank uses the dimension and version)", descriptionKey = "iris.director.commanddatapack.param.export_output", defaultValue = "")
|
||||
String output,
|
||||
@Param(name = "format", description = "zip or directory", descriptionKey = "iris.director.commanddatapack.param.export_format", defaultValue = WorldgenExportRequest.DEFAULT_FORMAT)
|
||||
String format,
|
||||
@Param(name = "objects", description = "Include objects as structure templates", descriptionKey = "iris.director.commanddatapack.param.export_objects", defaultValue = "true")
|
||||
boolean objects,
|
||||
@Param(name = "replace", description = "Replace an existing export with the same name", descriptionKey = "iris.director.commanddatapack.param.export_replace", defaultValue = "false")
|
||||
boolean replace
|
||||
) {
|
||||
VolmitSender sender = sender();
|
||||
WorldgenExportRequest request = WorldgenExportRequest.builder()
|
||||
.pack(dimension.getLoader().getDataFolder().toPath())
|
||||
.dimension(dimension.getLoadKey())
|
||||
.version(version)
|
||||
.mode(mode)
|
||||
.namespace(namespace)
|
||||
.output(output)
|
||||
.format(format)
|
||||
.objects(objects)
|
||||
.replace(replace)
|
||||
.exportRoot(IrisPlatforms.get().dataFolder("exports", "datapacks").toPath())
|
||||
.build();
|
||||
DataVersion target;
|
||||
try {
|
||||
target = validateExport(request);
|
||||
} catch (IllegalArgumentException invalid) {
|
||||
sender.sendMessage(C.RED + IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_INVALID, MessageArgument.untrusted("reason", invalid.getMessage())));
|
||||
return;
|
||||
}
|
||||
WorldgenExportService service = WorldgenExportServices.get();
|
||||
sender.sendMessage(C.GRAY + IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_STARTED, MessageArgument.untrusted("dimension", request.dimension()), MessageArgument.untrusted("version", target.getVersion())));
|
||||
UUID audience = LanguageAudience.current();
|
||||
ExportFeedback feedback = new ExportFeedback(sender);
|
||||
J.a(() -> LanguageAudience.run(audience, () -> runExport(service, request, feedback)));
|
||||
}
|
||||
|
||||
static DataVersion validateExport(WorldgenExportRequest request) {
|
||||
DataVersion target = WorldgenExportTargets.resolve(request.version());
|
||||
WorldgenExportMode.parse(request.mode());
|
||||
DatapackExportDestinations.parseFormat(request.format());
|
||||
return target;
|
||||
}
|
||||
|
||||
private static void runExport(WorldgenExportService service, WorldgenExportRequest request, ExportFeedback feedback) {
|
||||
WorldgenExportResult result;
|
||||
try {
|
||||
result = service.export(request, feedback);
|
||||
} catch (Throwable failure) {
|
||||
Iris.reportError("Datapack export failed for '" + request.dimension() + "'.", failure);
|
||||
feedback.send(C.RED, IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_FAILED, MessageArgument.untrusted("reason", IrisLanguage.errorDetail(failure))));
|
||||
return;
|
||||
}
|
||||
reportExport(feedback, result);
|
||||
}
|
||||
|
||||
private static void reportExport(ExportFeedback feedback, WorldgenExportResult result) {
|
||||
for (ExportDiagnostic diagnostic : result.diagnostics()) {
|
||||
feedback.send(diagnosticColor(diagnostic.severity()), IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_DIAGNOSTIC, MessageArgument.untrusted("key", diagnosticLabel(diagnostic)), MessageArgument.untrusted("message", diagnostic.message())));
|
||||
}
|
||||
if (result.isSuccess()) {
|
||||
feedback.send(C.GREEN, IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_EXPORTED, MessageArgument.untrusted("path", result.output())));
|
||||
return;
|
||||
}
|
||||
TextKey outcome = result.status() == WorldgenExportResult.Status.REJECTED
|
||||
? DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_REJECTED
|
||||
: DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_FAILED;
|
||||
feedback.send(C.RED, IrisLanguage.text(outcome, MessageArgument.untrusted("reason", result.message())));
|
||||
}
|
||||
|
||||
private static C diagnosticColor(ExportDiagnostic.Severity severity) {
|
||||
return switch (severity) {
|
||||
case ERROR -> C.RED;
|
||||
case WARNING -> C.YELLOW;
|
||||
case INFO -> C.GRAY;
|
||||
};
|
||||
}
|
||||
|
||||
private static String diagnosticLabel(ExportDiagnostic diagnostic) {
|
||||
return diagnostic.resource().isEmpty()
|
||||
? diagnostic.limit().name()
|
||||
: diagnostic.limit().name() + " " + diagnostic.resource();
|
||||
}
|
||||
|
||||
private static final class ExportFeedback implements WorldgenExportProgress {
|
||||
private final VolmitSender sender;
|
||||
|
||||
private ExportFeedback(VolmitSender sender) {
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage(String stage) {
|
||||
send(C.GRAY, IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_STAGE, MessageArgument.untrusted("stage", stage)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resources(int done, int total) {
|
||||
int stride = Math.max(1, total / RESOURCE_REPORTS);
|
||||
if (done != total && done % stride != 0) {
|
||||
return;
|
||||
}
|
||||
send(C.GRAY, IrisLanguage.text(DirectorCommandMessages.COMMAND_DATAPACK_EXPORT_RESOURCES, MessageArgument.untrusted("done", done), MessageArgument.untrusted("total", total)));
|
||||
}
|
||||
|
||||
private void send(C color, String message) {
|
||||
String line = color + message;
|
||||
if (sender.isPlayer()) {
|
||||
J.runEntity(sender.player(), () -> sender.sendMessage(line));
|
||||
return;
|
||||
}
|
||||
sender.sendMessage(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,8 @@ import art.arcane.iris.structure.StructureImporter;
|
||||
import art.arcane.iris.structure.VillageImporter;
|
||||
import art.arcane.iris.structure.authoring.StructureKey;
|
||||
import art.arcane.iris.structure.authoring.StructureWriteResult;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportFormat;
|
||||
import art.arcane.iris.pack.datapack.export.DatapackExportDestinations;
|
||||
import art.arcane.iris.pack.datapack.export.DatapackExportFormat;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportRequest;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportSettings;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportSource;
|
||||
@@ -420,9 +421,9 @@ public class CommandJigsaw implements DirectorExecutor {
|
||||
sendError("Wait for the pending autosave or discard the edits before exporting the on-disk graph.");
|
||||
return;
|
||||
}
|
||||
VanillaJigsawExportFormat exportFormat;
|
||||
DatapackExportFormat exportFormat;
|
||||
try {
|
||||
exportFormat = CommandJigsawExports.parseFormat(format);
|
||||
exportFormat = DatapackExportDestinations.parseFormat(format);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
sendError(exception.getMessage());
|
||||
return;
|
||||
@@ -431,7 +432,7 @@ public class CommandJigsaw implements DirectorExecutor {
|
||||
.toPath().toAbsolutePath().normalize();
|
||||
Path destination;
|
||||
try {
|
||||
destination = CommandJigsawExports.resolveExportDestination(exportRoot, output, exportFormat);
|
||||
destination = DatapackExportDestinations.resolve(exportRoot, output, exportFormat);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
sendError(exception.getMessage());
|
||||
return;
|
||||
|
||||
+4
-37
@@ -4,7 +4,7 @@ import art.arcane.iris.Iris;
|
||||
import art.arcane.iris.studio.jigsaw.JigsawStudioService;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawDatapackExporter;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportDiagnostic;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportFormat;
|
||||
import art.arcane.iris.pack.datapack.export.DatapackExportDestinations;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportRequest;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportResult;
|
||||
import art.arcane.iris.localization.C;
|
||||
@@ -13,18 +13,14 @@ import art.arcane.iris.world.task.J;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
final class CommandJigsawExports {
|
||||
private static final Pattern EXPORT_OUTPUT_NAME = Pattern.compile("[a-zA-Z0-9_-][a-zA-Z0-9._-]{0,127}");
|
||||
private static final Set<UUID> EXPORTING_PLAYERS = ConcurrentHashMap.newKeySet();
|
||||
private static final Set<Path> EXPORT_DESTINATIONS = ConcurrentHashMap.newKeySet();
|
||||
|
||||
private CommandJigsawExports() {
|
||||
}
|
||||
@@ -45,11 +41,11 @@ final class CommandJigsawExports {
|
||||
|
||||
static boolean beginExport(UUID playerId, Path destination) {
|
||||
Objects.requireNonNull(playerId);
|
||||
Path normalizedDestination = Objects.requireNonNull(destination).toAbsolutePath().normalize();
|
||||
Objects.requireNonNull(destination);
|
||||
if (!EXPORTING_PLAYERS.add(playerId)) {
|
||||
return false;
|
||||
}
|
||||
if (EXPORT_DESTINATIONS.add(normalizedDestination)) {
|
||||
if (DatapackExportDestinations.claim(destination)) {
|
||||
return true;
|
||||
}
|
||||
EXPORTING_PLAYERS.remove(playerId);
|
||||
@@ -58,7 +54,7 @@ final class CommandJigsawExports {
|
||||
|
||||
static void finishExport(UUID playerId, Path destination) {
|
||||
EXPORTING_PLAYERS.remove(Objects.requireNonNull(playerId));
|
||||
EXPORT_DESTINATIONS.remove(Objects.requireNonNull(destination).toAbsolutePath().normalize());
|
||||
DatapackExportDestinations.release(destination);
|
||||
}
|
||||
|
||||
static void runExport(ExportOperation operation) {
|
||||
@@ -102,35 +98,6 @@ final class CommandJigsawExports {
|
||||
+ result.status() + ": " + result.output());
|
||||
}
|
||||
|
||||
static VanillaJigsawExportFormat parseFormat(String value) {
|
||||
return switch (value.trim().toLowerCase(Locale.ROOT)) {
|
||||
case "zip" -> VanillaJigsawExportFormat.ZIP;
|
||||
case "directory", "dir", "folder" -> VanillaJigsawExportFormat.DIRECTORY;
|
||||
default -> throw new IllegalArgumentException("Export format must be directory or zip.");
|
||||
};
|
||||
}
|
||||
|
||||
static Path resolveExportDestination(
|
||||
Path exportRoot,
|
||||
String output,
|
||||
VanillaJigsawExportFormat format
|
||||
) {
|
||||
Path root = Objects.requireNonNull(exportRoot, "Jigsaw export root").toAbsolutePath().normalize();
|
||||
String requested = Objects.requireNonNull(output, "Jigsaw export output name");
|
||||
String name = requested.trim();
|
||||
if (!name.equals(requested) || !EXPORT_OUTPUT_NAME.matcher(name).matches()) {
|
||||
throw new IllegalArgumentException(
|
||||
"Export output must be one file name using letters, numbers, '.', '_', or '-'.");
|
||||
}
|
||||
String fileName = format == VanillaJigsawExportFormat.ZIP && !name.endsWith(".zip")
|
||||
? name + ".zip" : name;
|
||||
Path destination = root.resolve(fileName).normalize();
|
||||
if (destination.equals(root) || !root.equals(destination.getParent())) {
|
||||
throw new IllegalArgumentException("Export output must be one artifact inside the Studio exports folder.");
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
|
||||
record ExportOperation(
|
||||
Player player,
|
||||
VolmitSender sender,
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
package art.arcane.iris.command;
|
||||
|
||||
import art.arcane.iris.command.handlers.DimensionHandler;
|
||||
import art.arcane.iris.generation.terrain.IrisDimension;
|
||||
import art.arcane.iris.localization.IrisLanguage;
|
||||
import art.arcane.iris.pack.datapack.DataVersion;
|
||||
import art.arcane.iris.pack.datapack.export.WorldgenExportRequest;
|
||||
import art.arcane.volmlib.util.director.annotations.Director;
|
||||
import art.arcane.volmlib.util.director.annotations.Param;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
|
||||
public class CommandDatapackExportContractTest {
|
||||
private static final List<String> NAMES = List.of(
|
||||
"dimension", "version", "mode", "namespace", "output", "format", "objects", "replace");
|
||||
private static final List<String> DEFAULTS = List.of(
|
||||
Param.NO_DEFAULT, "", "overworld", "iris_export", "", "zip", "true", "false");
|
||||
|
||||
@Rule
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void exportParametersAreNamedInOrder() throws Exception {
|
||||
List<String> names = new ArrayList<>();
|
||||
for (Parameter parameter : exportMethod().getParameters()) {
|
||||
names.add(parameter.getAnnotation(Param.class).name());
|
||||
}
|
||||
|
||||
assertEquals(NAMES, names);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dimensionIsPositionalAndEveryOtherParameterIsKeyedWithItsDefault() throws Exception {
|
||||
Parameter[] parameters = exportMethod().getParameters();
|
||||
List<String> defaults = new ArrayList<>();
|
||||
for (Parameter parameter : parameters) {
|
||||
defaults.add(parameter.getAnnotation(Param.class).defaultValue());
|
||||
}
|
||||
|
||||
assertEquals(DEFAULTS, defaults);
|
||||
assertEquals(DimensionHandler.class, parameters[0].getAnnotation(Param.class).customHandler());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exportCommandAndParametersUseRegisteredDescriptions() throws Exception {
|
||||
Method export = exportMethod();
|
||||
Director director = export.getAnnotation(Director.class);
|
||||
|
||||
assertNotNull(director);
|
||||
assertEquals(0L, Arrays.stream(director.aliases()).filter((String alias) -> !alias.isBlank()).count());
|
||||
assertNotNull(director.descriptionKey(), IrisLanguage.catalog().key(director.descriptionKey()));
|
||||
for (Parameter parameter : export.getParameters()) {
|
||||
String key = parameter.getAnnotation(Param.class).descriptionKey();
|
||||
assertNotNull(key, IrisLanguage.catalog().key(key));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validRequestResolvesItsTarget() {
|
||||
assertSame(DataVersion.V26_3, CommandDatapack.validateExport(request().build()));
|
||||
assertSame(DataVersion.V26_3, CommandDatapack.validateExport(request().version("26.3").build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unsupportedArgumentsAreRejectedWithSharedMessages() {
|
||||
assertEquals("Unsupported datapack export version '1.21.1'. Supported: 26.3",
|
||||
reason(request().version("1.21.1").build()));
|
||||
assertEquals("Unsupported datapack export version '26.2'. Supported: 26.3",
|
||||
reason(request().version("26.2").build()));
|
||||
assertEquals("Unknown export mode 'nether'. Expected: preset, dimension, overworld",
|
||||
reason(request().mode("nether").build()));
|
||||
assertEquals("Export format must be directory or zip.", reason(request().format("rar").build()));
|
||||
}
|
||||
|
||||
private WorldgenExportRequest.Builder request() {
|
||||
Path root = temporaryFolder.getRoot().toPath();
|
||||
return WorldgenExportRequest.builder()
|
||||
.pack(root.resolve("packs").resolve("overworld"))
|
||||
.dimension("overworld")
|
||||
.exportRoot(root.resolve("exports"));
|
||||
}
|
||||
|
||||
private static String reason(WorldgenExportRequest request) {
|
||||
return assertThrows(IllegalArgumentException.class, () -> CommandDatapack.validateExport(request)).getMessage();
|
||||
}
|
||||
|
||||
private static Method exportMethod() throws NoSuchMethodException {
|
||||
return CommandDatapack.class.getDeclaredMethod("export", IrisDimension.class, String.class, String.class,
|
||||
String.class, String.class, String.class, boolean.class, boolean.class);
|
||||
}
|
||||
}
|
||||
-19
@@ -17,7 +17,6 @@ import art.arcane.iris.structure.authoring.StructureOwnershipManifest;
|
||||
import art.arcane.iris.structure.authoring.StructureSource;
|
||||
import art.arcane.iris.structure.authoring.StructureTransactionWriter;
|
||||
import art.arcane.iris.structure.conversion.IrisStructureAdoptionInputKind;
|
||||
import art.arcane.iris.structure.export.VanillaJigsawExportFormat;
|
||||
import art.arcane.iris.world.IrisCreator;
|
||||
import art.arcane.iris.generation.terrain.IrisDimension;
|
||||
import art.arcane.iris.pack.value.IrisDirection;
|
||||
@@ -413,24 +412,6 @@ public class CommandJigsawContractTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exportOutputIsOneSafeChildArtifact() {
|
||||
Path root = Path.of("build", "jigsaw-exports").toAbsolutePath().normalize();
|
||||
|
||||
assertEquals(root.resolve("village.zip"), CommandJigsawExports.resolveExportDestination(
|
||||
root, "village", VanillaJigsawExportFormat.ZIP));
|
||||
assertEquals(root.resolve("village"), CommandJigsawExports.resolveExportDestination(
|
||||
root, "village", VanillaJigsawExportFormat.DIRECTORY));
|
||||
assertThrows(IllegalArgumentException.class, () -> CommandJigsawExports.resolveExportDestination(
|
||||
root, "", VanillaJigsawExportFormat.DIRECTORY));
|
||||
assertThrows(IllegalArgumentException.class, () -> CommandJigsawExports.resolveExportDestination(
|
||||
root, ".", VanillaJigsawExportFormat.DIRECTORY));
|
||||
assertThrows(IllegalArgumentException.class, () -> CommandJigsawExports.resolveExportDestination(
|
||||
root, "../all-exports", VanillaJigsawExportFormat.DIRECTORY));
|
||||
assertThrows(IllegalArgumentException.class, () -> CommandJigsawExports.resolveExportDestination(
|
||||
root, "nested/export", VanillaJigsawExportFormat.DIRECTORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void exportLeaseRejectsDuplicatePlayerAndDestination() {
|
||||
UUID firstPlayer = UUID.randomUUID();
|
||||
|
||||
Reference in new issue
Block a user