This commit is contained in:
Brian Neumann-Fopiano
2026-07-16 18:18:23 -04:00
parent 699247b1de
commit e8dd4e1127
10 changed files with 229 additions and 36 deletions
@@ -465,7 +465,8 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
BoundingBox area, ChunkPos chunkPos, String structureId, StructureStart start,
IrisNativeStructureDecision decision) {
NativeStructurePostProcessor.place(world, structureManager, this, random, area, chunkPos,
structureId, start, decision, this::resolveStiltBlock);
structureId, start, decision, this::resolveStiltBlock,
(x, z) -> engine.getHeight(x, z, true) + engine.getMinHeight());
}
private List<List<Structure>> structuresByStep(Registry<Structure> registry) {
@@ -85,10 +85,12 @@ public class IrisChunkGeneratorMonumentLocateContractTest {
int placement = source.indexOf("start.placeInChunk(world, structureManager, generator");
int stiltPlacement = source.indexOf("placeStilts(world, area, structureId, start", placement);
int occupancyCheck = source.indexOf("if (state.isSolid())", stiltPlacement);
int terrainFloor = source.indexOf("y > terrainY", stiltPlacement);
assertTrue(placement >= 0);
assertTrue(stiltPlacement > placement);
assertTrue(occupancyCheck > stiltPlacement);
assertTrue(terrainFloor > stiltPlacement);
assertFalse(source.contains("state.equals("));
assertFalse(source.contains("snapshot.states"));
}
@@ -60,13 +60,15 @@ public final class NativeStructurePostProcessor {
public static void place(WorldGenLevel world, StructureManager structureManager, ChunkGenerator generator,
WorldgenRandom random, BoundingBox area, ChunkPos chunkPos, String structureId,
StructureStart start, IrisNativeStructureDecision decision,
StiltBlockResolver stiltBlockResolver) {
StiltBlockResolver stiltBlockResolver,
IntBinaryOperator surfaceHeight) {
IrisStructureStiltSettings stilt = decision.stilt();
ensureMonumentSeaLevelAlignment(start, structureId, decision.yShift(), generator.getSeaLevel(),
area.minY(), area.maxY() + 1);
start.placeInChunk(world, structureManager, generator, random, area, chunkPos);
if (stilt != null) {
placeStilts(world, area, structureId, start, stilt, stiltBlockResolver);
placeStilts(world, area, structureId, start, stilt, stiltBlockResolver, surfaceHeight,
!isUndergroundStep(start.getStructure().step()));
}
}
@@ -798,7 +800,10 @@ public final class NativeStructurePostProcessor {
private static void placeStilts(WorldGenLevel world, BoundingBox area, String structureId,
StructureStart start, IrisStructureStiltSettings settings,
StiltBlockResolver stiltBlockResolver) {
StiltBlockResolver stiltBlockResolver,
IntBinaryOperator surfaceHeight,
boolean surfaceStructure) {
Objects.requireNonNull(surfaceHeight, "Structure stilts require an Iris terrain height resolver");
BlockPos.MutableBlockPos position = new BlockPos.MutableBlockPos();
int structureHash = structureId == null ? 0 : structureId.hashCode();
RNG rng = new RNG(world.getSeed() ^ structureHash);
@@ -807,8 +812,12 @@ public final class NativeStructurePostProcessor {
if (foundationY == Integer.MIN_VALUE) {
continue;
}
int terrainY = surfaceStructure
? Math.max(area.minY(), Math.min(
area.maxY(), surfaceHeight.applyAsInt(column.x(), column.z())))
: area.minY() - 1;
for (int depth = 0, y = foundationY - 1;
depth < settings.getMaxDepth() && y >= area.minY(); depth++, y--) {
depth < settings.getMaxDepth() && y > terrainY; depth++, y--) {
position.set(column.x(), y, column.z());
BlockState existingState = world.getBlockState(position);
boolean vegetation = existingState.is(BlockTags.LOGS) || existingState.is(BlockTags.LEAVES);
@@ -825,8 +834,10 @@ public final class NativeStructurePostProcessor {
}
public static StiltSupportAudit auditStiltSupport(WorldGenLevel world, BoundingBox area,
StructureStart start, BlockState expectedStilt) {
StructureStart start, BlockState expectedStilt,
IntBinaryOperator surfaceHeight) {
Objects.requireNonNull(expectedStilt, "Expected stilt state must not be null");
Objects.requireNonNull(surfaceHeight, "Structure stilt audit requires an Iris terrain height resolver");
BlockPos.MutableBlockPos position = new BlockPos.MutableBlockPos();
int baseColumns = 0;
int stiltBlocks = 0;
@@ -838,9 +849,15 @@ public final class NativeStructurePostProcessor {
continue;
}
baseColumns++;
boolean grounded = foundationY == area.minY();
int terrainY = Math.max(area.minY(), Math.min(
area.maxY(), surfaceHeight.applyAsInt(column.x(), column.z())));
boolean grounded = foundationY <= terrainY + 1;
boolean stiltColumn = false;
for (int y = foundationY - 1; y >= area.minY(); y--) {
if (y <= terrainY) {
grounded = true;
break;
}
BlockState state = world.getBlockState(position.set(column.x(), y, column.z()));
if (state.is(expectedStilt.getBlock())) {
stiltBlocks++;
@@ -1041,7 +1041,8 @@ public final class IrisModdedChunkGenerator extends ChunkGenerator {
String structureId, StructureStart start,
IrisNativeStructureDecision decision) {
NativeStructurePostProcessor.place(world, structureManager, this, random, area, chunkPos,
structureId, start, decision, this::resolveStiltBlock);
structureId, start, decision, this::resolveStiltBlock,
(x, z) -> engine().getHeight(x, z, true) + engine().getMinHeight());
}
private List<List<Structure>> structuresByStep(Registry<Structure> registry) {
@@ -19,6 +19,7 @@
package art.arcane.iris.modded;
import art.arcane.iris.core.nms.datapack.DataVersion;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.framework.NativeStructureGenerationPolicy;
import art.arcane.iris.engine.framework.StructureVerticalBounds;
import art.arcane.iris.engine.object.IrisDimension;
@@ -44,6 +45,7 @@ import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGeneratorStructureState;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.levelgen.Heightmap;
@@ -71,6 +73,7 @@ import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BooleanSupplier;
import java.util.function.IntBinaryOperator;
public final class ModdedWorldCheck {
private static final int EXIT_PASS = 0;
@@ -872,9 +875,16 @@ public final class ModdedWorldCheck {
BoundingBox area = new BoundingBox(
minimumChunkX, minimumWorldY, minimumChunkZ,
maximumChunkX, maximumWorldY, maximumChunkZ);
ChunkGenerator chunkGenerator = level.getChunkSource().getGenerator();
if (!(chunkGenerator instanceof IrisModdedChunkGenerator irisGenerator)) {
throw new IllegalStateException("Iris structure audit requires the Iris chunk generator");
}
Engine engine = irisGenerator.commandEngine();
IntBinaryOperator surfaceHeight = (x, z) ->
engine.getHeight(x, z, true) + engine.getMinHeight();
NativeStructurePostProcessor.StiltSupportAudit foundation =
NativeStructurePostProcessor.auditStiltSupport(
level, area, start, Blocks.COBBLESTONE.defaultBlockState());
level, area, start, Blocks.COBBLESTONE.defaultBlockState(), surfaceHeight);
foundationBaseColumns = foundation.baseColumns();
foundationBlocks = foundation.stiltBlocks();
foundationColumns = foundation.stiltColumns();