mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 04:37:47 +00:00
s
This commit is contained in:
+1
-1
@@ -260,7 +260,7 @@ public final class ModdedEngineBootstrap {
|
||||
selfTest(moddedLoader.getClass().getClassLoader());
|
||||
bind();
|
||||
IrisLanguage.initialize();
|
||||
ModdedStartup.prefetchDefaultPack();
|
||||
ModdedStartup.prefetchStartupDatapack();
|
||||
if (!moddedLoader.clientEnvironment()) {
|
||||
MainWorldService.reconcileEarly();
|
||||
}
|
||||
|
||||
@@ -253,8 +253,6 @@ public final class ModdedForcedDatapack {
|
||||
}
|
||||
|
||||
private static Path write() throws IOException {
|
||||
// No ensureDefaultPack() here: write() is reachable from loadPacks on the first boot, and loadPacks
|
||||
// must never touch the network. ModdedStartup.prefetchDefaultPack covers the download at boot.
|
||||
String packsHash = packsHash();
|
||||
Path datapackRoot = datapackRoot();
|
||||
Files.createDirectories(datapackRoot);
|
||||
|
||||
@@ -33,17 +33,15 @@ public final class ModdedModConfig {
|
||||
private static volatile ModdedModConfig instance;
|
||||
|
||||
private final String defaultPack;
|
||||
private final boolean autoDownloadDefaultPack;
|
||||
private final String primaryWorld;
|
||||
private final boolean routePlayersToPrimaryWorld;
|
||||
private final String mainWorldPack;
|
||||
private final long mainWorldSeed;
|
||||
private final boolean mainWorldAutoRestart;
|
||||
|
||||
private ModdedModConfig(String defaultPack, boolean autoDownloadDefaultPack, String primaryWorld, boolean routePlayersToPrimaryWorld,
|
||||
private ModdedModConfig(String defaultPack, String primaryWorld, boolean routePlayersToPrimaryWorld,
|
||||
String mainWorldPack, long mainWorldSeed, boolean mainWorldAutoRestart) {
|
||||
this.defaultPack = defaultPack;
|
||||
this.autoDownloadDefaultPack = autoDownloadDefaultPack;
|
||||
this.primaryWorld = primaryWorld == null ? "" : primaryWorld.trim();
|
||||
this.routePlayersToPrimaryWorld = routePlayersToPrimaryWorld;
|
||||
this.mainWorldPack = mainWorldPack == null ? "" : mainWorldPack.trim();
|
||||
@@ -68,7 +66,7 @@ public final class ModdedModConfig {
|
||||
public static void setPrimaryWorld(String dimensionId) {
|
||||
synchronized (LOCK) {
|
||||
ModdedModConfig current = get();
|
||||
ModdedModConfig updated = new ModdedModConfig(current.defaultPack, current.autoDownloadDefaultPack, dimensionId, current.routePlayersToPrimaryWorld,
|
||||
ModdedModConfig updated = new ModdedModConfig(current.defaultPack, dimensionId, current.routePlayersToPrimaryWorld,
|
||||
current.mainWorldPack, current.mainWorldSeed, current.mainWorldAutoRestart);
|
||||
instance = updated;
|
||||
write(configFile(), updated);
|
||||
@@ -78,7 +76,7 @@ public final class ModdedModConfig {
|
||||
public static void setMainWorld(String packRef, long seed) {
|
||||
synchronized (LOCK) {
|
||||
ModdedModConfig current = get();
|
||||
ModdedModConfig updated = new ModdedModConfig(current.defaultPack, current.autoDownloadDefaultPack, current.primaryWorld, current.routePlayersToPrimaryWorld,
|
||||
ModdedModConfig updated = new ModdedModConfig(current.defaultPack, current.primaryWorld, current.routePlayersToPrimaryWorld,
|
||||
packRef == null ? "" : packRef.trim(), seed, current.mainWorldAutoRestart);
|
||||
instance = updated;
|
||||
write(configFile(), updated);
|
||||
@@ -89,10 +87,6 @@ public final class ModdedModConfig {
|
||||
return defaultPack;
|
||||
}
|
||||
|
||||
public boolean autoDownloadDefaultPack() {
|
||||
return autoDownloadDefaultPack;
|
||||
}
|
||||
|
||||
public String primaryWorld() {
|
||||
return primaryWorld;
|
||||
}
|
||||
@@ -119,7 +113,7 @@ public final class ModdedModConfig {
|
||||
|
||||
private static ModdedModConfig load() {
|
||||
Path file = configFile();
|
||||
ModdedModConfig defaults = new ModdedModConfig("overworld", true, "", true, "", 0L, false);
|
||||
ModdedModConfig defaults = new ModdedModConfig("overworld", "", true, "", 0L, false);
|
||||
if (!Files.isRegularFile(file)) {
|
||||
write(file, defaults);
|
||||
return defaults;
|
||||
@@ -128,7 +122,6 @@ public final class ModdedModConfig {
|
||||
JSONObject json = new JSONObject(Files.readString(file, StandardCharsets.UTF_8));
|
||||
return new ModdedModConfig(
|
||||
json.optString("defaultPack", defaults.defaultPack),
|
||||
json.optBoolean("autoDownloadDefaultPack", defaults.autoDownloadDefaultPack),
|
||||
json.optString("primaryWorld", defaults.primaryWorld),
|
||||
json.optBoolean("routePlayersToPrimaryWorld", defaults.routePlayersToPrimaryWorld),
|
||||
json.optString("mainWorldPack", defaults.mainWorldPack),
|
||||
@@ -143,7 +136,6 @@ public final class ModdedModConfig {
|
||||
private static void write(Path file, ModdedModConfig config) {
|
||||
JSONObject json = new JSONObject();
|
||||
json.put("defaultPack", config.defaultPack);
|
||||
json.put("autoDownloadDefaultPack", config.autoDownloadDefaultPack);
|
||||
json.put("primaryWorld", config.primaryWorld);
|
||||
json.put("routePlayersToPrimaryWorld", config.routePlayersToPrimaryWorld);
|
||||
json.put("mainWorldPack", config.mainWorldPack);
|
||||
|
||||
+5
-5
@@ -48,7 +48,7 @@ public final class ModdedPackInstaller {
|
||||
feedback.accept(IrisLanguage.plain(PackDownloadMessages.INVALID_PACK_NAME, MessageArgument.untrusted("pack", String.valueOf(pack))));
|
||||
return false;
|
||||
}
|
||||
boolean managedBeta = PackDownloader.isManagedBetaPack(pack);
|
||||
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;
|
||||
@@ -58,8 +58,8 @@ public final class ModdedPackInstaller {
|
||||
synchronized (installLock) {
|
||||
File packs = configDir.resolve("irisworldgen").resolve("packs").toFile();
|
||||
try {
|
||||
PackDownloader.PackInstallResult result = managedBeta
|
||||
? PackDownloader.downloadManagedBeta(packs, pack, forceOverwrite, feedback)
|
||||
PackDownloader.PackInstallResult result = managed
|
||||
? PackDownloader.downloadManaged(packs, pack, forceOverwrite, feedback)
|
||||
: PackDownloader.download(
|
||||
packs,
|
||||
"IrisDimensions/" + pack,
|
||||
@@ -84,7 +84,7 @@ public final class ModdedPackInstaller {
|
||||
}
|
||||
return installed;
|
||||
} catch (IOException error) {
|
||||
String source = managedBeta ? "beta release" : "branch " + branch;
|
||||
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,
|
||||
@@ -97,7 +97,7 @@ public final class ModdedPackInstaller {
|
||||
}
|
||||
|
||||
static boolean acceptsBranch(String pack, String branch) {
|
||||
return PackDownloader.isManagedBetaPack(pack)
|
||||
return PackDownloader.isManagedPack(pack)
|
||||
|| (branch != null && BRANCH_NAME.matcher(branch).matches());
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -47,7 +46,6 @@ public final class ModdedStartup {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Iris");
|
||||
private static final AtomicBoolean PREPARED = new AtomicBoolean(false);
|
||||
private static final AtomicBoolean STARTED = new AtomicBoolean(false);
|
||||
private static final Object PACK_LOCK = new Object();
|
||||
|
||||
private ModdedStartup() {
|
||||
}
|
||||
@@ -69,14 +67,13 @@ public final class ModdedStartup {
|
||||
* ModdedEngineBootstrap.start clears the async queue at SERVER_STARTING, which would silently drop this
|
||||
* one-shot task, and the datapack must be regenerated before the level PackRepository reload if it can.
|
||||
*/
|
||||
public static void prefetchDefaultPack() {
|
||||
Thread thread = new Thread(ModdedStartup::refreshPacksAndDatapack, "iris-modded-pack-prefetch");
|
||||
public static void prefetchStartupDatapack() {
|
||||
Thread thread = new Thread(ModdedStartup::refreshDatapack, "iris-modded-datapack-prefetch");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private static void refreshPacksAndDatapack() {
|
||||
ensureDefaultPack();
|
||||
private static void refreshDatapack() {
|
||||
try {
|
||||
ModdedForcedDatapack.regenerateIfStale("boot");
|
||||
} catch (Throwable failure) {
|
||||
@@ -98,10 +95,10 @@ public final class ModdedStartup {
|
||||
|
||||
ModdedScheduler scheduler = ModdedEngineBootstrap.schedulerOrNull();
|
||||
if (scheduler == null) {
|
||||
refreshPacksAndDatapack();
|
||||
refreshDatapack();
|
||||
return;
|
||||
}
|
||||
scheduler.async(ModdedStartup::refreshPacksAndDatapack);
|
||||
scheduler.async(ModdedStartup::refreshDatapack);
|
||||
}
|
||||
|
||||
public static void validateAllPacks() {
|
||||
@@ -248,45 +245,4 @@ public final class ModdedStartup {
|
||||
}
|
||||
}
|
||||
|
||||
public static void ensureDefaultPack() {
|
||||
synchronized (PACK_LOCK) {
|
||||
ModdedModConfig config = ModdedModConfig.get();
|
||||
if (!config.autoDownloadDefaultPack()) {
|
||||
return;
|
||||
}
|
||||
Path configDir = ModdedEngineBootstrap.loader().configDir();
|
||||
File packsRoot = ModdedPackCommands.packsRoot();
|
||||
for (String pack : startupPacks(config.defaultPack())) {
|
||||
ensureStartupPack(configDir, packsRoot, pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static List<String> startupPacks(String configuredDefault) {
|
||||
LinkedHashSet<String> packs = new LinkedHashSet<>(PackDownloader.managedBetaPacks());
|
||||
if (configuredDefault != null && !configuredDefault.isBlank()) {
|
||||
packs.add(configuredDefault);
|
||||
}
|
||||
return List.copyOf(packs);
|
||||
}
|
||||
|
||||
private static void ensureStartupPack(Path configDir, File packsRoot, String pack) {
|
||||
boolean present = PackDownloader.isManagedBetaPack(pack)
|
||||
? PackDownloader.isManagedBetaPackPresent(packsRoot, pack)
|
||||
: PackDownloader.isPackPresent(packsRoot, pack);
|
||||
if (present) {
|
||||
return;
|
||||
}
|
||||
boolean managedBeta = PackDownloader.isManagedBetaPack(pack);
|
||||
String branch = managedBeta ? "beta" : "master";
|
||||
String source = managedBeta ? "beta release" : "master branch";
|
||||
String role = managedBeta ? "managed beta pack" : "default pack";
|
||||
LOGGER.info("Iris {} '{}' missing; downloading IrisDimensions/{} ({})", role, pack, pack, source);
|
||||
boolean installed = ModdedPackInstaller.install(
|
||||
configDir, pack, branch, false, false,
|
||||
(String line) -> LOGGER.info("Iris: {}", line));
|
||||
if (!installed) {
|
||||
LOGGER.warn("Iris {} '{}' could not be downloaded; install it with /iris download {}", role, pack, pack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+27
-6
@@ -49,6 +49,8 @@ import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -258,8 +260,10 @@ public final class IrisModdedCommands {
|
||||
|
||||
static int download(CommandSourceStack source, String pack,
|
||||
String branch, boolean forceOverwrite) {
|
||||
boolean managedBeta = PackDownloader.isManagedBetaPack(pack);
|
||||
String baseDownloadSource = managedBeta ? "beta release" : "branch " + branch;
|
||||
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;
|
||||
@@ -273,11 +277,28 @@ public final class IrisModdedCommands {
|
||||
return 0;
|
||||
}
|
||||
scheduler.async(() -> {
|
||||
boolean installed = ModdedPackInstaller.install(
|
||||
ModdedEngineBootstrap.loader().configDir(), pack, branch, forceOverwrite, true,
|
||||
(String message) -> scheduler.global(() -> ok(source, message)));
|
||||
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)));
|
||||
}
|
||||
if (installed) {
|
||||
scheduler.global(() -> ok(source, IrisLanguage.plain(ModdedCommandMessages.IRIS_MODDED_COMMANDS_PACK_INSTALLED_ITS_EXACT_DIMENSION_TYPES_CUSTOM_BIOMES_JOIN_FORCED, MessageArgument.untrusted("pack", pack))));
|
||||
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))));
|
||||
}
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class ModdedPackInstallerTest {
|
||||
@Test
|
||||
public void managedBetaPacksIgnoreTheRequestedBranch() {
|
||||
public void managedPacksIgnoreTheRequestedBranch() {
|
||||
assertTrue(ModdedPackInstaller.acceptsBranch("overworld", null));
|
||||
assertTrue(ModdedPackInstaller.acceptsBranch("underworld", "feature/arbitrary"));
|
||||
}
|
||||
|
||||
-41
@@ -1,41 +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 org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ModdedStartupPackSelectionTest {
|
||||
@Test
|
||||
public void managedBetaPacksAreAlwaysInstalledInStableOrder() {
|
||||
assertEquals(List.of("overworld", "underworld"), ModdedStartup.startupPacks("overworld"));
|
||||
assertEquals(List.of("overworld", "underworld"), ModdedStartup.startupPacks("underworld"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configuredNonManagedDefaultIsInstalledAfterManagedBetaPacks() {
|
||||
assertEquals(
|
||||
List.of("overworld", "underworld", "custom"),
|
||||
ModdedStartup.startupPacks("custom")
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user