mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-12 03:24:14 +00:00
Fixed Structure Crash
- Don't carash anymore when you disable structures in the server.properties.
This commit is contained in:
-32
@@ -195,8 +195,6 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
|
||||
if (!nativeGenerator.represents(level)) {
|
||||
throw new IllegalArgumentException("NativeWorld does not use Iris generator '" + dimensionKey + "'");
|
||||
}
|
||||
requireGlobalStructureGeneration(
|
||||
NativeModdedServer.forWorld(level).generateStructures(), dimensionKey);
|
||||
Engine activeEngine = engineIfBound();
|
||||
Engine replacement = ModdedWorldEngines.prepareReplacement(
|
||||
level,
|
||||
@@ -462,13 +460,6 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
|
||||
// A recorded failure stands until repoint or unbind resets the binding; re-running the bind would repeat the
|
||||
// history verification on every chunk call and fail the same way.
|
||||
engineBinding.throwIfFailed(dimensionKey);
|
||||
try {
|
||||
requireGlobalStructureGeneration(
|
||||
NativeModdedServer.forWorld(level).generateStructures(), dimensionKey);
|
||||
} catch (RuntimeException error) {
|
||||
recordBindFailure(level, error);
|
||||
throw error;
|
||||
}
|
||||
// Cache the owning level so hot paths never scan the level map to find themselves.
|
||||
boundLevel = level;
|
||||
Engine cached = engine;
|
||||
@@ -575,29 +566,6 @@ public final class IrisModdedChunkGenerator implements NativeGeneratorOwner, Nat
|
||||
}
|
||||
}
|
||||
|
||||
static void requireGlobalStructureGeneration(boolean enabled, String dimensionKey) {
|
||||
if (enabled) {
|
||||
return;
|
||||
}
|
||||
String remedy = integratedEnvironment()
|
||||
? "enable 'Generate Structures' for this world; Iris requires it, then deny families through "
|
||||
+ "importedStructures.disabled or complete keys through importedStructures.disabledExact"
|
||||
: "set generate-structures=true in server.properties, restart the server, "
|
||||
+ "then deny families through importedStructures.disabled or complete keys through "
|
||||
+ "importedStructures.disabledExact";
|
||||
throw new IllegalStateException("Iris generator '" + dimensionKey
|
||||
+ "' cannot bind while generate-structures=false; " + remedy);
|
||||
}
|
||||
|
||||
private static boolean integratedEnvironment() {
|
||||
try {
|
||||
return ModdedEngineBootstrap.loader().clientEnvironment();
|
||||
} catch (Throwable e) {
|
||||
// No loader bound (unit tests, very early boot): assume dedicated wording.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Null only while no level uses this generator (world creation screens, codec validation). A bound level whose
|
||||
* engine is refused, unloading or stopping throws, so no stage can mistake it for an unbound generator.
|
||||
|
||||
-11
@@ -122,17 +122,6 @@ final class ModdedNativeStructurePolicy implements NativeModdedStructureStage.Po
|
||||
return ((IrisMaterialPalette) source).get(rng, x, y, z, generator.engine().getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuntimeException structuresDisabled(int chunkX, int chunkZ) {
|
||||
return new IllegalStateException("Iris cannot generate native structures in chunk "
|
||||
+ chunkX + "," + chunkZ
|
||||
+ " because generate-structures=false disables them outside the pack. That flag is fixed when "
|
||||
+ "the world is created (server.properties generate-structures, or the Generate Structures "
|
||||
+ "toggle in singleplayer), so it cannot be changed for this world: create a new world with "
|
||||
+ "structures enabled, then deny families through importedStructures.disabled or complete keys "
|
||||
+ "through importedStructures.disabledExact");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generationLabel(String structureId) {
|
||||
return "Iris native structure " + structureId;
|
||||
|
||||
+8
-3
@@ -57,8 +57,11 @@ public class ModdedBindFailureTest {
|
||||
when(server.generateStructures()).thenReturn(false);
|
||||
|
||||
try (MockedStatic<NativeModdedServer> servers = mockStatic(NativeModdedServer.class);
|
||||
MockedStatic<ModdedWorldEngines> engines = mockStatic(ModdedWorldEngines.class);
|
||||
MockedStatic<ModdedIrisLog> log = mockStatic(ModdedIrisLog.class)) {
|
||||
servers.when(() -> NativeModdedServer.forWorld(level)).thenReturn(server);
|
||||
engines.when(() -> ModdedWorldEngines.get(eq(level), any(), any(), anyLong(), any()))
|
||||
.thenThrow(new IllegalStateException("broken world binding"));
|
||||
|
||||
IllegalStateException recorded = assertThrows(IllegalStateException.class, () -> generator.bindLevel(level));
|
||||
IllegalStateException second = assertThrows(IllegalStateException.class, generator::engine);
|
||||
@@ -66,9 +69,9 @@ public class ModdedBindFailureTest {
|
||||
|
||||
assertSame(recorded, second.getCause());
|
||||
assertSame(recorded, third.getCause());
|
||||
servers.verify(() -> NativeModdedServer.forWorld(level), times(1));
|
||||
engines.verify(() -> ModdedWorldEngines.get(eq(level), any(), any(), anyLong(), any()), times(1));
|
||||
log.verify(() -> ModdedIrisLog.error(argThat((String line) -> line != null && line.startsWith("Cause: ")
|
||||
&& line.contains("generate-structures=false"))), times(1));
|
||||
&& line.contains("broken world binding"))), times(1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,13 +120,15 @@ public class ModdedBindFailureTest {
|
||||
MockedStatic<ModdedWorldEngines> engines = mockStatic(ModdedWorldEngines.class);
|
||||
MockedStatic<ModdedIrisLog> log = mockStatic(ModdedIrisLog.class)) {
|
||||
servers.when(() -> NativeModdedServer.forWorld(level)).thenReturn(server);
|
||||
engines.when(() -> ModdedWorldEngines.get(eq(level), any(), any(), anyLong(), any()))
|
||||
.thenAnswer(invocation -> { throw new IllegalStateException("broken world binding"); });
|
||||
|
||||
IllegalStateException first = assertThrows(IllegalStateException.class, () -> generator.bindLevel(level));
|
||||
generator.unbindEngine(level);
|
||||
IllegalStateException second = assertThrows(IllegalStateException.class, () -> generator.bindLevel(level));
|
||||
|
||||
assertNotSame(first, second.getCause());
|
||||
servers.verify(() -> NativeModdedServer.forWorld(level), times(2));
|
||||
engines.verify(() -> ModdedWorldEngines.get(eq(level), any(), any(), anyLong(), any()), times(2));
|
||||
engines.verify(() -> ModdedWorldEngines.evictOrThrow(level));
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -37,7 +37,7 @@ public class ModdedStructureBindingOrderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initialBindingPublishesReadyEngineBeforeStartingStructureSearches() throws Exception {
|
||||
public void disabledStructuresAllowInitialBindingBeforeStartingStructureSearches() throws Exception {
|
||||
NativeModdedChunkGenerator<?, ?, ?> nativeGenerator = mock(NativeModdedChunkGenerator.class);
|
||||
ModdedEngineBinding<Engine> binding = new ModdedEngineBinding<>(1L, TimeUnit.MILLISECONDS);
|
||||
IrisModdedChunkGenerator generator = generator(nativeGenerator, binding);
|
||||
@@ -45,7 +45,7 @@ public class ModdedStructureBindingOrderTest {
|
||||
NativeModdedServer server = mock(NativeModdedServer.class);
|
||||
Engine engine = readyEngine();
|
||||
when(nativeGenerator.represents(world)).thenReturn(true);
|
||||
when(server.generateStructures()).thenReturn(true);
|
||||
when(server.generateStructures()).thenReturn(false);
|
||||
doAnswer(invocation -> {
|
||||
assertSame(engine, generator.awaitStructureEngine());
|
||||
assertSame(engine, binding.await("overworld"));
|
||||
@@ -88,7 +88,7 @@ public class ModdedStructureBindingOrderTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void repointPublishesReplacementBindingBeforeStartingStructureSearches() throws Exception {
|
||||
public void disabledStructuresAllowReplacementBindingBeforeStartingStructureSearches() throws Exception {
|
||||
NativeModdedChunkGenerator<?, ?, ?> nativeGenerator = mock(NativeModdedChunkGenerator.class);
|
||||
ModdedEngineBinding<Engine> binding = new ModdedEngineBinding<>(1L, TimeUnit.MILLISECONDS);
|
||||
IrisModdedChunkGenerator generator = generator(nativeGenerator, binding);
|
||||
@@ -96,7 +96,7 @@ public class ModdedStructureBindingOrderTest {
|
||||
NativeModdedServer server = mock(NativeModdedServer.class);
|
||||
Engine replacement = readyEngine();
|
||||
when(nativeGenerator.represents(world)).thenReturn(true);
|
||||
when(server.generateStructures()).thenReturn(true);
|
||||
when(server.generateStructures()).thenReturn(false);
|
||||
doAnswer(invocation -> {
|
||||
assertSame(replacement, generator.awaitStructureEngine());
|
||||
assertSame(replacement, binding.await("overworld"));
|
||||
|
||||
-16
@@ -7,7 +7,6 @@ import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class NativeStructureFailureContractTest {
|
||||
@@ -17,21 +16,6 @@ public class NativeStructureFailureContractTest {
|
||||
Bootstrap.bootStrap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void globalStructureDisableRefusesGeneratorBinding() {
|
||||
IrisModdedChunkGenerator.requireGlobalStructureGeneration(true, "overworld:overworld");
|
||||
|
||||
IllegalStateException error = assertThrows(
|
||||
IllegalStateException.class,
|
||||
() -> IrisModdedChunkGenerator.requireGlobalStructureGeneration(
|
||||
false, "overworld:overworld"));
|
||||
|
||||
assertTrue(error.getMessage().contains("overworld:overworld"));
|
||||
assertTrue(error.getMessage().contains("generate-structures=false"));
|
||||
assertTrue(error.getMessage().contains("importedStructures.disabled"));
|
||||
assertTrue(error.getMessage().contains("importedStructures.disabledExact"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void structureFailurePreservesPhaseIdentityChunkAndCause() {
|
||||
IllegalArgumentException cause = new IllegalArgumentException("broken placement");
|
||||
|
||||
@@ -118,14 +118,6 @@ public final class BukkitStructureStagePolicy implements StructureStagePolicy<
|
||||
return ((IrisMaterialPalette) source).get(rng, x, y, z, engine.getData());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuntimeException structuresDisabled(int chunkX, int chunkZ) {
|
||||
return new IllegalStateException("Iris cannot generate native structures in chunk "
|
||||
+ chunkX + "," + chunkZ
|
||||
+ " because structure generation is disabled outside the pack; enable native structure generation "
|
||||
+ "and deny families through importedStructures.disabled or complete keys through importedStructures.disabledExact");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String generationLabel(String structureId) {
|
||||
return "Iris native structure " + structureId;
|
||||
|
||||
Reference in New Issue
Block a user