mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 12:41:43 +00:00
ddd
This commit is contained in:
+1
-1
@@ -414,7 +414,7 @@ public final class ModdedForcedDatapack {
|
||||
}
|
||||
LOGGER.info("Iris forced startup datapack staged: {} pack(s), {} world preset(s), {} custom biome(s) at {}", packCount, presetIds.size(), countBiomes(seenBiomes), stagingDirectory);
|
||||
if (packCount == 0) {
|
||||
LOGGER.warn("Iris installed NO worldgen packs into the forced datapack - custom biomes and their colors will NOT generate. Install a pack (e.g. /iris download overworld) and restart the server before creating an Iris world.");
|
||||
LOGGER.warn("Iris installed NO worldgen packs into the forced datapack - custom biomes and their colors will NOT generate. Install a pack with /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>, then restart before creating an Iris world.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Servers
|
||||
* Copyright (c) 2026 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.iris.core.localization.IrisLanguage;
|
||||
import art.arcane.iris.core.localization.PackDownloadMessages;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import art.arcane.volmlib.util.localization.MessageArgument;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public final class ModdedPackInstaller {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final Pattern PACK_NAME = Pattern.compile("[a-z0-9_-]+");
|
||||
private static final Pattern BRANCH_NAME = Pattern.compile("[A-Za-z0-9._-]+");
|
||||
private static final ConcurrentHashMap<String, Object> INSTALL_LOCKS = new ConcurrentHashMap<>();
|
||||
|
||||
private ModdedPackInstaller() {
|
||||
}
|
||||
|
||||
public static boolean install(Path configDir, String pack, String branch,
|
||||
boolean forceOverwrite, boolean refreshDatapack,
|
||||
Consumer<String> feedback) {
|
||||
if (pack == null || !PACK_NAME.matcher(pack).matches()) {
|
||||
feedback.accept(IrisLanguage.plain(PackDownloadMessages.INVALID_PACK_NAME, MessageArgument.untrusted("pack", String.valueOf(pack))));
|
||||
return false;
|
||||
}
|
||||
boolean managed = PackDownloader.isManagedPack(pack);
|
||||
if (!acceptsBranch(pack, branch)) {
|
||||
feedback.accept(IrisLanguage.plain(PackDownloadMessages.INVALID_BRANCH_NAME, MessageArgument.untrusted("branch", String.valueOf(branch))));
|
||||
return false;
|
||||
}
|
||||
|
||||
Object installLock = INSTALL_LOCKS.computeIfAbsent(pack, key -> new Object());
|
||||
synchronized (installLock) {
|
||||
File packs = configDir.resolve("irisworldgen").resolve("packs").toFile();
|
||||
try {
|
||||
PackDownloader.PackInstallResult result = managed
|
||||
? PackDownloader.downloadManaged(packs, pack, forceOverwrite, feedback)
|
||||
: PackDownloader.download(
|
||||
packs,
|
||||
"IrisDimensions/" + pack,
|
||||
branch,
|
||||
forceOverwrite,
|
||||
false,
|
||||
pack,
|
||||
feedback);
|
||||
boolean installed = result != null;
|
||||
if (shouldRefreshDatapack(result, refreshDatapack)) {
|
||||
// Pack-install completion is one of the four forced-datapack regeneration triggers; every
|
||||
// install call site already runs off the server thread, so regenerate inline here. A
|
||||
// regeneration failure must never turn a successful install into a failed one.
|
||||
try {
|
||||
ModdedForcedDatapack.regenerateIfStale("pack install " + pack);
|
||||
} catch (Throwable regenerationFailure) {
|
||||
LOGGER.error("Iris installed pack '{}' but could not regenerate the forced datapack", pack, regenerationFailure);
|
||||
}
|
||||
}
|
||||
if (result != null && result.restartRequired()) {
|
||||
feedback.accept("Pack '" + pack + "' is installed on disk and requires a server restart before its active data changes.");
|
||||
}
|
||||
return installed;
|
||||
} catch (IOException error) {
|
||||
String source = managed ? "configured Git source" : "branch " + branch;
|
||||
LOGGER.error("Iris pack download failed for IrisDimensions/{} ({})", pack, source, error);
|
||||
feedback.accept(IrisLanguage.plain(
|
||||
PackDownloadMessages.DOWNLOAD_FAILED,
|
||||
MessageArgument.untrusted("type", error.getClass().getSimpleName()),
|
||||
MessageArgument.trusted("errorMessage", IrisLanguage.errorDetail(error))
|
||||
));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean acceptsBranch(String pack, String branch) {
|
||||
return PackDownloader.isManagedPack(pack)
|
||||
|| (branch != null && BRANCH_NAME.matcher(branch).matches());
|
||||
}
|
||||
|
||||
static boolean shouldRefreshDatapack(PackDownloader.PackInstallResult result, boolean refreshDatapack) {
|
||||
return result != null && result.changed() && refreshDatapack;
|
||||
}
|
||||
}
|
||||
@@ -133,7 +133,7 @@ public final class ModdedStartup {
|
||||
List<File> packDirs = PackDirectoryResolver.listVisiblePackDirectories(packsRoot);
|
||||
PackValidationRegistry.clear();
|
||||
if (packDirs.isEmpty()) {
|
||||
LOGGER.info("Iris found no packs to validate under {}; install one with /iris download <pack>",
|
||||
LOGGER.info("Iris found no packs to validate under {}; install one with /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>",
|
||||
packsRoot.getAbsolutePath());
|
||||
return;
|
||||
}
|
||||
|
||||
+49
-32
@@ -27,7 +27,6 @@ import art.arcane.iris.modded.ModdedDimensionManager;
|
||||
import art.arcane.iris.modded.ModdedEngineBootstrap;
|
||||
import art.arcane.iris.modded.ModdedForcedDatapack;
|
||||
import art.arcane.iris.modded.ModdedLoader;
|
||||
import art.arcane.iris.modded.ModdedPackInstaller;
|
||||
import art.arcane.iris.modded.ModdedScheduler;
|
||||
import art.arcane.iris.modded.ModdedServerLevels;
|
||||
import art.arcane.iris.modded.ModdedWorldgenIds;
|
||||
@@ -53,6 +52,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -258,54 +258,68 @@ public final class IrisModdedCommands {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int download(CommandSourceStack source, String pack,
|
||||
String branch, boolean forceOverwrite) {
|
||||
boolean managed = PackDownloader.isManagedPack(pack);
|
||||
boolean directUrl = PackDownloader.isDirectZipUrl(pack);
|
||||
String baseDownloadSource = directUrl ? "direct ZIP URL"
|
||||
: managed ? "configured Git source" : "branch " + branch;
|
||||
String downloadSource = forceOverwrite
|
||||
? baseDownloadSource + IrisLanguage.plain(RuntimeUiMessages.DOWNLOAD_OVERWRITE_SUFFIX)
|
||||
: baseDownloadSource;
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("downloadSource", downloadSource)));
|
||||
static int download(CommandSourceStack source, String rawRequest) {
|
||||
DownloadRequest request = parseDownloadRequest(rawRequest);
|
||||
if (request == null) {
|
||||
fail(source, "Use /iris download pack=overworld, /iris download pack=underworld, or /iris download link=<zip-url>.");
|
||||
return 0;
|
||||
}
|
||||
String target = request.pack() == null ? request.url() : request.pack();
|
||||
String downloadSource = request.pack() == null ? "direct ZIP URL" : "built-in beta release";
|
||||
ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", target), MessageArgument.untrusted("downloadSource", downloadSource)));
|
||||
ModdedScheduler scheduler = ModdedEngineBootstrap.schedulerOrNull();
|
||||
if (scheduler == null) {
|
||||
fail(source, IrisLanguage.plain(
|
||||
ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE,
|
||||
MessageArgument.untrusted("pack", pack),
|
||||
MessageArgument.untrusted("pack", target),
|
||||
MessageArgument.untrusted("downloadSource", downloadSource)));
|
||||
return 0;
|
||||
}
|
||||
scheduler.async(() -> {
|
||||
boolean installed;
|
||||
if (directUrl) {
|
||||
File packs = ModdedPackCommands.packsRoot();
|
||||
try {
|
||||
PackDownloader.PackInstallResult result = PackDownloader.downloadUrl(
|
||||
packs,
|
||||
pack,
|
||||
forceOverwrite,
|
||||
(String message) -> scheduler.global(() -> ok(source, message))
|
||||
);
|
||||
installed = result != null;
|
||||
} catch (IOException error) {
|
||||
LOGGER.error("Iris pack download failed for direct URL {}", pack, error);
|
||||
installed = false;
|
||||
}
|
||||
} else {
|
||||
installed = ModdedPackInstaller.install(
|
||||
ModdedEngineBootstrap.loader().configDir(), pack, branch, forceOverwrite, false,
|
||||
(String message) -> scheduler.global(() -> ok(source, message)));
|
||||
boolean installed = false;
|
||||
File packs = ModdedPackCommands.packsRoot();
|
||||
try {
|
||||
PackDownloader.PackInstallResult result = request.pack() == null
|
||||
? PackDownloader.downloadUrl(
|
||||
packs,
|
||||
request.url(),
|
||||
false,
|
||||
(String message) -> scheduler.global(() -> ok(source, message))
|
||||
)
|
||||
: PackDownloader.downloadBuiltIn(
|
||||
packs,
|
||||
request.pack(),
|
||||
false,
|
||||
(String message) -> scheduler.global(() -> ok(source, message))
|
||||
);
|
||||
installed = result != null;
|
||||
} catch (IOException | RuntimeException error) {
|
||||
LOGGER.error("Iris pack download failed for {}", target, error);
|
||||
}
|
||||
if (installed) {
|
||||
scheduler.global(() -> ok(source, "Pack installed on disk. Restart the server before using it."));
|
||||
} else {
|
||||
scheduler.global(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("downloadSource", downloadSource))));
|
||||
scheduler.global(() -> fail(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_DOWNLOAD_FAILED_SEE_CONSOLE, MessageArgument.untrusted("pack", target), MessageArgument.untrusted("downloadSource", downloadSource))));
|
||||
}
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
|
||||
static DownloadRequest parseDownloadRequest(String rawRequest) {
|
||||
if (rawRequest == null || rawRequest.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
if (rawRequest.startsWith("pack=")) {
|
||||
String pack = rawRequest.substring("pack=".length()).trim().toLowerCase(Locale.ROOT);
|
||||
return PackDownloader.isBuiltInPack(pack) ? new DownloadRequest(pack, null) : null;
|
||||
}
|
||||
if (rawRequest.startsWith("link=")) {
|
||||
String url = rawRequest.substring("link=".length()).trim();
|
||||
return PackDownloader.isDirectZipUrl(url) ? new DownloadRequest(null, url) : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static int metrics(CommandSourceStack source) {
|
||||
ServerLevel level = source.getLevel();
|
||||
Engine engine = engineFor(level);
|
||||
@@ -371,4 +385,7 @@ public final class IrisModdedCommands {
|
||||
static void fail(CommandSourceStack source, String message) {
|
||||
ModdedCommandFeedback.fail(source, message);
|
||||
}
|
||||
|
||||
record DownloadRequest(String pack, String url) {
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -70,7 +70,7 @@ final class ModdedCommandHelp {
|
||||
Entry.command("seed", "", ModdedHelpMessages.COMMAND_SEED_PRINT_WORLD_AND_ENGINE_SEED_INFORMATION),
|
||||
Entry.command("debug", "", ModdedHelpMessages.COMMAND_DEBUG_TOGGLE_IRIS_DEBUG_LOGGING_AND_SAVE_SETTINGS_JSON),
|
||||
Entry.command("reload", "", ModdedHelpMessages.COMMAND_RELOAD_RELOAD_SETTINGS_JSON_ALSO_HOTLOADED_AUTOMATICALLY_EVERY_3S),
|
||||
Entry.command("download", "<pack> [branch] [overwrite]", ModdedHelpMessages.COMMAND_DOWNLOAD_DOWNLOAD_A_PACK_PROJECT, "dl"),
|
||||
Entry.command("download", "<pack=overworld|pack=underworld|link=<zip-url>>", ModdedHelpMessages.COMMAND_DOWNLOAD_DOWNLOAD_A_PACK_PROJECT, "dl"),
|
||||
Entry.command("metrics", "", ModdedHelpMessages.COMMAND_METRICS_PRINT_GENERATION_METRICS_FOR_YOUR_CURRENT_IRIS_DIMENSION, "measure"),
|
||||
Entry.command("regen", "[radius]", ModdedHelpMessages.COMMAND_REGEN_DELETE_AND_REGENERATE_NEARBY_CHUNKS_IN_PLACE, "rg"),
|
||||
Entry.group("pregen", ModdedHelpMessages.GROUP_PREGEN_PREGENERATE_AN_IRIS_DIMENSION, "pregenerate"),
|
||||
|
||||
+14
-31
@@ -18,8 +18,6 @@
|
||||
|
||||
package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import com.mojang.brigadier.arguments.BoolArgumentType;
|
||||
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||
import com.mojang.brigadier.arguments.LongArgumentType;
|
||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||
@@ -27,15 +25,24 @@ import com.mojang.brigadier.builder.ArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.suggestion.SuggestionProvider;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.commands.arguments.DimensionArgument;
|
||||
import net.minecraft.commands.arguments.EntityArgument;
|
||||
import net.minecraft.resources.Identifier;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
final class ModdedCommandTree {
|
||||
private static final SuggestionProvider<CommandSourceStack> DOWNLOAD_SOURCES =
|
||||
(context, builder) ->
|
||||
SharedSuggestionProvider.suggest(
|
||||
List.of("pack=overworld", "pack=underworld", "link="),
|
||||
builder
|
||||
);
|
||||
private static final Predicate<CommandSourceStack> GATE = Commands.hasPermission(Commands.LEVEL_GAMEMASTERS);
|
||||
/**
|
||||
* SP-4: read-only inspection must work for an unopped player in a no-cheats singleplayer world, where the
|
||||
@@ -189,35 +196,11 @@ final class ModdedCommandTree {
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSourceStack> downloadTree(String name) {
|
||||
return Commands.literal(name).requires(GATE)
|
||||
.then(Commands.argument("pack", StringArgumentType.word()).suggests(ModdedCommandSuggestions.PACK_NAMES)
|
||||
.executes((CommandContext<CommandSourceStack> context) ->
|
||||
IrisModdedCommands.download(context.getSource(),
|
||||
StringArgumentType.getString(context, "pack"), PackDownloader.DEFAULT_BRANCH, false))
|
||||
.then(Commands.literal("force")
|
||||
.executes((CommandContext<CommandSourceStack> context) ->
|
||||
IrisModdedCommands.download(context.getSource(),
|
||||
StringArgumentType.getString(context, "pack"), PackDownloader.DEFAULT_BRANCH, true)))
|
||||
.then(Commands.argument("overwrite", BoolArgumentType.bool())
|
||||
.executes((CommandContext<CommandSourceStack> context) ->
|
||||
IrisModdedCommands.download(context.getSource(),
|
||||
StringArgumentType.getString(context, "pack"), PackDownloader.DEFAULT_BRANCH,
|
||||
BoolArgumentType.getBool(context, "overwrite"))))
|
||||
.then(Commands.argument("branch", StringArgumentType.word())
|
||||
.executes((CommandContext<CommandSourceStack> context) ->
|
||||
IrisModdedCommands.download(context.getSource(),
|
||||
StringArgumentType.getString(context, "pack"),
|
||||
StringArgumentType.getString(context, "branch"), false))
|
||||
.then(Commands.literal("force")
|
||||
.executes((CommandContext<CommandSourceStack> context) ->
|
||||
IrisModdedCommands.download(context.getSource(),
|
||||
StringArgumentType.getString(context, "pack"),
|
||||
StringArgumentType.getString(context, "branch"), true)))
|
||||
.then(Commands.argument("overwrite", BoolArgumentType.bool())
|
||||
.executes((CommandContext<CommandSourceStack> context) ->
|
||||
IrisModdedCommands.download(context.getSource(),
|
||||
StringArgumentType.getString(context, "pack"),
|
||||
StringArgumentType.getString(context, "branch"),
|
||||
BoolArgumentType.getBool(context, "overwrite"))))));
|
||||
.then(Commands.argument("source", StringArgumentType.greedyString()).suggests(DOWNLOAD_SOURCES)
|
||||
.executes((CommandContext<CommandSourceStack> context) -> IrisModdedCommands.download(
|
||||
context.getSource(),
|
||||
StringArgumentType.getString(context, "source")
|
||||
)));
|
||||
}
|
||||
|
||||
private static LiteralArgumentBuilder<CommandSourceStack> metricsTree(String name) {
|
||||
|
||||
+6
-16
@@ -23,7 +23,6 @@ import art.arcane.iris.core.gui.GuiHost;
|
||||
import art.arcane.iris.core.gui.NoiseExplorerGUI;
|
||||
import art.arcane.iris.core.gui.VisionGUI;
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import art.arcane.iris.core.pack.StructurePackageClosure;
|
||||
import art.arcane.iris.core.project.IrisProjectCopier;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
@@ -40,7 +39,6 @@ import art.arcane.iris.engine.object.IrisSpawner;
|
||||
import art.arcane.iris.engine.object.IrisStructurePlacement;
|
||||
import art.arcane.iris.modded.ModdedDimensionManager;
|
||||
import art.arcane.iris.modded.ModdedEngineBootstrap;
|
||||
import art.arcane.iris.modded.ModdedPackInstaller;
|
||||
import art.arcane.iris.modded.ModdedWorkspaceGenerator;
|
||||
import art.arcane.iris.util.common.parallel.BurstExecutor;
|
||||
import art.arcane.iris.util.common.parallel.MultiBurst;
|
||||
@@ -385,13 +383,9 @@ public final class ModdedStudioCommands {
|
||||
try {
|
||||
File packFolder = new File(ModdedPackCommands.packsRoot(), pack);
|
||||
if (!new File(packFolder, "dimensions/" + pack + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_MISSING_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack))));
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, PackDownloader.DEFAULT_BRANCH, false, true,
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
if (!installed || !new File(packFolder, "dimensions/" + pack + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_PACK_COULD_NOT_BE_DOWNLOADED_CHECK_NAME_TRY_IRIS_DOWNLOAD, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack))));
|
||||
return;
|
||||
}
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Pack '" + pack
|
||||
+ "' is not installed. Use /iris download pack=overworld or pack=underworld, then restart."));
|
||||
return;
|
||||
}
|
||||
IrisData data = IrisData.get(packFolder);
|
||||
IrisDimension dimension = data.getDimensionLoader().load(pack);
|
||||
@@ -593,13 +587,9 @@ public final class ModdedStudioCommands {
|
||||
try {
|
||||
File templateFolder = new File(packsRoot, template);
|
||||
if (!new File(templateFolder, "dimensions/" + template + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_TEMPLATE_IS_NOT_INSTALLED_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("template", template), MessageArgument.untrusted("template2", template))));
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), template, PackDownloader.DEFAULT_BRANCH, false, true,
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
if (!installed || !new File(templateFolder, "dimensions/" + template + ".json").isFile()) {
|
||||
server.execute(() -> IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_STUDIO_COMMANDS_TEMPLATE_COULD_NOT_BE_DOWNLOADED_INSTALL_PACK_WITH_DIMENSIONS_JSON, MessageArgument.untrusted("template", template), MessageArgument.untrusted("template2", template))));
|
||||
return;
|
||||
}
|
||||
server.execute(() -> IrisModdedCommands.fail(source, "Template pack '" + template
|
||||
+ "' is not installed. Install its zip with /iris download link=<zip-url>, then restart."));
|
||||
return;
|
||||
}
|
||||
IrisProjectCopier.copyProject(templateFolder, target, template, name);
|
||||
try {
|
||||
|
||||
+6
-32
@@ -20,7 +20,6 @@ package art.arcane.iris.modded.command;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.core.pack.BrokenPackException;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import art.arcane.iris.core.pack.PackValidationRegistry;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.modded.IrisModdedChunkGenerator;
|
||||
@@ -28,7 +27,6 @@ import art.arcane.iris.modded.MainWorldService;
|
||||
import art.arcane.iris.modded.ModdedDimensionManager;
|
||||
import art.arcane.iris.modded.ModdedEngineBootstrap;
|
||||
import art.arcane.iris.modded.ModdedModConfig;
|
||||
import art.arcane.iris.modded.ModdedPackInstaller;
|
||||
import art.arcane.iris.modded.ModdedPrimaryWorldRouter;
|
||||
import art.arcane.iris.modded.ModdedServerLevels;
|
||||
import art.arcane.iris.modded.ModdedStartup;
|
||||
@@ -176,21 +174,9 @@ public final class ModdedWorldCommands {
|
||||
if (packFolder.isDirectory()) {
|
||||
return enableInstalled(source, server, dimensionId, pack, packDimension, seed);
|
||||
}
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_IS_NOT_INSTALLED_DOWNLOADING_IRISDIMENSIONS, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
Thread thread = new Thread(() -> {
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, PackDownloader.DEFAULT_BRANCH, false, true,
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
server.execute(() -> {
|
||||
if (!installed || !packFolder.isDirectory()) {
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_COULD_NOT_BE_DOWNLOADED_CHECK_NAME_INSTALL_IT_WITH, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
return;
|
||||
}
|
||||
enableInstalled(source, server, dimensionId, pack, packDimension, seed);
|
||||
});
|
||||
}, "Iris World Pack Download");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
return 1;
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack
|
||||
+ "' is not installed. Use /iris download pack=overworld or pack=underworld, then restart.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int enableInstalled(CommandSourceStack source, MinecraftServer server, String dimensionId, String pack, String packDimension, long seed) {
|
||||
@@ -279,21 +265,9 @@ public final class ModdedWorldCommands {
|
||||
if (packFolder.isDirectory()) {
|
||||
return applyMainWorld(source, pack, packDimension, packRaw, seed);
|
||||
}
|
||||
IrisModdedCommands.ok(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_IS_NOT_INSTALLED_DOWNLOADING_IRISDIMENSIONS_2, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
Thread thread = new Thread(() -> {
|
||||
boolean installed = ModdedPackInstaller.install(ModdedEngineBootstrap.loader().configDir(), pack, PackDownloader.DEFAULT_BRANCH, false, true,
|
||||
(String line) -> server.execute(() -> IrisModdedCommands.ok(source, line)));
|
||||
server.execute(() -> {
|
||||
if (!installed || !packFolder.isDirectory()) {
|
||||
IrisModdedCommands.fail(source, IrisLanguage.plain(ModdedCommandMessages.MODDED_WORLD_COMMANDS_PACK_COULD_NOT_BE_DOWNLOADED_CHECK_NAME_INSTALL_IT_WITH_2, MessageArgument.untrusted("pack", pack), MessageArgument.untrusted("pack2", pack)));
|
||||
return;
|
||||
}
|
||||
applyMainWorld(source, pack, packDimension, packRaw, seed);
|
||||
});
|
||||
}, "Iris Main World Pack Download");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
return 1;
|
||||
IrisModdedCommands.fail(source, "Pack '" + pack
|
||||
+ "' is not installed. Use /iris download pack=overworld or pack=underworld, then restart.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int applyMainWorld(CommandSourceStack source, String pack, String packDimension, String packRef, long seed) {
|
||||
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ModdedDownloadBranchParityTest {
|
||||
private static final List<String> DOWNLOAD_SOURCES = List.of(
|
||||
"art/arcane/iris/modded/command/ModdedWorldCommands.java",
|
||||
"art/arcane/iris/modded/command/ModdedStudioCommands.java",
|
||||
"art/arcane/iris/modded/command/ModdedCommandTree.java");
|
||||
|
||||
@Test
|
||||
public void implicitAndExplicitDownloadsShareTheCoreDefaultBranch() throws Exception {
|
||||
for (String source : DOWNLOAD_SOURCES) {
|
||||
Path path = Path.of(System.getProperty("iris.moddedCommonSources"), source);
|
||||
String text = Files.readString(path);
|
||||
assertFalse(source + " must not hardcode a \"master\" download branch",
|
||||
text.contains("\"master\""));
|
||||
assertFalse(source + " must not hardcode a \"stable\" download branch",
|
||||
text.contains("\"stable\""));
|
||||
assertTrue(source + " must use PackDownloader.DEFAULT_BRANCH",
|
||||
text.contains("PackDownloader.DEFAULT_BRANCH"));
|
||||
}
|
||||
}
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Iris is a World Generator for Minecraft Servers
|
||||
* Copyright (c) 2026 Arcane Arts (Volmit Software)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package art.arcane.iris.modded;
|
||||
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ModdedPackInstallerTest {
|
||||
@Test
|
||||
public void managedPacksIgnoreTheRequestedBranch() {
|
||||
assertTrue(ModdedPackInstaller.acceptsBranch("overworld", null));
|
||||
assertTrue(ModdedPackInstaller.acceptsBranch("underworld", "feature/arbitrary"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonManagedPacksStillRequireAValidBranch() {
|
||||
assertTrue(ModdedPackInstaller.acceptsBranch("custom", "stable"));
|
||||
assertFalse(ModdedPackInstaller.acceptsBranch("custom", null));
|
||||
assertFalse(ModdedPackInstaller.acceptsBranch("custom", "feature/arbitrary"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startupBatchDefersDatapackRefresh() {
|
||||
PackDownloader.PackInstallResult changed = new PackDownloader.PackInstallResult("underworld", true, true);
|
||||
|
||||
assertFalse(ModdedPackInstaller.shouldRefreshDatapack(changed, false));
|
||||
assertTrue(ModdedPackInstaller.shouldRefreshDatapack(changed, true));
|
||||
assertFalse(ModdedPackInstaller.shouldRefreshDatapack(
|
||||
new PackDownloader.PackInstallResult("underworld", false, false),
|
||||
true
|
||||
));
|
||||
}
|
||||
}
|
||||
+25
-6
@@ -10,7 +10,9 @@ import org.junit.Test;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class IrisModdedCommandParityTest {
|
||||
@@ -50,17 +52,34 @@ public class IrisModdedCommandParityTest {
|
||||
child(studio, "pkg");
|
||||
|
||||
CommandNode<CommandSourceStack> download = child(iris, "download");
|
||||
CommandNode<CommandSourceStack> pack = child(download, "pack");
|
||||
child(pack, "force");
|
||||
child(pack, "overwrite");
|
||||
CommandNode<CommandSourceStack> branch = child(pack, "branch");
|
||||
child(branch, "force");
|
||||
child(branch, "overwrite");
|
||||
CommandNode<CommandSourceStack> source = child(download, "source");
|
||||
assertTrue(source.getChildren().isEmpty());
|
||||
|
||||
assertSame(iris, child(dispatcher.getRoot(), "ir").getRedirect());
|
||||
assertSame(iris, child(dispatcher.getRoot(), "irs").getRedirect());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void downloadRequestAcceptsOnlyBuiltInsAndZipLinks() {
|
||||
IrisModdedCommands.DownloadRequest overworld = IrisModdedCommands.parseDownloadRequest("pack=overworld");
|
||||
IrisModdedCommands.DownloadRequest underworld = IrisModdedCommands.parseDownloadRequest("pack=UNDERWORLD");
|
||||
IrisModdedCommands.DownloadRequest link = IrisModdedCommands.parseDownloadRequest(
|
||||
"link=https://packs.example.test/custom.zip?token=a=b"
|
||||
);
|
||||
|
||||
assertNotNull(overworld);
|
||||
assertEquals("overworld", overworld.pack());
|
||||
assertNotNull(underworld);
|
||||
assertEquals("underworld", underworld.pack());
|
||||
assertNotNull(link);
|
||||
assertEquals("https://packs.example.test/custom.zip?token=a=b", link.url());
|
||||
assertNull(IrisModdedCommands.parseDownloadRequest("overworld"));
|
||||
assertNull(IrisModdedCommands.parseDownloadRequest("pack=custom"));
|
||||
assertNull(IrisModdedCommands.parseDownloadRequest("link=https://packs.example.test/custom.tar.gz"));
|
||||
assertNull(IrisModdedCommands.parseDownloadRequest("pack=underworld branch=stable"));
|
||||
assertNull(IrisModdedCommands.parseDownloadRequest("pack=underworld overwrite=true"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void helpDocumentsParityCommandsAndPlatformStubs() {
|
||||
assertTrue(ModdedCommandHelp.documents("what", "here"));
|
||||
|
||||
Reference in New Issue
Block a user