diff --git a/core/src/main/java/art/arcane/iris/generation/runtime/Engine.java b/core/src/main/java/art/arcane/iris/generation/runtime/Engine.java index b00f21993..f0739750e 100644 --- a/core/src/main/java/art/arcane/iris/generation/runtime/Engine.java +++ b/core/src/main/java/art/arcane/iris/generation/runtime/Engine.java @@ -87,10 +87,6 @@ import java.util.stream.Collectors; public interface Engine extends DataProvider, Fallible, BlockUpdater, Renderer, Hotloadable { IrisComplex getComplex(); - default art.arcane.iris.structure.object.PlacementLifecycles getPlacementLifecycles() { - return art.arcane.iris.structure.object.PlacementLifecycles.defaults(); - } - default BiomeEnvironment getBiomeEnvironment(int x, int y, int z) { return new BiomeEnvironment(0L, getBiome(x, y, z), getRegion(x, y, z), getDimension(), getData()); } diff --git a/core/src/main/java/art/arcane/iris/generation/runtime/EngineHotloader.java b/core/src/main/java/art/arcane/iris/generation/runtime/EngineHotloader.java index d999c4287..05d704260 100644 --- a/core/src/main/java/art/arcane/iris/generation/runtime/EngineHotloader.java +++ b/core/src/main/java/art/arcane/iris/generation/runtime/EngineHotloader.java @@ -96,8 +96,7 @@ final class EngineHotloader { assembly.complex, assembly.upperContext, assembly.dimensionStackContext, - biomeMaxes, - assembly.placementLifecycles); + biomeMaxes); next = previous.withGeneration(nextGeneration); } finally { engine.threadState.setAssembly(null); diff --git a/core/src/main/java/art/arcane/iris/generation/runtime/EngineRuntimeBuilder.java b/core/src/main/java/art/arcane/iris/generation/runtime/EngineRuntimeBuilder.java index 8d42412fc..79fe292cd 100644 --- a/core/src/main/java/art/arcane/iris/generation/runtime/EngineRuntimeBuilder.java +++ b/core/src/main/java/art/arcane/iris/generation/runtime/EngineRuntimeBuilder.java @@ -18,8 +18,6 @@ package art.arcane.iris.generation.runtime; -import art.arcane.iris.structure.object.PlacementLifecycles; - import art.arcane.iris.pack.loading.IrisData; import art.arcane.iris.pack.loading.ResourceLoader; import art.arcane.iris.generation.runtime.GenerationRuntime.BiomeMaxes; @@ -422,7 +420,6 @@ final class EngineRuntimeBuilder { final GenerationKernelRegistry.RuntimeKernel runtimeKernel; final SeedManager seedManager; final TransitionGenerationPlan transitionPlan; - final PlacementLifecycles placementLifecycles; static int nextRuntimeId() { return RUNTIME_IDS.incrementAndGet(); @@ -471,7 +468,6 @@ final class EngineRuntimeBuilder { this.seedManager = this.runtimeKernel.createSeedManager(target.getWorld().getRawWorldSeed()); this.kernelVersion = this.runtimeKernel.version(); this.transitionPlan = transitionPlan; - this.placementLifecycles = PlacementLifecycles.resolve(); } GenerationRuntime freezeGeneration(BiomeMaxes biomeMaxes) { @@ -494,8 +490,7 @@ final class EngineRuntimeBuilder { mantle, mantleStorageDirectory, hash32, - biomeMaxes, - placementLifecycles); + biomeMaxes); } EngineRuntime freezeRuntime(BiomeMaxes biomeMaxes) { diff --git a/core/src/main/java/art/arcane/iris/generation/runtime/GenerationRuntime.java b/core/src/main/java/art/arcane/iris/generation/runtime/GenerationRuntime.java index 4c841a963..61463574a 100644 --- a/core/src/main/java/art/arcane/iris/generation/runtime/GenerationRuntime.java +++ b/core/src/main/java/art/arcane/iris/generation/runtime/GenerationRuntime.java @@ -18,8 +18,6 @@ package art.arcane.iris.generation.runtime; -import art.arcane.iris.structure.object.PlacementLifecycles; - import art.arcane.iris.pack.loading.IrisData; import art.arcane.iris.world.history.TransitionGenerationPlan; import art.arcane.iris.world.history.GenerationKernelRegistry; @@ -46,8 +44,7 @@ record GenerationRuntime( EngineMantle mantle, Path mantleStorageDirectory, CompletableFuture hash32, - BiomeMaxes biomeMaxes, - PlacementLifecycles placementLifecycles + BiomeMaxes biomeMaxes ) { GenerationRuntime { Objects.requireNonNull(target, "generation target"); @@ -64,7 +61,6 @@ record GenerationRuntime( Objects.requireNonNull(mantle, "generation mantle"); mantleStorageDirectory = IrisEngineMantle.normalizeStorageDirectory(mantleStorageDirectory); Objects.requireNonNull(hash32, "generation pack hash"); - Objects.requireNonNull(placementLifecycles, "placement lifecycles"); Objects.requireNonNull(biomeMaxes, "generation biome maximums"); if (target.getData() != data || target.getDimension() != dimension) { throw new IllegalArgumentException("Generation target, data, and dimension must describe one runtime."); @@ -76,8 +72,7 @@ record GenerationRuntime( IrisComplex nextComplex, UpperDimensionContext nextUpperContext, DimensionStackContext nextDimensionStackContext, - BiomeMaxes nextBiomeMaxes, - PlacementLifecycles nextPlacementLifecycles + BiomeMaxes nextBiomeMaxes ) { return new GenerationRuntime( nextCacheId, @@ -95,8 +90,7 @@ record GenerationRuntime( mantle, mantleStorageDirectory, hash32, - nextBiomeMaxes, - nextPlacementLifecycles); + nextBiomeMaxes); } record BiomeMaxes(double objectDensity, double layerDensity, double decoratorDensity) { diff --git a/core/src/main/java/art/arcane/iris/generation/runtime/IrisEngine.java b/core/src/main/java/art/arcane/iris/generation/runtime/IrisEngine.java index 1a38b8ee0..7145da0b2 100644 --- a/core/src/main/java/art/arcane/iris/generation/runtime/IrisEngine.java +++ b/core/src/main/java/art/arcane/iris/generation/runtime/IrisEngine.java @@ -1403,20 +1403,6 @@ public class IrisEngine implements Engine { return current == null ? null : current.complex(); } - @Override - public art.arcane.iris.structure.object.PlacementLifecycles getPlacementLifecycles() { - EngineThreadState.Frame frame = threadState.current(); - RuntimeAssembly assembly = frame == null ? null : frame.assembly; - if (assembly != null) { - return assembly.placementLifecycles; - } - GenerationRuntime current = selectedGenerationRuntime(frame); - if (current == null) { - throw new IllegalStateException("Placement requires an active Iris runtime."); - } - return current.placementLifecycles(); - } - @Override public EngineTarget getTarget() { return targetIn(threadState.current()); diff --git a/core/src/main/java/art/arcane/iris/structure/object/IrisObjectPlacementRunner.java b/core/src/main/java/art/arcane/iris/structure/object/IrisObjectPlacementRunner.java index 5ba1971d1..31ea860cd 100644 --- a/core/src/main/java/art/arcane/iris/structure/object/IrisObjectPlacementRunner.java +++ b/core/src/main/java/art/arcane/iris/structure/object/IrisObjectPlacementRunner.java @@ -27,7 +27,7 @@ import art.arcane.volmlib.util.math.RNG; import java.util.function.BiConsumer; -/** Entry point for executing an engine's resolved placement plan. */ +/** Entry point for executing the resolved placement plan of a mode. */ final class IrisObjectPlacementRunner { private final IrisObject self; private final IrisObjectPlacementAlignment alignment; @@ -40,6 +40,6 @@ final class IrisObjectPlacementRunner { int place(int x, int yv, int z, IObjectPlacer placer, IrisObjectPlacement config, RNG rng, BiConsumer listener, CarveResult cave, IrisData data) { PlacementContext context = new PlacementContext(config, data, placer, cave, rng, self, alignment, x, z, yv, listener); - return PlacementLifecycles.forPlacer(placer).get(config.getMode()).execute(context).heightOrRejected(); + return PlacementLifecycles.defaults().get(config.getMode()).execute(context).heightOrRejected(); } } diff --git a/core/src/main/java/art/arcane/iris/structure/object/PlacementLifecycles.java b/core/src/main/java/art/arcane/iris/structure/object/PlacementLifecycles.java index 8d7bfb681..971cfa11a 100644 --- a/core/src/main/java/art/arcane/iris/structure/object/PlacementLifecycles.java +++ b/core/src/main/java/art/arcane/iris/structure/object/PlacementLifecycles.java @@ -3,16 +3,17 @@ package art.arcane.iris.structure.object; import java.util.EnumMap; import java.util.Map; +import java.util.Objects; -/** One resolved plan per mode in an engine runtime. Engine-less tools share a separate default set. */ -public final class PlacementLifecycles { +/** One resolved plan per mode. Plans are immutable, so every placement shares the default set. */ +final class PlacementLifecycles { private final Map plans; private PlacementLifecycles(Map plans) { this.plans = Map.copyOf(plans); } - public static PlacementLifecycles resolve() { + static PlacementLifecycles resolve() { Map plans = new EnumMap<>(ObjectPlaceMode.class); for (ObjectPlaceMode mode : ObjectPlaceMode.values()) { try { @@ -24,18 +25,12 @@ public final class PlacementLifecycles { return new PlacementLifecycles(plans); } - public static PlacementLifecycles defaults() { + static PlacementLifecycles defaults() { return Defaults.INSTANCE; } - static PlacementLifecycles forPlacer(IObjectPlacer placer) { - var engine = placer.getEngine(); - PlacementLifecycles plans = engine == null ? null : engine.getPlacementLifecycles(); - return plans == null ? defaults() : plans; - } - - public PlacementLifecycle get(ObjectPlaceMode mode) { - return plans.get(java.util.Objects.requireNonNull(mode, "Placement mode")); + PlacementLifecycle get(ObjectPlaceMode mode) { + return plans.get(Objects.requireNonNull(mode, "Placement mode")); } private static final class Defaults { diff --git a/core/src/test/java/art/arcane/iris/generation/runtime/EnginePlacementLifecycleTest.java b/core/src/test/java/art/arcane/iris/generation/runtime/EnginePlacementLifecycleTest.java deleted file mode 100644 index e821d14d6..000000000 --- a/core/src/test/java/art/arcane/iris/generation/runtime/EnginePlacementLifecycleTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package art.arcane.iris.generation.runtime; - -import art.arcane.iris.generation.runtime.EngineEffects; -import art.arcane.iris.generation.runtime.EngineMode; -import art.arcane.iris.generation.runtime.EngineTarget; -import art.arcane.iris.generation.runtime.EngineWorldManager; -import art.arcane.iris.structure.object.ObjectPlaceMode; -import org.junit.Test; - -import java.util.concurrent.CompletableFuture; - -import static org.junit.Assert.*; -import static org.mockito.Mockito.mock; - -public class EnginePlacementLifecycleTest { - @Test - public void runtimeAssemblyResolvesBeforePublicationAndKeepsOldPlansIntact() { - var initial = assembly(1); - EngineRuntime previous = initial.freezeRuntime(new GenerationRuntime.BiomeMaxes(0, 0, 0)); - var replacement = assembly(2); - EngineRuntime next = replacement.freezeRuntime(new GenerationRuntime.BiomeMaxes(0, 0, 0)); - - assertSame(initial.placementLifecycles, previous.generation().placementLifecycles()); - assertSame(replacement.placementLifecycles, next.generation().placementLifecycles()); - for (ObjectPlaceMode mode : ObjectPlaceMode.values()) { - assertNotNull(next.generation().placementLifecycles().get(mode)); - assertNotSame(previous.generation().placementLifecycles().get(mode), next.generation().placementLifecycles().get(mode)); - } - assertSame(initial.placementLifecycles, previous.generation().placementLifecycles()); - } - - @Test - public void complexReplacementCarriesNewPlansAlongsideTheNewComplex() { - var initial = assembly(1); - EngineRuntime previous = initial.freezeRuntime(new GenerationRuntime.BiomeMaxes(0, 0, 0)); - var replacement = assembly(2); - EngineRuntime next = previous.withGeneration(previous.generation().withComplex(2, replacement.complex, null, null, - new GenerationRuntime.BiomeMaxes(1, 1, 1), replacement.placementLifecycles)); - - assertSame(replacement.placementLifecycles, next.generation().placementLifecycles()); - assertSame(replacement.complex, next.generation().complex()); - assertSame(previous.worldManager(), next.worldManager()); - assertSame(initial.placementLifecycles, previous.generation().placementLifecycles()); - } - - private EngineRuntimeBuilder.RuntimeAssembly assembly(int id) { - EngineTarget target = mock(EngineTarget.class); - var world = mock(art.arcane.iris.world.IrisWorld.class); - org.mockito.Mockito.when(target.getWorld()).thenReturn(world); - org.mockito.Mockito.when(target.getData()).thenReturn(mock(art.arcane.iris.pack.loading.IrisData.class)); - org.mockito.Mockito.when(target.getDimension()).thenReturn(mock(art.arcane.iris.generation.terrain.IrisDimension.class)); - var assembly = new EngineRuntimeBuilder.RuntimeAssembly(id, target, - java.nio.file.Path.of("build", "test-mantles", "placement-" + id)); - assembly.mantle = mock(art.arcane.iris.generation.mantle.EngineMantle.class); - assembly.complex = mock(IrisComplex.class); - assembly.effects = mock(EngineEffects.class); - assembly.mode = mock(EngineMode.class); - assembly.worldManager = mock(EngineWorldManager.class); - assembly.hash32 = CompletableFuture.completedFuture(0L); - return assembly; - } -} diff --git a/core/src/test/java/art/arcane/iris/generation/runtime/EngineShutdownDrainTest.java b/core/src/test/java/art/arcane/iris/generation/runtime/EngineShutdownDrainTest.java index f880e0de3..1704b654a 100644 --- a/core/src/test/java/art/arcane/iris/generation/runtime/EngineShutdownDrainTest.java +++ b/core/src/test/java/art/arcane/iris/generation/runtime/EngineShutdownDrainTest.java @@ -858,7 +858,7 @@ public class EngineShutdownDrainTest { when(generation.runtimeKernel()).thenReturn(kernel); GenerationRuntime nextGeneration = generation(target, mantle); when(nextGeneration.complex()).thenReturn(replacement); - when(generation.withComplex(anyInt(), same(replacement), isNull(), isNull(), any(), any())) + when(generation.withComplex(anyInt(), same(replacement), isNull(), isNull(), any())) .thenReturn(nextGeneration); EngineRuntimeBuilder builder = spy(new EngineRuntimeBuilder(engine)); doReturn(new GenerationRuntime.BiomeMaxes(0D, 0D, 0D)).when(builder).computeBiomeMaxes(); diff --git a/core/src/test/java/art/arcane/iris/generation/runtime/IrisEngineGenerationRuntimeScopeTest.java b/core/src/test/java/art/arcane/iris/generation/runtime/IrisEngineGenerationRuntimeScopeTest.java index 4a3df8846..ac7a33074 100644 --- a/core/src/test/java/art/arcane/iris/generation/runtime/IrisEngineGenerationRuntimeScopeTest.java +++ b/core/src/test/java/art/arcane/iris/generation/runtime/IrisEngineGenerationRuntimeScopeTest.java @@ -335,7 +335,6 @@ public class IrisEngineGenerationRuntimeScopeTest { assertSame(detached.dimension, engine.getDimension()); assertSame(detached.runtime.seedManager(), engine.getSeedManager()); assertSame(detached.complex, engine.getComplex()); - assertSame(detached.runtime.placementLifecycles(), engine.getPlacementLifecycles()); assertSame(detached.upperContext, engine.getUpperContext()); assertSame(detached.dimensionStackContext, engine.getDimensionStackContext()); assertSame(detached.mode, engine.getMode()); @@ -352,7 +351,6 @@ public class IrisEngineGenerationRuntimeScopeTest { assertSame(active.target, engine.getTarget()); assertSame(active.data, engine.getData()); assertSame(active.runtime.seedManager(), engine.getSeedManager()); - assertSame(active.runtime.placementLifecycles(), engine.getPlacementLifecycles()); assertSame(active.mantle, engine.getMantle()); assertEquals(1, engine.getCacheID()); } @@ -1011,8 +1009,7 @@ public class IrisEngineGenerationRuntimeScopeTest { mantle, mantleStorageDirectory, hash32, - new BiomeMaxes(objectDensity, layerDensity, decoratorDensity), - art.arcane.iris.structure.object.PlacementLifecycles.resolve()); + new BiomeMaxes(objectDensity, layerDensity, decoratorDensity)); return new RuntimeFixture( runtime, target, diff --git a/core/src/test/java/art/arcane/iris/structure/object/IrisObjectPlacementLifecycleRegressionTest.java b/core/src/test/java/art/arcane/iris/structure/object/IrisObjectPlacementLifecycleRegressionTest.java index 7f180678c..8e00d397a 100644 --- a/core/src/test/java/art/arcane/iris/structure/object/IrisObjectPlacementLifecycleRegressionTest.java +++ b/core/src/test/java/art/arcane/iris/structure/object/IrisObjectPlacementLifecycleRegressionTest.java @@ -271,7 +271,7 @@ public class IrisObjectPlacementLifecycleRegressionTest { } @Test - public void runnerUsesTheEnginePlanAndCompletesTheBlockPassBeforeAfterBlocks() { + public void customPlanCompletesTheBlockPassBeforeAfterBlocks() { RecordingPlacer placer = new RecordingPlacer(engine); PlacementLifecycleBuilder builder = new PlacementLifecycleBuilder(); ObjectPlaceMode.CENTER_HEIGHT.install(builder); @@ -280,11 +280,10 @@ public class IrisObjectPlacementLifecycleRegressionTest { List finishedSizes = new ArrayList<>(); builder.add(new PlacementLifecycleDependency("test.finished"), PlacementStage.AFTER_BLOCKS, (context, state, ignored) -> finishedSizes.add(placer.writes().size())); - PlacementLifecycles plans = mock(PlacementLifecycles.class); - when(plans.get(ObjectPlaceMode.CENTER_HEIGHT)).thenReturn(builder.build()); - when(engine.getPlacementLifecycles()).thenReturn(plans); + PlacementContext context = new PlacementContext(placement(), data, placer, null, new RNG(2L), lineObject(3), + 0, 0, ANCHOR_Y, null); - assertEquals(ANCHOR_Y + 5, lineObject(3).place(0, ANCHOR_Y, 0, placer, placement(), new RNG(2L), data)); + assertEquals(ANCHOR_Y + 5, builder.build().execute(context).heightOrRejected()); assertEquals(List.of(3), finishedSizes); assertTrue(placer.writes().stream().allMatch(write -> write.y() == ANCHOR_Y + 5)); } diff --git a/core/src/test/java/art/arcane/iris/structure/object/PlacementLifecycleTest.java b/core/src/test/java/art/arcane/iris/structure/object/PlacementLifecycleTest.java index e65fd01ea..c980cfa14 100644 --- a/core/src/test/java/art/arcane/iris/structure/object/PlacementLifecycleTest.java +++ b/core/src/test/java/art/arcane/iris/structure/object/PlacementLifecycleTest.java @@ -98,7 +98,7 @@ public class PlacementLifecycleTest { } @Test - public void everyModeResolvesAndRuntimePlansAreIndependent() { + public void everyModeResolvesToIndependentPlans() { PlacementLifecycles first = PlacementLifecycles.resolve(); PlacementLifecycles second = PlacementLifecycles.resolve(); for (ObjectPlaceMode mode : ObjectPlaceMode.values()) {