mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-25 13:30:08 +00:00
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:
commit
965606bbcc
42 files changed
+4921
-366
No files matched your search
+14
@@ -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) {
|
||||
|
||||
+48
-8
@@ -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");
|
||||
|
||||
+3
-3
@@ -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();
|
||||
|
||||
+25
@@ -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")));
|
||||
|
||||
+49
@@ -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")))
|
||||
|
||||
+3
-3
@@ -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();");
|
||||
|
||||
+15
@@ -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));
|
||||
|
||||
Reference in new issue
Block a user