Merged generation improvements

- Cold startup and hydrology changes integrate with terrain history
- Flat authoring worlds skip native features under the history write guards
- Native decoration checks retain recorded structure and terrain ownership
- Automatic build revisions replace manual source seals
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-05 12:05:14 -04:00
commit 965606bbcc
42 files changed
+4921 -366

No files matched your search

@@ -17,6 +17,7 @@ import art.arcane.iris.engine.object.IrisBiome;
import art.arcane.iris.engine.object.IrisBiomeCustom;
import art.arcane.iris.engine.object.IrisDimension;
import art.arcane.iris.engine.object.IrisDimensionCarvingResolver;
import art.arcane.iris.engine.platform.BukkitChunkGenerator;
import art.arcane.iris.util.project.context.IrisContext;
import art.arcane.volmlib.util.collection.KMap;
import art.arcane.volmlib.util.math.RNG;
@@ -64,6 +65,7 @@ public class CustomBiomeSource extends BiomeSource {
private final long seed;
private final Engine engine;
private final BukkitChunkGenerator platformGenerator;
private final Registry<Biome> biomeCustomRegistry;
private final Registry<Biome> biomeRegistry;
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
@@ -76,6 +78,9 @@ public class CustomBiomeSource extends BiomeSource {
public CustomBiomeSource(long seed, Engine engine, World world) {
this.engine = engine;
this.platformGenerator = world.getGenerator() instanceof BukkitChunkGenerator generator
? generator
: null;
this.seed = seed;
this.biomeCustomRegistry = registry().lookup(Registries.BIOME).orElse(null);
this.biomeRegistry = ((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())).lookup(Registries.BIOME).orElse(null);
@@ -353,6 +358,9 @@ public class CustomBiomeSource extends BiomeSource {
if (!isRuntimeAvailable()) {
return null;
}
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
return fallbackBiome;
}
runtimeBiomeState();
int quartX = QuartPos.fromBlock(blockX);
int quartZ = QuartPos.fromBlock(blockZ);
@@ -405,6 +413,9 @@ public class CustomBiomeSource extends BiomeSource {
}
private Holder<Biome> getStructureNoiseBiomeWithActiveGenerationLease(int x, int y, int z) {
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
return fallbackBiome;
}
if (isGuaranteedSurfaceBiome(y)) {
return getSurfaceStructureBiomeHolder(x, z);
}
@@ -731,6 +742,9 @@ public class CustomBiomeSource extends BiomeSource {
IrisDimensionCarvingResolver.State resolverState,
boolean cacheable
) {
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
return fallbackBiome;
}
RuntimeNoiseKey cacheKey = new RuntimeNoiseKey(
engine.getCacheID(), packNoiseKey(x, y, z));
if (cacheable) {
@@ -22,6 +22,7 @@ import art.arcane.iris.engine.history.SavedTerrainChunk;
import org.bukkit.NamespacedKey;
import org.bukkit.persistence.PersistentDataType;
import art.arcane.iris.engine.platform.BukkitChunkGenerator;
import art.arcane.iris.engine.platform.studio.generators.JigsawStudioGenerator;
import art.arcane.iris.engine.object.IrisDimension;
import art.arcane.iris.engine.object.IrisDimensionCarvingResolver;
import art.arcane.iris.engine.object.IrisMaterialPalette;
@@ -131,6 +132,13 @@ import java.util.function.IntBinaryOperator;
import java.util.function.Predicate;
public class IrisChunkGenerator extends CustomChunkGenerator implements LongPredicate {
private static final Set<Heightmap.Types> AUTHORING_HEIGHTMAPS = Set.of(
Heightmap.Types.WORLD_SURFACE_WG,
Heightmap.Types.OCEAN_FLOOR_WG,
Heightmap.Types.WORLD_SURFACE,
Heightmap.Types.OCEAN_FLOOR,
Heightmap.Types.MOTION_BLOCKING,
Heightmap.Types.MOTION_BLOCKING_NO_LEAVES);
private static final WrappedField<ChunkGenerator, BiomeSource> BIOME_SOURCE;
private static final WrappedReturningMethod<Heightmap, Object> SET_HEIGHT;
private static final Runnable NO_OP = () -> {
@@ -892,9 +900,17 @@ public class IrisChunkGenerator extends CustomChunkGenerator implements LongPred
}
private void primeWorldgenHeightmaps(ChunkAccess chunkAccess) {
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
primeAuthoringHeightmaps(chunkAccess);
return;
}
WorldgenTerrainHeightmaps.primeTerrain(chunkAccess, worldgenSurfaceHeight(), worldgenFloorHeight());
}
static void primeAuthoringHeightmaps(ChunkAccess chunkAccess) {
Heightmap.primeHeightmaps(chunkAccess, AUTHORING_HEIGHTMAPS);
}
private IntBinaryOperator worldgenSurfaceHeight() {
return (x, z) -> engine.getHeight(x, z, false) + runtimeMinY + 1;
}
@@ -971,19 +987,24 @@ public class IrisChunkGenerator extends CustomChunkGenerator implements LongPred
GenerationHistoryRuntimeRouter.RuntimeRoute.RuntimeScope runtimeScope = openHistoryRuntimeScope(route);
GenerationSessionLease lease = requireGenerationLease("bukkit_nms_biome_decoration");
IrisContext.Scope ignored = IrisContext.open(engine, lease.sessionId(), null)) {
if (!ichunkaccess.getPersistedStatus().isOrAfter(ChunkStatus.FEATURES)) {
boolean flatStudioTerrain = platformGenerator != null && platformGenerator.usesFlatStudioTerrain();
if (!flatStudioTerrain && !ichunkaccess.getPersistedStatus().isOrAfter(ChunkStatus.FEATURES)) {
placeVanillaStructures(generatoraccessseed, ichunkaccess, structuremanager);
}
if (allowsRoutedDiscreteGeneration(ichunkaccess, ChunkStatus.FEATURES)
&& NativeGenerationWriteGuard.allowsDecoration(engine, generatoraccessseed, chunkPos)) {
// Bind-time equivalent for Bukkit: the table is built on the first decorated chunk, which is where a
// feature-order cycle is reported once and degraded to features-off.
importedFeatures.prepare(generatoraccessseed);
if (!flatStudioTerrain) {
// Bind-time equivalent for Bukkit: the table is built on the first decorated chunk, which is where a
// feature-order cycle is reported once and degraded to features-off.
importedFeatures.prepare(generatoraccessseed);
}
addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager);
// Vanilla's placed-feature pass, on THIS thread. The delegate is still called with
// addVanillaDecorations=false below, so the vanilla half never runs twice. Inert unless the
// dimension set importedFeatures.enabled.
importedFeatures.run(generatoraccessseed, ichunkaccess, this);
if (!flatStudioTerrain) {
// Vanilla's placed-feature pass, on THIS thread. The delegate is still called with
// addVanillaDecorations=false below, so the vanilla half never runs twice. Inert unless the
// dimension set importedFeatures.enabled.
importedFeatures.run(generatoraccessseed, ichunkaccess, this);
}
delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager, false);
}
claimGeneratedSemantics(route, ichunkaccess, engine.getMinHeight());
@@ -1275,6 +1296,9 @@ public class IrisChunkGenerator extends CustomChunkGenerator implements LongPred
BlockPos blockPos = sectionPos.origin();
primeWorldgenHeightmaps(chunkAccess);
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
return;
}
Heightmap motion = chunkAccess.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING);
Heightmap motionNoLeaves = chunkAccess.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES);
@@ -1373,6 +1397,9 @@ public class IrisChunkGenerator extends CustomChunkGenerator implements LongPred
@Override
public int getBaseHeight(int i, int j, Heightmap.Types heightmap_type, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
return platformGenerator.getAuthoringBaseHeight();
}
try (GenerationHistoryRuntimeRouter.CoordinateScope route = openHistoryCoordinateScope(
i, j, "bukkit_nms_base_height");
GenerationSessionLease lease = engine.acquireGenerationLease("bukkit_nms_base_height");
@@ -1394,6 +1421,19 @@ public class IrisChunkGenerator extends CustomChunkGenerator implements LongPred
@Override
public NoiseColumn getBaseColumn(int i, int j, LevelHeightAccessor levelheightaccessor, RandomState randomstate) {
if (platformGenerator != null && platformGenerator.usesFlatStudioTerrain()) {
BlockState[] column = new BlockState[levelheightaccessor.getHeight()];
int floorIndex = platformGenerator.getAuthoringFloorY() - levelheightaccessor.getMinY();
BlockState floor = platformGenerator.isJigsawStudioActive() && JigsawStudioGenerator.isLightFloor(i, j)
? Blocks.SMOOTH_STONE.defaultBlockState()
: Blocks.POLISHED_DEEPSLATE.defaultBlockState();
for (int index = 0; index < column.length; index++) {
column[index] = index == floorIndex
? floor
: Blocks.AIR.defaultBlockState();
}
return new NoiseColumn(levelheightaccessor.getMinY(), column);
}
try (GenerationHistoryRuntimeRouter.CoordinateScope route = openHistoryCoordinateScope(
i, j, "bukkit_nms_base_column");
GenerationSessionLease lease = engine.acquireGenerationLease("bukkit_nms_base_column");
@@ -1270,9 +1270,9 @@ public class NMSBinding implements INMSBinding {
: null;
boolean studioBootstrap = platformGenerator != null
&& platformGenerator.isStudioEntryBootstrapActive();
boolean jigsawStudio = platformGenerator != null
&& platformGenerator.isJigsawStudioActive();
if (jigsawStudio) {
boolean authoringStudio = platformGenerator != null
&& platformGenerator.isAuthoringStudio();
if (authoringStudio) {
requireIrisGenerator(generator);
if (currentState.possibleStructureSets().isEmpty()) {
currentState.ensureStructuresGenerated();
@@ -24,6 +24,31 @@ public class CustomBiomeSourceStructureContractTest {
Bootstrap.bootStrap();
}
@Test
public void authoringBiomesBypassTerrainResolutionBeforeDestinationChunksGenerate() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.customBiomeSource")));
int visibleStart = source.indexOf("private Holder<Biome> getVisibleNoiseBiomeWithActiveGenerationLease(");
int visibleEnd = source.indexOf("private boolean isBiomeCacheable(", visibleStart);
String visible = source.substring(visibleStart, visibleEnd);
int constantBiome = visible.indexOf("platformGenerator.usesFlatStudioTerrain()");
int terrainResolution = visible.indexOf("resolveVisibleBiomeHolder(");
assertTrue(source.contains("platformGenerator.usesFlatStudioTerrain()"));
assertTrue(constantBiome >= 0);
assertTrue(visible.indexOf("return fallbackBiome;", constantBiome) < terrainResolution);
assertTrue(terrainResolution > constantBiome);
int structureStart = source.indexOf("private Holder<Biome> getStructureNoiseBiomeWithActiveGenerationLease(");
int structureEnd = source.indexOf("boolean cacheable", structureStart);
assertTrue(source.substring(structureStart, structureEnd).contains("platformGenerator.usesFlatStudioTerrain()"));
String generator = Files.readString(Path.of(System.getProperty("iris.nmsChunkGeneratorSource")));
int createBiomes = generator.indexOf("public CompletableFuture<ChunkAccess> createBiomes(");
int buildSurface = generator.indexOf("public void buildSurface(", createBiomes);
assertTrue(generator.substring(createBiomes, buildSurface)
.contains("customBiomeSource.getVisibleNoiseBiomeWithActiveGenerationLease("));
}
@Test
public void nativeStructuresUseTerrainSafeDerivativeAtEveryBiomeBoundary() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.customBiomeSource")));
@@ -221,6 +221,55 @@ public class IrisChunkGeneratorFailureContractTest {
assertTrue(source.contains("int minY = chunk.getMinY() + 1;"));
}
@Test
public void authoringHeightmapStagesReturnBeforeAnyTerrainHeightResolver() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.nmsChunkGeneratorSource")));
int primeStart = source.indexOf("private void primeWorldgenHeightmaps(");
int primeEnd = source.indexOf("private IntBinaryOperator worldgenSurfaceHeight()", primeStart);
String prime = source.substring(primeStart, primeEnd);
assertBefore(prime, "platformGenerator.usesFlatStudioTerrain()", "worldgenSurfaceHeight()");
assertBefore(prime, "primeAuthoringHeightmaps(chunkAccess);", "return;");
assertBefore(prime, "return;", "WorldgenTerrainHeightmaps.primeTerrain(");
int decorationStart = source.indexOf("public void addVanillaDecorations(");
int decorationEnd = source.indexOf("public void spawnOriginalMobs(", decorationStart);
String decorations = source.substring(decorationStart, decorationEnd);
assertBefore(decorations, "primeWorldgenHeightmaps(chunkAccess);", "platformGenerator.usesFlatStudioTerrain()");
assertBefore(decorations, "platformGenerator.usesFlatStudioTerrain()", "return;");
assertBefore(decorations, "return;", "engine.getHeight(");
}
@Test
public void authoringDecorationSkipsNativeFeaturesButRetainsHeightmapsAndBukkitPopulators() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.nmsChunkGeneratorSource")));
String decoration = method(source,
"public void applyBiomeDecoration(WorldGenLevel generatoraccessseed, ChunkAccess ichunkaccess, StructureManager structuremanager, boolean vanilla)",
"public BiomeGenerationSettings getBiomeGenerationSettings");
int structuresGuard = decoration.indexOf("if (!flatStudioTerrain && !ichunkaccess.getPersistedStatus().isOrAfter(ChunkStatus.FEATURES))");
assertTrue(structuresGuard >= 0);
int structuresEnd = decoration.indexOf("\n }", structuresGuard);
String structures = decoration.substring(structuresGuard, structuresEnd);
assertTrue(structures.contains("placeVanillaStructures(generatoraccessseed, ichunkaccess, structuremanager);"));
int preparationGuard = decoration.indexOf("if (!flatStudioTerrain)");
assertTrue(structuresEnd < preparationGuard);
assertTrue(decoration.indexOf("NativeGenerationWriteGuard.allowsDecoration") > structuresEnd);
int preparationEnd = decoration.indexOf("\n }", preparationGuard);
String preparation = decoration.substring(preparationGuard, preparationEnd);
assertTrue(preparation.contains("importedFeatures.prepare(generatoraccessseed);"));
int placementGuard = decoration.indexOf("if (!flatStudioTerrain)", preparationEnd);
int placementEnd = decoration.indexOf("\n }", placementGuard);
String placement = decoration.substring(placementGuard, placementEnd);
assertTrue(placement.contains("importedFeatures.run(generatoraccessseed, ichunkaccess, this);"));
int heightmaps = decoration.indexOf("addVanillaDecorations(generatoraccessseed, ichunkaccess, structuremanager);");
int populators = decoration.indexOf("delegate.applyBiomeDecoration(generatoraccessseed, ichunkaccess, structuremanager, false);");
assertTrue(heightmaps > preparationEnd && heightmaps < placementGuard);
assertTrue(populators > placementEnd);
assertTrue(decoration.indexOf("claimGeneratedSemantics(route,") > populators);
assertTrue(decoration.contains("requireGenerationStage(\"bukkit_nms_biome_decoration\")"));
assertTrue(decoration.contains("requireGenerationLease(\"bukkit_nms_biome_decoration\")"));
}
@Test
public void everyChunkUsesTheProductionGenerationStages() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.nmsChunkGeneratorSource")))
@@ -352,7 +352,7 @@ public class NMSBindingDatapackStructureScopeTest {
}
@Test
public void standardPublishesOneDeferredStateWhileJigsawPublishesInitializedEmptyState() throws IOException {
public void standardPublishesOneDeferredStateWhileAuthoringPublishesInitializedEmptyState() throws IOException {
Path chunkGeneratorSource = Path.of(System.getProperty("iris.nmsChunkGeneratorSource"));
String source = Files.readString(chunkGeneratorSource.resolveSibling("NMSBinding.java")).replace("\r\n", "\n");
int methodStart = source.indexOf("public DatapackStructureScopeResult scopeDatapackStructures(");
@@ -365,8 +365,8 @@ public class NMSBindingDatapackStructureScopeTest {
String method = source.substring(methodStart, methodEnd);
int filteredState = method.indexOf("possibleSetsField.set(scopedState, selection.structureSets());");
int jigsawMode = method.indexOf(
"boolean jigsawStudio = platformGenerator != null");
int jigsawOnly = method.indexOf("if (jigsawStudio)");
"boolean authoringStudio = platformGenerator != null");
int jigsawOnly = method.indexOf("if (authoringStudio)");
int emptyCreation = method.indexOf("ChunkGeneratorStructureState bootstrapState = createStructureState(");
int emptyFiltering = method.indexOf("bootstrapSetsField.set(bootstrapState, List.of());");
int emptyInitialization = method.indexOf("bootstrapState.ensureStructuresGenerated();");
@@ -64,6 +64,21 @@ public class WorldgenTerrainHeightmapsTest {
Bootstrap.bootStrap();
}
@Test
public void authoringHeightmapsReadPlacedObjectsAndFluidsWithoutTerrainResolvers() {
ProtoChunk chunk = terrainChunk(new ChunkPos(0, 0));
IrisChunkGenerator.primeAuthoringHeightmaps(chunk);
assertEquals(LAND_CANOPY_TOP, chunk.getHeight(Heightmap.Types.WORLD_SURFACE_WG, LAND_X, LAND_Z));
assertEquals(LAND_CANOPY_TOP, chunk.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, LAND_X, LAND_Z));
assertEquals(LAND_CANOPY_TOP, chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, LAND_X, LAND_Z));
assertEquals(LAND_TERRAIN_TOP + 6,
chunk.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, LAND_X, LAND_Z));
assertEquals(OCEAN_FLUID_TOP, chunk.getHeight(Heightmap.Types.WORLD_SURFACE_WG, OCEAN_X, OCEAN_Z));
assertEquals(OCEAN_FLOOR_TOP, chunk.getHeight(Heightmap.Types.OCEAN_FLOOR_WG, OCEAN_X, OCEAN_Z));
}
@Test
public void primeTerrainWritesEngineSurfaceAndOceanFloorHeights() {
ProtoChunk chunk = terrainChunk(new ChunkPos(0, 0));