This commit is contained in:
Brian Neumann-Fopiano
2026-09-10 13:08:12 -04:00
parent e33e6a632a
commit e4cdf2dcda
3 changed files with 125 additions and 4 deletions
@@ -145,6 +145,62 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
}
}
@Test
public void flattenBlendsAnElevatedRoadJunctionWithNearbyFoundations() {
List<NativeStructureSurfaceFitter.FlattenAnchor> anchors = new ArrayList<>();
for (int x : List.of(-3, 3)) {
for (int z = -1; z <= 1; z++) {
anchors.add(new NativeStructureSurfaceFitter.FlattenAnchor(
new NativeStructureSurfaceFitter.SurfaceAnchor(x, x, z, z, 64, 2), 24, 64));
}
}
anchors.add(new NativeStructureSurfaceFitter.FlattenAnchor(
new NativeStructureSurfaceFitter.SurfaceAnchor(0, 0, 0, 0, 105, 1), 24, 64));
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
NativeStructureSurfaceFitter.FlattenResolution grade =
NativeStructureSurfaceFitter.resolveFlattenSurface(anchors, x, z, 96);
assertTrue(grade.targetY() >= 64 && grade.targetY() <= 72);
assertEquals(grade, NativeStructureSurfaceFitter.resolveFlattenSurface(
anchors.reversed(), x, z, 96));
if (x < 1) {
assertTrue(Math.abs(grade.targetY() - NativeStructureSurfaceFitter.resolveFlattenSurface(
anchors, x + 1, z, 96).targetY()) <= 1);
}
if (z < 1) {
assertTrue(Math.abs(grade.targetY() - NativeStructureSurfaceFitter.resolveFlattenSurface(
anchors, x, z + 1, 96).targetY()) <= 1);
}
}
}
}
@Test
public void flattenPreservesAnExactRigidFloorBesideAnElevatedJunction() {
NativeStructureSurfaceFitter.FlattenAnchor rigid = new NativeStructureSurfaceFitter.FlattenAnchor(
new NativeStructureSurfaceFitter.SurfaceAnchor(0, 0, 0, 0, 64, 2), 24, 64);
NativeStructureSurfaceFitter.FlattenAnchor junction = new NativeStructureSurfaceFitter.FlattenAnchor(
new NativeStructureSurfaceFitter.SurfaceAnchor(0, 0, 0, 0, 105, 1), 24, 64);
assertEquals(64, NativeStructureSurfaceFitter.resolveFlattenSurface(
List.of(rigid, junction), 0, 0, 96).targetY());
assertEquals(64, NativeStructureSurfaceFitter.resolveFlattenSurface(
List.of(junction, rigid), 0, 0, 96).targetY());
}
@Test
public void flattenRetainsIsolatedJunctionSupportWithinItsConfiguredBounds() {
for (int radius : List.of(0, 24)) {
NativeStructureSurfaceFitter.FlattenAnchor junction = new NativeStructureSurfaceFitter.FlattenAnchor(
new NativeStructureSurfaceFitter.SurfaceAnchor(0, 0, 0, 0, 105, 1), radius, 8);
List<NativeStructureSurfaceFitter.FlattenAnchor> anchors = List.of(junction);
assertEquals(104, NativeStructureSurfaceFitter.resolveFlattenSurface(anchors, 0, 0, 96).targetY());
assertEquals(8, NativeStructureSurfaceFitter.resolveFlattenSurface(anchors, 0, 0, 96).range());
int outside = Math.max(1, radius);
assertEquals(96, NativeStructureSurfaceFitter.resolveFlattenSurface(anchors, outside, 0, 96).targetY());
assertEquals(0, NativeStructureSurfaceFitter.resolveFlattenSurface(anchors, outside, 0, 96).range());
}
}
@Test
public void flattenLevelsNonJigsawFoundationsAndRemovesDetachedRoofs() {
StructureStart start = desertStart();
@@ -188,6 +188,69 @@ public class NativeStructurePostProcessorVegetationTest {
bounds, 0, 58, 320, (x, z) -> x == 1 ? 76 : 100));
}
@Test
public void loweringSurfaceRemovesCactusStacksAndTheirFlowers() {
ProtoChunk chunk = chunk();
for (int y = 80; y <= 102; y++) {
write(chunk, 4, y, 4, Blocks.SAND.defaultBlockState());
}
for (int y = 103; y <= 105; y++) {
write(chunk, 4, y, 4, Blocks.CACTUS.defaultBlockState());
}
write(chunk, 4, 106, 4, Blocks.CACTUS_FLOWER.defaultBlockState());
NativeStructureSurfaceFitter.applySurfaceColumn(
world(chunk), new BlockPos.MutableBlockPos(), 4, 4, 102, 93, MIN_Y, MAX_Y);
assertEquals(Blocks.SAND.defaultBlockState(), chunk.getBlockState(new BlockPos(4, 93, 4)));
for (int y = 94; y <= 106; y++) {
assertTrue("Unsupported decoration at " + y, chunk.getBlockState(new BlockPos(4, y, 4)).isAir());
}
}
@Test
public void loweringSurfacePreservesCactusOnUnchangedColumns() {
ProtoChunk chunk = chunk();
for (int x : List.of(4, 5)) {
for (int y = 60; y <= 64; y++) {
write(chunk, x, y, 4, Blocks.SAND.defaultBlockState());
}
write(chunk, x, 65, 4, Blocks.CACTUS.defaultBlockState());
write(chunk, x, 66, 4, Blocks.CACTUS_FLOWER.defaultBlockState());
}
WorldGenLevel world = world(chunk);
NativeStructureSurfaceFitter.applySurfaceColumn(
world, new BlockPos.MutableBlockPos(), 4, 4, 64, 60, MIN_Y, MAX_Y);
NativeStructureSurfaceFitter.applySurfaceColumn(
world, new BlockPos.MutableBlockPos(), 5, 4, 64, 64, MIN_Y, MAX_Y);
assertTrue(chunk.getBlockState(new BlockPos(4, 65, 4)).isAir());
assertTrue(chunk.getBlockState(new BlockPos(4, 66, 4)).isAir());
assertEquals(Blocks.SAND.defaultBlockState(), chunk.getBlockState(new BlockPos(5, 64, 4)));
assertEquals(Blocks.CACTUS.defaultBlockState(), chunk.getBlockState(new BlockPos(5, 65, 4)));
assertEquals(Blocks.CACTUS_FLOWER.defaultBlockState(), chunk.getBlockState(new BlockPos(5, 66, 4)));
}
@Test
public void loweringSurfaceKeepsTreeAndSolidObjectBoundaries() {
for (BlockState boundary : List.of(Blocks.OAK_LOG.defaultBlockState(), Blocks.OAK_PLANKS.defaultBlockState())) {
ProtoChunk chunk = chunk();
write(chunk, 4, 63, 4, Blocks.SAND.defaultBlockState());
write(chunk, 4, 64, 4, Blocks.SAND.defaultBlockState());
write(chunk, 4, 65, 4, boundary);
write(chunk, 4, 66, 4, Blocks.CACTUS.defaultBlockState());
write(chunk, 4, 67, 4, Blocks.CACTUS_FLOWER.defaultBlockState());
NativeStructureSurfaceFitter.applySurfaceColumn(
world(chunk), new BlockPos.MutableBlockPos(), 4, 4, 64, 60, MIN_Y, MAX_Y);
assertEquals(boundary, chunk.getBlockState(new BlockPos(4, 65, 4)));
assertEquals(Blocks.CACTUS.defaultBlockState(), chunk.getBlockState(new BlockPos(4, 66, 4)));
assertEquals(Blocks.CACTUS_FLOWER.defaultBlockState(), chunk.getBlockState(new BlockPos(4, 67, 4)));
}
}
private static void clearVegetation(ProtoChunk chunk, StructureStart start) {
NativeStructureVegetationClearer.clearIntersectingVegetation(
world(chunk), chunk, AREA, List.of(start));
@@ -727,17 +727,18 @@ public final class NativeStructureSurfaceFitter {
SurfaceAnchor source = anchor.source();
int outX = IrisObjectVacuum.outset(x, source.minX(), source.maxX());
int outZ = IrisObjectVacuum.outset(z, source.minZ(), source.maxZ());
if (outX == 0 && outZ == 0) {
boolean containsColumn = outX == 0 && outZ == 0;
if (containsColumn && source.strength() > 1) {
if (selected == null || precedes(source, selected.source())) {
selected = anchor;
}
continue;
}
double distance = Math.sqrt((double) outX * outX + (double) outZ * outZ);
if (anchor.radius() == 0 || distance >= anchor.radius()) {
if (!containsColumn && (anchor.radius() == 0 || distance >= anchor.radius())) {
continue;
}
double progress = distance / anchor.radius();
double progress = containsColumn ? 0D : distance / anchor.radius();
double factor = 1D - progress * progress * (3D - 2D * progress);
long influence = Math.round(factor * SURFACE_TERRAIN_INFLUENCE_SCALE);
long weight = influence * source.strength();
@@ -1062,7 +1063,8 @@ public final class NativeStructureSurfaceFitter {
}
return fluid;
}
if (state.isSolid() || NativeStructureVegetationClearer.isTreeBlock(state)) {
if (state.isSolid() && !state.is(Blocks.CACTUS)
|| NativeStructureVegetationClearer.isTreeBlock(state)) {
return air;
}
world.setBlock(position, air, 2);