Production-readiness suite fixes

Surface hydrology policy split, native terrain height cache, watched-edit
hotload cancellation, world-save requestSave with tracked ownership flush,
background-task drain that follows saves admitted mid-drain, peaceful spawn
guard, cached-completion terminal state, IO drains off the owner thread.

Studio pregen at scale: detached historical runtimes keep the configured
noise cache instead of the Studio-wide cache; retired runtimes are no longer
pinned by the volumetric fragment filter's per-thread scratch; pregen mantle
cleanup and native region flushes run on per-run threads instead of the
server thread and the shared Iris IO pool (the flush on the IO pool starved
tectonic plate loads and wedged every Paper worker in Mantle.getChunks);
background-task cancellation claims tasks atomically.
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-09 16:24:05 -04:00
1 parent 4de1aea8b9
commit 62e61970f8
150 files changed
+7892 -1341

No files matched your search

@@ -19,6 +19,7 @@
package art.arcane.iris.modded;
import art.arcane.iris.nativegen.NativeTransitionColumn;
import art.arcane.iris.nativegen.NativeTerrainHeightCache;
import art.arcane.iris.engine.history.TerrainBoundarySignature;
import art.arcane.iris.engine.history.NativeBiomeSpawnSelection;
import java.util.Optional;
@@ -107,6 +108,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CancellationException;
@@ -145,6 +147,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
private final ModdedNativeStructureStage nativeStructures = new ModdedNativeStructureStage(this);
private final ModdedSpawnTableMerger spawnTables = new ModdedSpawnTableMerger(this);
private final ModdedImportedFeatureStage importedFeatures;
private final NativeTerrainHeightCache terrainHeights = new NativeTerrainHeightCache();
private final AtomicBoolean announced = new AtomicBoolean(false);
private final IntConsumer generationRuntimeRetirementListener = this::retireGenerationRuntimeCaches;
private volatile boolean unloading;
@@ -1381,15 +1384,18 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
@Override
public int getBaseHeight(int x, int z, Heightmap.Types type, LevelHeightAccessor heightAccessor, RandomState randomState) {
Engine current = requireDataQueryEngine("base height");
boolean ignoreFluid = !type.isOpaque().test(Blocks.WATER.defaultBlockState());
try (GenerationHistoryRuntimeRouter.CoordinateScope historyScope = openHistoryCoordinateScope(
current, x, z, "modded_base_height");
GenerationSessionLease lease = current.acquireGenerationLease("modded_base_height");
IrisContext.Scope ignored = IrisContext.open(current, lease.sessionId(), null)) {
Optional<TerrainBoundarySignature> resolved = current.getComplex().resolvedTerrainColumn(x, z);
NativeTerrainHeightCache.Query query = new NativeTerrainHeightCache.Query(
current.getCacheID(), x, z, type, heightAccessor.getMinY(), heightAccessor.getHeight());
OptionalInt resolved = terrainHeights.resolvedHeight(query,
() -> resolvedBaseHeight(current, x, z, type, heightAccessor));
if (resolved.isPresent()) {
return NativeTransitionColumn.height(resolved.get(), type, heightAccessor);
return resolved.getAsInt();
}
boolean ignoreFluid = !type.isOpaque().test(Blocks.WATER.defaultBlockState());
int height = current.getDimensionStackContext() == null
? current.getHeight(x, z, ignoreFluid)
: Engine.hostHeight(current, x, z, ignoreFluid);
@@ -1399,6 +1405,13 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
}
}
private OptionalInt resolvedBaseHeight(Engine current, int x, int z, Heightmap.Types type, LevelHeightAccessor heightAccessor) {
Optional<TerrainBoundarySignature> resolved = current.getComplex().resolvedTerrainColumn(x, z);
return resolved.isPresent()
? OptionalInt.of(NativeTransitionColumn.height(resolved.get(), type, heightAccessor))
: OptionalInt.empty();
}
@Override
public NoiseColumn getBaseColumn(int x, int z, LevelHeightAccessor heightAccessor, RandomState randomState) {
int minY = heightAccessor.getMinY();
@@ -1482,6 +1495,7 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
}
private void retireGenerationRuntimeCaches(int runtimeIdentity) {
terrainHeights.evictRuntime(runtimeIdentity);
structureBiomeSource.evictRuntime(runtimeIdentity);
importedFeatures.evictRuntime(runtimeIdentity);
spawnTables.evictRuntime(runtimeIdentity);
@@ -46,6 +46,7 @@ import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
@@ -120,13 +121,20 @@ public final class ModdedEntitySpawner {
return null;
}
Entity entity = type.spawn(level, BlockPos.containing(x, y, z), reasonFor(irisEntity.getReason()));
Entity entity = spawnNative(type, level, BlockPos.containing(x, y, z), reasonFor(irisEntity.getReason()));
if (entity != null) {
entity.snapTo(x, y, z, 0F, 0F);
}
return entity;
}
static Entity spawnNative(EntityType<?> type, ServerLevel level, BlockPos position, EntitySpawnReason reason) {
if (level.getDifficulty() == Difficulty.PEACEFUL && !type.isAllowedInPeaceful()) {
return null;
}
return type.spawn(level, position, reason);
}
private static void applyConfig(Engine engine, IrisEntity irisEntity, Entity entity, ServerLevel level, int blockX, int blockY, int blockZ, RNG rng, boolean riseEffectActive) {
String customName = irisEntity.getCustomName();
if (customName != null) {
@@ -398,10 +398,7 @@ final class ModdedNativeStructureStage {
}
IrisStaticObjectLayer staticObjects = current.getDimension().getStaticObjectLayer(current.getData());
Predicate<BlockPos> protectedPosition = nativeStructureProtection(current, staticObjects);
WorldGenLevel boundedWorld = staticObjects.isEmpty()
&& current.getDimensionStackContext() == null
? world
: ModdedNativeStructureWorldgenAccess.create(
WorldGenLevel boundedWorld = ModdedNativeStructureWorldgenAccess.create(
world, chunkPos, worldgenSurfaceHeight(current, world.getMinY()), worldgenFloorHeight(current, world.getMinY()),
current.getDimensionStackContext() != null,
protectedPosition);
@@ -413,11 +410,12 @@ final class ModdedNativeStructureStage {
"vegetation cleanup", nativeStructureBatchContext(placementGroups),
chunkPos.x(), chunkPos.z(), error);
}
NativeStructureSurfaceFitter.VacuumFoundationPlan vacuumFoundationPlan;
NativeStructureSurfaceFitter.SurfaceTerrainPlan surfaceTerrainPlan;
try {
vacuumFoundationPlan = NativeStructureSurfaceFitter.prepareSurfaceStructures(
surfaceTerrainPlan = NativeStructureSurfaceFitter.prepareSurfaceStructures(
boundedWorld, area, terrainTargets,
(x, z) -> Engine.hostHeight(current, x, z, true) + current.getMinHeight());
surfaceTerrainPlan.primeHeightmaps(chunk);
} catch (Throwable error) {
throw NativeStructureGenerationException.failure(
"terrain integration", nativeStructureBatchContext(placementGroups),
@@ -445,7 +443,7 @@ final class ModdedNativeStructureStage {
}
try {
NativeStructureSurfaceFitter.repairVacuumFoundations(
boundedWorld, area, vacuumFoundationPlan);
boundedWorld, area, surfaceTerrainPlan);
} catch (Throwable error) {
throw NativeStructureGenerationException.failure(
"foundation repair", nativeStructureBatchContext(placementGroups),
@@ -210,7 +210,7 @@ public final class ModdedPlatform implements IrisPlatform {
}
EntityType<?> type = (EntityType<?>) resolved.nativeHandle();
BlockPos pos = BlockPos.containing(x, y, z);
Entity entity = type.spawn(level, pos, EntitySpawnReason.COMMAND);
Entity entity = ModdedEntitySpawner.spawnNative(type, level, pos, EntitySpawnReason.COMMAND);
return entity != null;
}