mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 12:41:43 +00:00
f
This commit is contained in:
@@ -60,6 +60,7 @@ import java.nio.file.Files;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@@ -134,6 +135,12 @@ public class CommandIris implements DirectorExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
Optional<String> startupDenial = ServerConfigurator.worldCreationDenialReason(false);
|
||||
if (startupDenial.isPresent()) {
|
||||
sender().sendMessage(C.YELLOW + startupDenial.get());
|
||||
return;
|
||||
}
|
||||
|
||||
String resolvedType = type.equalsIgnoreCase("default")
|
||||
? IrisSettings.get().getGenerator().getDefaultWorldType()
|
||||
: type;
|
||||
|
||||
+4
-2
@@ -120,9 +120,11 @@ public class CommandStudio implements DirectorExecutor {
|
||||
@Param(description = "The dimension pack to open a studio for", descriptionKey = "iris.director.commandstudio.param.dimension_pack_open_studio", aliases = "dim", customHandler = DimensionHandler.class)
|
||||
IrisDimension dimension,
|
||||
@Param(defaultValue = "1337", description = "The seed to generate the studio with", descriptionKey = "iris.director.commandstudio.param.seed_generate_studio_with", aliases = "s")
|
||||
long seed) {
|
||||
long seed,
|
||||
@Param(defaultValue = "false", description = "Attempt to open Studio before a required registry restart", aliases = "f")
|
||||
boolean force) {
|
||||
sender().sendMessage(IrisLanguage.text(BukkitCommandMessagesExtended.COMMAND_STUDIO_OPENING_STUDIO_PACK_SEED, MessageArgument.untrusted("value", dimension.getName()), MessageArgument.untrusted("seed", seed)));
|
||||
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey());
|
||||
Iris.service(StudioSVC.class).open(sender(), seed, dimension.getLoadKey(), force);
|
||||
}
|
||||
|
||||
@Director(description = "Import vanilla trees, mushrooms & objects (and structures/jigsaw) from the server into a pack's objects/vanilla folder", descriptionKey = "iris.director.commandstudio.director.import_vanilla_trees_mushrooms_objects_structures_jigsaw_from_server_into_pack_s", aliases = {"importv", "iv"}, origin = DirectorOrigin.BOTH)
|
||||
|
||||
+16
@@ -8,9 +8,11 @@ import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class CommandStudioCreationContractTest {
|
||||
@Test
|
||||
@@ -24,4 +26,18 @@ public class CommandStudioCreationContractTest {
|
||||
assertEquals("null", template.defaultValue());
|
||||
assertEquals(NullableDimensionHandler.class, template.customHandler());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openExposesAnOptInForceFlag() throws NoSuchMethodException {
|
||||
Method command = CommandStudio.class.getDeclaredMethod(
|
||||
"open",
|
||||
IrisDimension.class,
|
||||
long.class,
|
||||
boolean.class
|
||||
);
|
||||
Param force = command.getParameters()[2].getAnnotation(Param.class);
|
||||
|
||||
assertEquals("false", force.defaultValue());
|
||||
assertTrue(List.of(force.aliases()).contains("f"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,21 @@ public final class IrisStartupValidation {
|
||||
}
|
||||
|
||||
public static Optional<String> denialReason() {
|
||||
return denialReason(snapshot);
|
||||
}
|
||||
|
||||
public static Optional<String> studioDenialReason(boolean force) {
|
||||
Snapshot current = snapshot;
|
||||
if (force
|
||||
&& current.enforced()
|
||||
&& current.datapacks() == ValidationState.RESTART_REQUIRED
|
||||
&& current.packs() == ValidationState.READY) {
|
||||
return Optional.empty();
|
||||
}
|
||||
return denialReason(current);
|
||||
}
|
||||
|
||||
private static Optional<String> denialReason(Snapshot current) {
|
||||
if (!current.enforced() || isReady(current)) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
@@ -171,12 +172,34 @@ public class ServerConfigurator {
|
||||
}
|
||||
|
||||
public static void requireDatapackRestart() {
|
||||
requireWorldCreationRestart();
|
||||
IrisStartupValidation.requireRestart(
|
||||
"Iris datapack changes require a restart before player admission or world creation.");
|
||||
}
|
||||
|
||||
public static void requireWorldCreationRestart() {
|
||||
synchronized (DATAPACK_INSTALL_LOCK) {
|
||||
invalidateLoadedDatapackRuntime();
|
||||
loadedDatapackRestartRequired = true;
|
||||
}
|
||||
IrisStartupValidation.requireRestart(
|
||||
"Iris datapack changes require a restart before player admission or world creation.");
|
||||
}
|
||||
|
||||
public static Optional<String> worldCreationDenialReason(boolean forceStudio) {
|
||||
Optional<String> startupDenial = IrisStartupValidation.studioDenialReason(forceStudio);
|
||||
if (startupDenial.isPresent()) {
|
||||
return startupDenial;
|
||||
}
|
||||
if (!forceStudio && loadedDatapackRestartRequired) {
|
||||
return Optional.of("Iris installed or updated a dimension pack that requires a server restart before world creation or Studio open.");
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static void requireWorldCreationReady(boolean forceStudio) {
|
||||
Optional<String> denial = worldCreationDenialReason(forceStudio);
|
||||
if (denial.isPresent()) {
|
||||
throw new IllegalStateException("Iris world creation is locked: " + denial.get());
|
||||
}
|
||||
}
|
||||
|
||||
public static void restoreLoadedDatapackRuntimeIfUnchanged(
|
||||
|
||||
@@ -2,6 +2,7 @@ package art.arcane.iris.core.lifecycle;
|
||||
|
||||
public enum WorldLifecycleCaller {
|
||||
STUDIO,
|
||||
FORCED_STUDIO,
|
||||
CREATE,
|
||||
BENCHMARK
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package art.arcane.iris.core.lifecycle;
|
||||
|
||||
import art.arcane.iris.core.IrisStartupValidation;
|
||||
import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.spi.IrisLogging;
|
||||
import art.arcane.iris.core.tools.IrisToolbelt;
|
||||
@@ -77,7 +76,11 @@ public final class WorldLifecycleService {
|
||||
public CompletableFuture<World> create(WorldLifecycleRequest request) {
|
||||
WorldLifecycleBackend backend;
|
||||
try {
|
||||
IrisStartupValidation.requireWorldCreationReady();
|
||||
if (request.callerKind() == WorldLifecycleCaller.FORCED_STUDIO) {
|
||||
ServerConfigurator.requireWorldCreationReady(true);
|
||||
} else {
|
||||
ServerConfigurator.requireWorldCreationReady(false);
|
||||
}
|
||||
backend = selectCreateBackend(request);
|
||||
} catch (Throwable e) {
|
||||
IrisLogging.reportError("WorldLifecycle create backend selection failed for world=\"" + request.worldName()
|
||||
|
||||
@@ -119,7 +119,7 @@ public final class StudioOpenCoordinator {
|
||||
return CompletableFuture.failedFuture(new IllegalStateException(
|
||||
"Studio entry point could not be resolved."));
|
||||
}
|
||||
CompletableFuture<Boolean> teleport = project.getActiveOpenKind() == StudioOpenKind.STANDARD
|
||||
CompletableFuture<Boolean> teleport = project.getActiveOpenKind().teleportThroughStandardEntry()
|
||||
? WorldRuntimeControlService.get().teleportInMode(player, entry, GameMode.SPECTATOR)
|
||||
: WorldRuntimeControlService.get().teleport(player, entry);
|
||||
if (teleport == null) {
|
||||
@@ -914,6 +914,10 @@ public final class StudioOpenCoordinator {
|
||||
true,
|
||||
true,
|
||||
IrisCreator.DatapackPreparation.REUSE_LOADED_RUNTIME_IF_READY),
|
||||
FORCED_STANDARD(
|
||||
true,
|
||||
true,
|
||||
IrisCreator.DatapackPreparation.FORCE_REUSE_LOADED_RUNTIME),
|
||||
OBJECT(
|
||||
false,
|
||||
true,
|
||||
|
||||
@@ -420,6 +420,7 @@ public class StudioSVC implements IrisService {
|
||||
reporter.fail(null);
|
||||
return;
|
||||
}
|
||||
retainPackRestartRequirement(result);
|
||||
reporter.succeed(result);
|
||||
}, "Failed to download built-in Iris pack '" + key + "'.");
|
||||
}
|
||||
@@ -447,6 +448,7 @@ public class StudioSVC implements IrisService {
|
||||
reporter.fail(null);
|
||||
return;
|
||||
}
|
||||
retainPackRestartRequirement(result);
|
||||
reporter.succeed(result);
|
||||
}, "Failed to download Iris pack.");
|
||||
}
|
||||
@@ -491,8 +493,15 @@ public class StudioSVC implements IrisService {
|
||||
}
|
||||
|
||||
public void open(VolmitSender sender, long seed, String dimm) {
|
||||
open(sender, seed, dimm, false);
|
||||
}
|
||||
|
||||
public void open(VolmitSender sender, long seed, String dimm, boolean force) {
|
||||
try {
|
||||
open(sender, seed, dimm, (w) -> {
|
||||
StudioOpenCoordinator.StudioOpenKind openKind = force
|
||||
? StudioOpenCoordinator.StudioOpenKind.FORCED_STANDARD
|
||||
: StudioOpenCoordinator.StudioOpenKind.STANDARD;
|
||||
open(sender, seed, dimm, openKind, (w) -> {
|
||||
});
|
||||
} catch (Exception e) {
|
||||
IrisLogging.reportError("Failed to open studio world \"" + dimm + "\".", e);
|
||||
@@ -501,8 +510,13 @@ public class StudioSVC implements IrisService {
|
||||
}
|
||||
|
||||
private static BrokenPackException reportPackAdmissionFailure(
|
||||
VolmitSender sender, String dimm) {
|
||||
Optional<String> startupDenial = IrisStartupValidation.denialReason();
|
||||
VolmitSender sender,
|
||||
String dimm,
|
||||
StudioOpenCoordinator.StudioOpenKind openKind
|
||||
) {
|
||||
boolean force = openKind == StudioOpenCoordinator.StudioOpenKind.FORCED_STANDARD;
|
||||
Optional<String> unforcedStartupDenial = ServerConfigurator.worldCreationDenialReason(false);
|
||||
Optional<String> startupDenial = ServerConfigurator.worldCreationDenialReason(force);
|
||||
IrisDimension dimension = IrisToolbelt.getDimension(dimm);
|
||||
String packName = dimension == null || dimension.getLoader() == null
|
||||
? dimm
|
||||
@@ -511,6 +525,9 @@ public class StudioSVC implements IrisService {
|
||||
BrokenPackException failure = resolvePackAdmissionFailure(
|
||||
packName, startupDenial, validation);
|
||||
if (failure == null) {
|
||||
if (force && unforcedStartupDenial.isPresent()) {
|
||||
sender.sendMessage("Force-opening Studio with the currently loaded registry state. The open may fail; restart remains required.");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (startupDenial.isPresent()) {
|
||||
@@ -525,6 +542,12 @@ public class StudioSVC implements IrisService {
|
||||
return failure;
|
||||
}
|
||||
|
||||
static void retainPackRestartRequirement(PackDownloader.PackInstallResult result) {
|
||||
if (result != null && result.restartRequired()) {
|
||||
ServerConfigurator.requireWorldCreationRestart();
|
||||
}
|
||||
}
|
||||
|
||||
static BrokenPackException resolvePackAdmissionFailure(
|
||||
String packName,
|
||||
Optional<String> startupDenial,
|
||||
@@ -554,7 +577,7 @@ public class StudioSVC implements IrisService {
|
||||
Consumer<World> onDone
|
||||
) throws IrisException {
|
||||
long requestedAtNanos = System.nanoTime();
|
||||
if (reportPackAdmissionFailure(sender, dimm) != null) {
|
||||
if (reportPackAdmissionFailure(sender, dimm, openKind) != null) {
|
||||
return;
|
||||
}
|
||||
StudioOpenCoordinator.StudioOpenKind requiredOpenKind = Objects.requireNonNull(
|
||||
@@ -587,7 +610,7 @@ public class StudioSVC implements IrisService {
|
||||
Consumer<World> onDone
|
||||
) {
|
||||
long requestedAtNanos = System.nanoTime();
|
||||
BrokenPackException failure = reportPackAdmissionFailure(sender, dimension);
|
||||
BrokenPackException failure = reportPackAdmissionFailure(sender, dimension, openKind);
|
||||
if (failure != null) {
|
||||
return CompletableFuture.failedFuture(failure);
|
||||
}
|
||||
@@ -1027,9 +1050,7 @@ public class StudioSVC implements IrisService {
|
||||
closeLease(lease);
|
||||
}
|
||||
|
||||
if (outcome == CreationOutcome.RESTART) {
|
||||
ServerConfigurator.restart();
|
||||
} else if (outcome == CreationOutcome.OPEN) {
|
||||
if (outcome == CreationOutcome.OPEN) {
|
||||
String completedProjectName = projectName;
|
||||
LifecycleOperationCoordinator.get().whenIdle(() -> open(sender, completedProjectName));
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import art.arcane.iris.spi.IrisServices;
|
||||
import art.arcane.iris.platform.bukkit.BukkitPlatform;
|
||||
import art.arcane.iris.core.link.MultiverseCoreLink;
|
||||
import art.arcane.iris.core.IrisRuntimeSchedulerMode;
|
||||
import art.arcane.iris.core.IrisStartupValidation;
|
||||
import art.arcane.iris.core.DatapackInstallResult;
|
||||
import art.arcane.iris.core.IrisWorldStorage;
|
||||
import art.arcane.iris.core.IrisWorlds;
|
||||
@@ -182,7 +181,7 @@ public class IrisCreator {
|
||||
throw new IrisException("Dimension cannot be found for id " + dimension());
|
||||
}
|
||||
reportCreationProgress(creationReporter, 0.06D, "validate_pack");
|
||||
IrisStartupValidation.requireWorldCreationReady();
|
||||
ServerConfigurator.requireWorldCreationReady(datapackPreparation.forcesLoadedRuntime());
|
||||
PackValidationRegistry.requireLoadable(
|
||||
resolvedDimension.getLoader().getDataFolder().getName());
|
||||
worldLease = coordinator.acquire(
|
||||
@@ -253,10 +252,11 @@ public class IrisCreator {
|
||||
if (!datapackResult.succeeded()) {
|
||||
throw new IrisException("Failed to compile datapacks for dimension \"" + dimension() + "\".");
|
||||
}
|
||||
if (datapackResult.restartRequired() || !ServerConfigurator.verifyDataPackInstalled(resolvedDimension)) {
|
||||
ServerConfigurator.restart();
|
||||
if (!datapackPreparation.forcesLoadedRuntime()
|
||||
&& (datapackResult.restartRequired()
|
||||
|| !ServerConfigurator.verifyDataPackInstalled(resolvedDimension))) {
|
||||
throw new IrisException("The dimension types for pack \"" + dimension() + "\" are not loaded yet. "
|
||||
+ "Iris queued a restart; run the command again after the server returns.");
|
||||
+ "Restart the server, then run the command again.");
|
||||
}
|
||||
|
||||
IrisDimension installedDimension = resolvedDimension;
|
||||
@@ -301,7 +301,13 @@ public class IrisCreator {
|
||||
reportCreationProgress(creationReporter, 0.44D, "create_world");
|
||||
long nmsStartNanos = System.nanoTime();
|
||||
try {
|
||||
WorldLifecycleCaller callerKind = benchmark ? WorldLifecycleCaller.BENCHMARK : studio() ? WorldLifecycleCaller.STUDIO : WorldLifecycleCaller.CREATE;
|
||||
WorldLifecycleCaller callerKind = benchmark
|
||||
? WorldLifecycleCaller.BENCHMARK
|
||||
: studio() && datapackPreparation.forcesLoadedRuntime()
|
||||
? WorldLifecycleCaller.FORCED_STUDIO
|
||||
: studio()
|
||||
? WorldLifecycleCaller.STUDIO
|
||||
: WorldLifecycleCaller.CREATE;
|
||||
WorldLifecycleRequest request = WorldLifecycleRequest.fromCreator(wc, studio(), benchmark, callerKind);
|
||||
world = J.sfut(() -> INMS.get().createWorldAsync(wc, request))
|
||||
.thenCompose(Function.identity())
|
||||
@@ -319,9 +325,8 @@ public class IrisCreator {
|
||||
throw new IrisException("Runtime world creation is blocked and the selected world lifecycle backend could not create the world.", e);
|
||||
}
|
||||
if (containsMissingDimensionTypes(e)) {
|
||||
ServerConfigurator.restart();
|
||||
throw new IrisException("The dimension types for pack \"" + dimension() + "\" are not loaded on this server yet. "
|
||||
+ "Iris queued a restart; run the command again after the server returns.", e);
|
||||
+ "Restart the server, then run the command again.", e);
|
||||
}
|
||||
throw new IrisException("Failed to create world with backend family " + WorldLifecycleService.get().capabilities().serverFamily().id() + "!", e);
|
||||
} finally {
|
||||
@@ -856,17 +861,24 @@ public class IrisCreator {
|
||||
}
|
||||
|
||||
public enum DatapackPreparation {
|
||||
INSTALL_IF_CHANGED(false),
|
||||
REUSE_LOADED_RUNTIME_IF_READY(true);
|
||||
INSTALL_IF_CHANGED(false, false),
|
||||
REUSE_LOADED_RUNTIME_IF_READY(true, false),
|
||||
FORCE_REUSE_LOADED_RUNTIME(true, true);
|
||||
|
||||
private final boolean reusesLoadedRuntime;
|
||||
private final boolean forcesLoadedRuntime;
|
||||
|
||||
DatapackPreparation(boolean reusesLoadedRuntime) {
|
||||
DatapackPreparation(boolean reusesLoadedRuntime, boolean forcesLoadedRuntime) {
|
||||
this.reusesLoadedRuntime = reusesLoadedRuntime;
|
||||
this.forcesLoadedRuntime = forcesLoadedRuntime;
|
||||
}
|
||||
|
||||
boolean requiresInstall(boolean runtimeReady) {
|
||||
return !reusesLoadedRuntime || !runtimeReady;
|
||||
return !forcesLoadedRuntime && (!reusesLoadedRuntime || !runtimeReady);
|
||||
}
|
||||
|
||||
public boolean forcesLoadedRuntime() {
|
||||
return forcesLoadedRuntime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,6 +107,20 @@ public class IrisStartupValidationTest {
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forceAllowsOnlyStudioAtACompletedRestartBoundary() {
|
||||
IrisStartupValidation.begin();
|
||||
IrisStartupValidation.markDatapacksReady();
|
||||
IrisStartupValidation.markPacksReady();
|
||||
IrisStartupValidation.requireRestart("restart boundary");
|
||||
|
||||
assertTrue(IrisStartupValidation.studioDenialReason(true).isEmpty());
|
||||
assertThrows(IllegalStateException.class, IrisStartupValidation::requireWorldCreationReady);
|
||||
|
||||
IrisStartupValidation.markPacksInvalid(List.of("pack validation failed"));
|
||||
assertFalse(IrisStartupValidation.studioDenialReason(true).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void packValidationInfrastructureFailureDeniesCreation() {
|
||||
IrisStartupValidation.begin();
|
||||
|
||||
+17
-2
@@ -27,14 +27,29 @@ public class StudioOpenCoordinatorOpenKindTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void allStudioKindsReuseOnlyAnUnchangedLoadedRuntime() {
|
||||
public void ordinaryStudioKindsReuseOnlyAnUnchangedLoadedRuntime() {
|
||||
for (StudioOpenCoordinator.StudioOpenKind kind : StudioOpenCoordinator.StudioOpenKind.values()) {
|
||||
if (kind == StudioOpenCoordinator.StudioOpenKind.FORCED_STANDARD) {
|
||||
continue;
|
||||
}
|
||||
assertEquals(
|
||||
IrisCreator.DatapackPreparation.REUSE_LOADED_RUNTIME_IF_READY,
|
||||
kind.datapackPreparation());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forcedStandardStudioAttemptsTheLoadedRuntime() {
|
||||
StudioOpenCoordinator.StudioOpenKind kind = StudioOpenCoordinator.StudioOpenKind.FORCED_STANDARD;
|
||||
|
||||
assertTrue(kind.openWorkspace());
|
||||
assertTrue(kind.teleportThroughStandardEntry());
|
||||
assertTrue(kind.prepareGeneratorState());
|
||||
assertEquals(
|
||||
IrisCreator.DatapackPreparation.FORCE_REUSE_LOADED_RUNTIME,
|
||||
kind.datapackPreparation());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void objectStudioOwnsWorkspaceWithoutUsingTheStandardEntry() {
|
||||
StudioOpenCoordinator.StudioOpenKind kind = StudioOpenCoordinator.StudioOpenKind.OBJECT;
|
||||
@@ -115,7 +130,7 @@ public class StudioOpenCoordinatorOpenKindTest {
|
||||
assertTrue(coordinatorMethod.contains(
|
||||
"WorldRuntimeControlService.get().resolveEntryAnchor(world, provider)"));
|
||||
assertTrue(coordinatorMethod.contains(
|
||||
"project.getActiveOpenKind() == StudioOpenKind.STANDARD"));
|
||||
"project.getActiveOpenKind().teleportThroughStandardEntry()"));
|
||||
assertFalse(coordinatorMethod.contains("requestChunkAsync("));
|
||||
assertFalse(coordinatorMethod.contains("getHighestBlockYAt("));
|
||||
assertTrue(nativeDelegation >= 0);
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
package art.arcane.iris.core.service;
|
||||
|
||||
import art.arcane.iris.core.IrisStartupValidation;
|
||||
import art.arcane.iris.core.ServerConfigurator;
|
||||
import art.arcane.iris.core.pack.BrokenPackException;
|
||||
import art.arcane.iris.core.pack.PackDownloader;
|
||||
import art.arcane.iris.core.pack.PackValidationResult;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class StudioSVCPackAdmissionTest {
|
||||
@After
|
||||
public void disableStartupValidation() {
|
||||
IrisStartupValidation.disable();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadablePackIsAdmitted() {
|
||||
PackValidationResult validation = new PackValidationResult(
|
||||
@@ -57,4 +68,25 @@ public class StudioSVCPackAdmissionTest {
|
||||
|
||||
assertEquals(List.of(denial), failure.getReasons());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void completedPackDownloadRetainsTheCreationGateWithoutDenyingLogin() throws Exception {
|
||||
Field restartRequired = ServerConfigurator.class.getDeclaredField("loadedDatapackRestartRequired");
|
||||
restartRequired.setAccessible(true);
|
||||
boolean previous = restartRequired.getBoolean(null);
|
||||
IrisStartupValidation.begin();
|
||||
IrisStartupValidation.markDatapacksReady();
|
||||
IrisStartupValidation.markPacksReady();
|
||||
|
||||
try {
|
||||
StudioSVC.retainPackRestartRequirement(
|
||||
new PackDownloader.PackInstallResult("overworld", true, true));
|
||||
|
||||
assertTrue(ServerConfigurator.worldCreationDenialReason(false).isPresent());
|
||||
assertTrue(ServerConfigurator.worldCreationDenialReason(true).isEmpty());
|
||||
assertTrue(IrisStartupValidation.denialReason().isEmpty());
|
||||
} finally {
|
||||
restartRequired.setBoolean(null, previous);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,4 +17,11 @@ public class IrisCreatorDatapackPreparationTest {
|
||||
assertTrue(IrisCreator.DatapackPreparation.REUSE_LOADED_RUNTIME_IF_READY.requiresInstall(false));
|
||||
assertFalse(IrisCreator.DatapackPreparation.REUSE_LOADED_RUNTIME_IF_READY.requiresInstall(true));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void forcedStudioCreationNeverInstallsDatapacks() {
|
||||
assertFalse(IrisCreator.DatapackPreparation.FORCE_REUSE_LOADED_RUNTIME.requiresInstall(false));
|
||||
assertFalse(IrisCreator.DatapackPreparation.FORCE_REUSE_LOADED_RUNTIME.requiresInstall(true));
|
||||
assertTrue(IrisCreator.DatapackPreparation.FORCE_REUSE_LOADED_RUNTIME.forcesLoadedRuntime());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user