This commit is contained in:
Brian Neumann-Fopiano
2026-07-30 12:31:39 -04:00
parent 0afbfcb7a2
commit 324cf9e095
374 changed files with 22705 additions and 25650 deletions
@@ -106,11 +106,26 @@ public class CustomBiomeSource extends BiomeSource {
return o;
}
return invokeFor(type, source);
o = invokeFor(type, source);
if (o != null) {
return o;
}
throw new IllegalStateException("Iris cannot resolve a " + type.getName()
+ " from " + source.getClass().getName() + " on this server version");
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
for (Class<?> sourceType = in.getClass(); sourceType != null; sourceType = sourceType.getSuperclass()) {
Object o = fieldForClass(returns, sourceType, in);
if (o != null) {
return o;
}
}
return null;
}
private static Object invokeFor(Class<?> returns, Object in) {
@@ -120,8 +135,9 @@ public class CustomBiomeSource extends BiomeSource {
try {
IrisLogging.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
} catch (ReflectiveOperationException | RuntimeException e) {
throw new IllegalStateException("Iris failed to invoke " + in.getClass().getName() + "."
+ i.getName() + "() for " + returns.getName(), e);
}
}
}
@@ -137,8 +153,9 @@ public class CustomBiomeSource extends BiomeSource {
try {
IrisLogging.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalAccessException | RuntimeException e) {
throw new IllegalStateException("Iris failed to read " + sourceType.getName() + "."
+ i.getName() + " for " + returnType.getName(), e);
}
}
}
@@ -241,7 +258,13 @@ public class CustomBiomeSource extends BiomeSource {
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
RegistryAccess access = registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
if (access == null) {
throw new IllegalStateException("Iris cannot resolve the Minecraft registry access on this server version");
}
return access;
}
@Override
@@ -15,6 +15,11 @@ import art.arcane.iris.nativegen.NativeStructureStartInjector;
import art.arcane.iris.nativegen.NativeStructureReferenceEnvelope;
import art.arcane.iris.nativegen.NativeStructureLocateResults;
import art.arcane.iris.nativegen.NativeStructurePostProcessor;
import art.arcane.iris.nativegen.NativeStructureSurfaceFitter;
import art.arcane.iris.nativegen.NativeStructureTerrainIntegrator;
import art.arcane.iris.nativegen.NativeStructureVegetationClearer;
import art.arcane.iris.nativegen.NativeStructureVerticalPlacer;
import art.arcane.iris.nativegen.WorldgenTerrainHeightmaps;
import art.arcane.iris.spi.PlatformBlockState;
import art.arcane.iris.util.common.data.IrisCustomData;
import art.arcane.iris.util.common.reflect.WrappedField;
@@ -184,7 +189,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
}
String key = id.toString();
IrisNativeStructureDecision decision = NativeStructureGenerationPolicy.resolve(engine,
key, NativeStructurePostProcessor.isUndergroundStep(holder.value().step()));
key, NativeStructureVegetationClearer.isUndergroundStep(holder.value().step()));
if (!decision.generate()) {
continue;
}
@@ -290,7 +295,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
throw NativeStructureGenerationException.failure(
"resolution", null, chunkPos.x(), chunkPos.z());
}
boolean undergroundStep = NativeStructurePostProcessor.isUndergroundStep(structure.step());
boolean undergroundStep = NativeStructureVegetationClearer.isUndergroundStep(structure.step());
IrisNativeStructureDecision decision;
try {
decision = NativeStructureGenerationPolicy.resolve(engine,
@@ -304,7 +309,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
continue;
}
try {
NativeStructurePostProcessor.applyVerticalPlacement(
NativeStructureVerticalPlacer.applyVerticalPlacement(
start,
structureId,
decision.yShift(),
@@ -317,7 +322,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
(x, z) -> engine.getHeight(x, z, true) + engine.getMinHeight());
StructureStart wrapped = NativeStructureReferenceEnvelope.wrap(
start, structure, start.getReferences(), templateManager,
NativeStructurePostProcessor.resolveNativeTerrain(start, decision.terrain()));
NativeStructureTerrainIntegrator.resolveNativeTerrain(start, decision.terrain()));
access.setStartForStructure(structure, wrapped);
} catch (Throwable error) {
throw NativeStructureGenerationException.failure(
@@ -448,8 +453,8 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
List<NativePlacementGroup> placementGroups = new ArrayList<>();
List<StructureStart> heightmapStarts = new ArrayList<>();
List<StructureStart> nativeStarts = new ArrayList<>();
List<NativeStructurePostProcessor.VegetationTarget> vegetationTargets = new ArrayList<>();
List<NativeStructurePostProcessor.TerrainTarget> terrainTargets = new ArrayList<>();
List<NativeStructureVegetationClearer.VegetationTarget> vegetationTargets = new ArrayList<>();
List<NativeStructureTerrainIntegrator.TerrainTarget> terrainTargets = new ArrayList<>();
for (int step = 0; step < steps; step++) {
int index = 0;
for (Structure structure : byStep.get(step)) {
@@ -461,7 +466,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
}
try {
IrisNativeStructureDecision sourceDecision = NativeStructureGenerationPolicy.resolve(engine,
structureId, NativeStructurePostProcessor.isUndergroundStep(structure.step()));
structureId, NativeStructureVegetationClearer.isUndergroundStep(structure.step()));
List<StructureStart> starts = structureManager.startsForStructure(sectionPos, structure);
List<NativePlacement> resolvedPlacements = new ArrayList<>(starts.size());
for (StructureStart start : starts) {
@@ -474,17 +479,17 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
}
resolvedPlacements.add(new NativePlacement(start, decision));
heightmapStarts.add(start);
terrainTargets.add(new NativeStructurePostProcessor.TerrainTarget(
terrainTargets.add(new NativeStructureTerrainIntegrator.TerrainTarget(
structureId, start,
NativeStructurePostProcessor.resolveNativeTerrain(
NativeStructureTerrainIntegrator.resolveNativeTerrain(
start, decision.terrain())));
if (plan == null || !plan.placement().isUnderground()) {
nativeStarts.add(start);
}
boolean clearEntireFootprint = NativeStructurePostProcessor
boolean clearEntireFootprint = NativeStructureVegetationClearer
.shouldClearEntireVegetationFootprint(
structure.step(), decision.clearVegetation());
vegetationTargets.add(new NativeStructurePostProcessor.VegetationTarget(
vegetationTargets.add(new NativeStructureVegetationClearer.VegetationTarget(
start, clearEntireFootprint));
}
if (!resolvedPlacements.isEmpty()) {
@@ -507,7 +512,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
chunkPos.x(), chunkPos.z(), error);
}
try {
NativeStructurePostProcessor.prepareSurfaceStructures(
NativeStructureSurfaceFitter.prepareSurfaceStructures(
world, area, nativeStarts,
(x, z) -> engine.getHeight(x, z, true) + engine.getMinHeight());
} catch (Throwable error) {
@@ -516,7 +521,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
chunkPos.x(), chunkPos.z(), error);
}
try {
NativeStructurePostProcessor.clearIntersectingVegetation(
NativeStructureVegetationClearer.clearIntersectingVegetation(
world, chunk, area, vegetationTargets);
} catch (Throwable error) {
throw NativeStructureGenerationException.failure(
@@ -741,27 +746,30 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
}
static {
Field biomeSource = null;
List<Field> biomeSources = new ArrayList<>(1);
for (Field field : ChunkGenerator.class.getDeclaredFields()) {
if (!field.getType().equals(BiomeSource.class))
continue;
biomeSource = field;
break;
biomeSources.add(field);
}
if (biomeSource == null)
throw new RuntimeException("Could not find biomeSource field in ChunkGenerator!");
if (biomeSources.size() != 1)
throw new IllegalStateException("Expected exactly one BiomeSource field in ChunkGenerator, found "
+ biomeSources.size() + " " + biomeSources.stream().map(Field::getName).toList());
Field biomeSource = biomeSources.getFirst();
Method setHeight = null;
List<Method> setHeights = new ArrayList<>(1);
for (Method method : Heightmap.class.getDeclaredMethods()) {
Class<?>[] types = method.getParameterTypes();
if (types.length != 3 || !Arrays.equals(types, new Class<?>[]{int.class, int.class, int.class})
if (!method.getName().equals("setHeight")
|| !Arrays.equals(types, new Class<?>[]{int.class, int.class, int.class})
|| !method.getReturnType().equals(void.class))
continue;
setHeight = method;
break;
setHeights.add(method);
}
if (setHeight == null)
throw new RuntimeException("Could not find setHeight method in Heightmap!");
if (setHeights.size() != 1)
throw new IllegalStateException("Expected exactly one Heightmap.setHeight(int,int,int) method, found "
+ setHeights.size());
Method setHeight = setHeights.getFirst();
BIOME_SOURCE = new WrappedField<>(ChunkGenerator.class, biomeSource.getName());
SET_HEIGHT = new WrappedReturningMethod<>(Heightmap.class, setHeight.getName(), setHeight.getParameterTypes());
@@ -171,7 +171,14 @@ public class NMSBinding implements INMSBinding {
return o;
}
return invokeFor(type, source);
o = invokeFor(type, source);
if (o != null) {
return o;
}
throw new IllegalStateException("Iris cannot resolve a " + type.getName()
+ " from " + source.getClass().getName() + " on this server version");
}
private static Object invokeFor(Class<?> returns, Object in) {
@@ -181,8 +188,9 @@ public class NMSBinding implements INMSBinding {
try {
IrisLogging.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
} catch (ReflectiveOperationException | RuntimeException e) {
throw new IllegalStateException("Iris failed to invoke " + in.getClass().getName() + "."
+ i.getName() + "() for " + returns.getName(), e);
}
}
}
@@ -191,7 +199,15 @@ public class NMSBinding implements INMSBinding {
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
for (Class<?> sourceType = in.getClass(); sourceType != null; sourceType = sourceType.getSuperclass()) {
Object o = fieldForClass(returns, sourceType, in);
if (o != null) {
return o;
}
}
return null;
}
@SuppressWarnings("unchecked")
@@ -202,8 +218,9 @@ public class NMSBinding implements INMSBinding {
try {
IrisLogging.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalAccessException | RuntimeException e) {
throw new IllegalStateException("Iris failed to read " + sourceType.getName() + "."
+ i.getName() + " for " + returnType.getName(), e);
}
}
}
@@ -366,11 +383,18 @@ public class NMSBinding implements INMSBinding {
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
RegistryAccess access = registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
if (access == null) {
throw new IllegalStateException("Iris cannot resolve the Minecraft registry access on this server version");
}
return access;
}
private Registry<net.minecraft.world.level.biome.Biome> getCustomBiomeRegistry() {
return registry().lookup(Registries.BIOME).orElse(null);
return registry().lookup(Registries.BIOME).orElseThrow(() -> new IllegalStateException(
"Iris cannot resolve the Minecraft biome registry on this server version"));
}
private Registry<Block> getBlockRegistry() {
@@ -435,7 +459,26 @@ public class NMSBinding implements INMSBinding {
@Override
public String getKeyForBiomeBase(Object biomeBase) {
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
net.minecraft.world.level.biome.Biome biome;
if (biomeBase instanceof Holder<?> holder) {
Object value = holder.value();
if (!(value instanceof net.minecraft.world.level.biome.Biome held)) {
throw new IllegalArgumentException("Iris cannot read a biome key from holder value "
+ (value == null ? "null" : value.getClass().getName()));
}
biome = held;
} else if (biomeBase instanceof net.minecraft.world.level.biome.Biome direct) {
biome = direct;
} else {
throw new IllegalArgumentException("Iris cannot read a biome key from "
+ (biomeBase == null ? "null" : biomeBase.getClass().getName()));
}
Identifier key = getCustomBiomeRegistry().getKey(biome);
if (key == null) {
throw new IllegalStateException("Iris found no registry key for biome " + biome);
}
return key.getPath(); // something, not something:something
}
@Override
@@ -805,7 +848,7 @@ public class NMSBinding implements INMSBinding {
@Override
public MCAPaletteAccess createPalette() {
MCAIdMapper<BlockState> registry = registryCache.aquireNasty(() -> {
MCAIdMapper<BlockState> registry = registryCache.aquireNastyPrint(() -> {
Field cf = IdMapper.class.getDeclaredField("tToId");
Field df = IdMapper.class.getDeclaredField("idToT");
Field bf = IdMapper.class.getDeclaredField("nextId");
@@ -818,7 +861,13 @@ public class NMSBinding implements INMSBinding {
List<BlockState> d = (List<BlockState>) df.get(blockData);
return new MCAIdMapper<BlockState>(c, d, b);
});
MCAPalette<BlockState> global = globalCache.aquireNasty(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState()));
if (registry == null) {
throw new IllegalStateException("Iris cannot mirror the Minecraft block state id map on this server version");
}
MCAPalette<BlockState> global = globalCache.aquireNastyPrint(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState()));
if (global == null) {
throw new IllegalStateException("Iris cannot build the global block state palette on this server version");
}
java.util.Map<CompoundTag, BlockState> innerDecodeCache = new java.util.concurrent.ConcurrentHashMap<>(64);
java.util.Map<CompoundTag, BlockState> outerDecodeCache = new java.util.concurrent.ConcurrentHashMap<>(64);
MCAPalettedContainer<BlockState> container = new MCAPalettedContainer<>(global, registry,
@@ -1,106 +0,0 @@
package art.arcane.iris.core.nms.v26_2_R1;
import net.minecraft.core.SectionPos;
import net.minecraft.util.Mth;
import net.minecraft.util.SimpleBitStorage;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.IntBinaryOperator;
/**
* Writes WORLD_SURFACE_WG and OCEAN_FLOOR_WG from Iris engine heights.
*
* Iris writes its terrain straight into LevelChunkSection, so neither vanilla's noise fill nor
* ProtoChunk.setBlockState ever updates the two worldgen heightmaps. Without these writes
* ChunkAccess.getHeight lazily primes the map from finished blocks - Iris trees, leaves and snow
* included - and vanilla pieces that self-snap against WORLD_SURFACE_WG (igloo) or OCEAN_FLOOR_WG
* (ocean ruins, buried treasure, mineshaft interiors) anchor to the canopy instead of the terrain.
*
* Both resolvers take world block coordinates and return the absolute first free Y, matching
* Heightmap's internal "first available" semantics: WORLD_SURFACE_WG counts fluid, OCEAN_FLOOR_WG
* does not.
*/
final class WorldgenTerrainHeightmaps {
private static final int COLUMNS = 256;
private static final int PLACEMENT_CHUNK_MARGIN = 1;
private WorldgenTerrainHeightmaps() {
}
static void primeTerrain(ChunkAccess chunk, IntBinaryOperator surfaceFirstFreeY,
IntBinaryOperator floorFirstFreeY) {
Objects.requireNonNull(chunk, "Iris worldgen heightmap priming requires a chunk");
Objects.requireNonNull(surfaceFirstFreeY,
"Iris worldgen heightmap priming requires a surface height resolver");
Objects.requireNonNull(floorFirstFreeY,
"Iris worldgen heightmap priming requires an ocean floor height resolver");
write(chunk, Heightmap.Types.WORLD_SURFACE_WG, surfaceFirstFreeY);
write(chunk, Heightmap.Types.OCEAN_FLOOR_WG, floorFirstFreeY);
}
static void primeStructurePlacement(WorldGenLevel world, List<StructureStart> starts,
IntBinaryOperator surfaceFirstFreeY,
IntBinaryOperator floorFirstFreeY) {
Objects.requireNonNull(world,
"Iris worldgen heightmap priming requires a generation level");
if (starts == null || starts.isEmpty()) {
return;
}
Set<Long> primed = new HashSet<>();
for (StructureStart start : starts) {
if (start == null || !start.isValid()) {
continue;
}
BoundingBox bounds = start.getBoundingBox();
int minChunkX = SectionPos.blockToSectionCoord(bounds.minX()) - PLACEMENT_CHUNK_MARGIN;
int maxChunkX = SectionPos.blockToSectionCoord(bounds.maxX()) + PLACEMENT_CHUNK_MARGIN;
int minChunkZ = SectionPos.blockToSectionCoord(bounds.minZ()) - PLACEMENT_CHUNK_MARGIN;
int maxChunkZ = SectionPos.blockToSectionCoord(bounds.maxZ()) + PLACEMENT_CHUNK_MARGIN;
for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX++) {
for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ++) {
if (!primed.add(ChunkPos.pack(chunkX, chunkZ))) {
continue;
}
if (!world.hasChunk(chunkX, chunkZ)) {
continue;
}
primeTerrain(world.getChunk(chunkX, chunkZ), surfaceFirstFreeY, floorFirstFreeY);
}
}
}
}
private static void write(ChunkAccess chunk, Heightmap.Types type, IntBinaryOperator firstFreeY) {
ChunkPos pos = chunk.getPos();
int minY = chunk.getMinY();
int height = chunk.getHeight();
int baseX = pos.getMinBlockX();
int baseZ = pos.getMinBlockZ();
SimpleBitStorage storage = new SimpleBitStorage(Mth.ceillog2(height + 1), COLUMNS);
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int firstFree = firstFreeY.applyAsInt(baseX + x, baseZ + z) - minY;
storage.set(x + z * 16, Mth.clamp(firstFree, 0, height));
}
}
Heightmap heightmap = chunk.getOrCreateHeightmapUnprimed(type);
long[] packed = storage.getRaw();
int expected = heightmap.getRawData().length;
if (expected != packed.length) {
throw new IllegalStateException("Iris cannot prime " + type + " for chunk "
+ pos.x() + "," + pos.z() + ": packed " + packed.length
+ " words for a heightmap storing " + expected
+ "; Heightmap.setRawData would silently fall back to block scanning");
}
heightmap.setRawData(chunk, type, packed);
}
}
@@ -91,6 +91,27 @@ public class IrisChunkGeneratorFailureContractTest {
assertTrue(source.contains("engine.acquireGenerationLease(\"bukkit_nms_worldgen_heightmaps\")"));
}
@Test
public void worldgenHeightmapPrimingLivesInTheSharedNativegenSources() throws IOException {
Path nativegen = Path.of(System.getProperty("iris.nativeStructurePostProcessorSource")).getParent();
Path shared = nativegen.resolve("WorldgenTerrainHeightmaps.java");
assertTrue("Worldgen heightmap priming must be shared with the modded loaders through "
+ nativegen, Files.isRegularFile(shared));
String heightmaps = Files.readString(shared);
assertTrue(heightmaps.contains("package art.arcane.iris.nativegen;"));
assertTrue(heightmaps.contains("public static void primeTerrain("));
assertTrue(heightmaps.contains("public static void primeStructurePlacement("));
assertFalse(heightmaps.contains("org.bukkit"));
assertFalse(heightmaps.contains("craftbukkit"));
String source = Files.readString(Path.of(System.getProperty("iris.nmsChunkGeneratorSource")));
assertTrue(source.contains("import art.arcane.iris.nativegen.WorldgenTerrainHeightmaps;"));
}
private static int occurrences(String source, String needle) {
int count = 0;
int index = source.indexOf(needle);
@@ -79,23 +79,32 @@ public class IrisChunkGeneratorMonumentLocateContractTest {
@Test
public void stiltSupportUsesPlacedSolidOccupancyWithoutSnapshotDifferenceRequirement() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.nativeStructurePostProcessorSource")));
Path processor = Path.of(System.getProperty("iris.nativeStructurePostProcessorSource"));
String source = Files.readString(processor);
String foundation = Files.readString(
processor.resolveSibling("NativeStructureFoundationBuilder.java"));
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("Math.max(terrainY,", stiltPlacement);
int stiltDefinition = foundation.indexOf("static void placeStilts(");
int occupancyCheck = foundation.indexOf("if (state.isSolid())", stiltDefinition);
int terrainFloor = foundation.indexOf("Math.max(terrainY,", stiltDefinition);
assertTrue(placement >= 0);
assertTrue(stiltPlacement > placement);
assertTrue(occupancyCheck > stiltPlacement);
assertTrue(terrainFloor > stiltPlacement);
assertTrue(stiltDefinition >= 0);
assertTrue(occupancyCheck > stiltDefinition);
assertTrue(terrainFloor > stiltDefinition);
assertFalse(source.contains("state.equals("));
assertFalse(foundation.contains("state.equals("));
assertFalse(source.contains("snapshot.states"));
assertFalse(foundation.contains("snapshot.states"));
}
@Test
public void verticalPlacementMovesPiecesMonumentChildrenJigsawJunctionsAndCachedBoundsTogether() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.nativeStructurePostProcessorSource")));
String source = Files.readString(
Path.of(System.getProperty("iris.nativeStructurePostProcessorSource"))
.resolveSibling("NativeStructureVerticalPlacer.java"));
int placementStart = source.indexOf("public static int applyVerticalPlacement");
int shiftStart = source.indexOf("public static int applyVerticalShift", placementStart);
int alignmentStart = source.indexOf("static int alignOceanMonumentToSeaLevel", shiftStart);
@@ -1,5 +1,6 @@
package art.arcane.iris.core.nms.v26_2_R1;
import art.arcane.iris.nativegen.WorldgenTerrainHeightmaps;
import com.mojang.serialization.Codec;
import net.minecraft.SharedConstants;
import net.minecraft.core.BlockPos;
@@ -95,7 +95,7 @@ public class NativeStructureFactoryTest {
new PiecesContainer(List.of(piece))
);
StructureStart relocated = NativeStructurePostProcessor.relocateToMinY(
StructureStart relocated = NativeStructureVerticalPlacer.relocateToMinY(
start, source, -20, LevelHeightAccessor.create(-64, 384));
assertNotSame(start, relocated);
@@ -61,7 +61,7 @@ public class NativeStructurePostProcessorEncaseTest {
put(blocks, bounds.minX(), bounds.minY(), bounds.minZ(), Blocks.DIRT.defaultBlockState());
put(blocks, bounds.maxX(), bounds.minY(), bounds.maxZ(), Blocks.WATER.defaultBlockState());
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), area, "minecraft:stronghold", start,
new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.ENCASE)
@@ -86,7 +86,7 @@ public class NativeStructurePostProcessorEncaseTest {
BoundingBox bounds = start.getPieces().getFirst().getBoundingBox();
Map<BlockPos, BlockState> blocks = new HashMap<>();
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), bounds, "minecraft:stronghold", start,
new IrisStructureTerrain().setMode(IrisStructureTerrainMode.ENCASE),
null);
@@ -105,7 +105,7 @@ public class NativeStructurePostProcessorEncaseTest {
Map<BlockPos, BlockState> blocks = new HashMap<>();
IrisMaterialPalette palette = new IrisMaterialPalette().qclear().qadd("minecraft:tuff");
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), bounds, "minecraft:stronghold", start,
new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.ENCASE)
@@ -131,7 +131,7 @@ public class NativeStructurePostProcessorEncaseTest {
@Test
public void buryAndEncapsulateAdaptationsAutoDefaultToEncase() {
for (TerrainAdjustment adjustment : List.of(TerrainAdjustment.BURY, TerrainAdjustment.ENCAPSULATE)) {
IrisStructureTerrain resolved = NativeStructurePostProcessor.resolveNativeTerrain(
IrisStructureTerrain resolved = NativeStructureTerrainIntegrator.resolveNativeTerrain(
start(adjustment, 64), null);
assertEquals(IrisStructureTerrainMode.ENCASE, resolved.resolvedMode());
@@ -146,7 +146,7 @@ public class NativeStructurePostProcessorEncaseTest {
public void otherAdaptationsNeverAutoDefaultToEncase() {
for (TerrainAdjustment adjustment : List.of(
TerrainAdjustment.NONE, TerrainAdjustment.BEARD_THIN, TerrainAdjustment.BEARD_BOX)) {
assertNull(NativeStructurePostProcessor.resolveNativeTerrain(
assertNull(NativeStructureTerrainIntegrator.resolveNativeTerrain(
start(adjustment, 64), null));
}
}
@@ -156,7 +156,7 @@ public class NativeStructurePostProcessorEncaseTest {
IrisStructureTerrain configured = new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.SOURCE);
assertSame(configured, NativeStructurePostProcessor.resolveNativeTerrain(
assertSame(configured, NativeStructureTerrainIntegrator.resolveNativeTerrain(
start(TerrainAdjustment.BURY, 64), configured));
}
@@ -189,9 +189,9 @@ public class NativeStructurePostProcessorEncaseTest {
StructureStart first = start(TerrainAdjustment.BURY, 64);
StructureStart second = start(TerrainAdjustment.BURY, 64);
NativeStructurePostProcessor.applyVerticalShift(
NativeStructureVerticalPlacer.applyVerticalShift(
first, -64, -256, 320, true, false, band, (x, z) -> 40);
NativeStructurePostProcessor.applyVerticalShift(
NativeStructureVerticalPlacer.applyVerticalShift(
second, -64, -256, 320, true, false, band, (x, z) -> 40);
BoundingBox bounds = first.getBoundingBox();
@@ -199,7 +199,7 @@ public class NativeStructurePostProcessorEncaseTest {
assertTrue(bounds.minY() >= -120);
assertTrue(bounds.maxY() <= -20);
int repeated = NativeStructurePostProcessor.applyVerticalShift(
int repeated = NativeStructureVerticalPlacer.applyVerticalShift(
first, -64, -256, 320, true, false, band, (x, z) -> 40);
assertEquals(0, repeated);
}
@@ -209,7 +209,7 @@ public class NativeStructurePostProcessorEncaseTest {
IrisStructureYBand band = new IrisStructureYBand().setMin(-50).setMax(-45);
StructureStart start = start(TerrainAdjustment.BURY, 64);
NativeStructurePostProcessor.applyVerticalShift(
NativeStructureVerticalPlacer.applyVerticalShift(
start, 0, -256, 320, true, false, band, (x, z) -> 40);
BoundingBox bounds = start.getBoundingBox();
@@ -225,7 +225,7 @@ public class NativeStructurePostProcessorEncaseTest {
BoundingBox bounds = start.getBoundingBox();
int height = bounds.maxY() - bounds.minY();
NativeStructurePostProcessor.applyVerticalShift(
NativeStructureVerticalPlacer.applyVerticalShift(
start, -200, -256, 320, true, false, band, (x, z) -> 40);
assertEquals(-64 - height / 2, start.getBoundingBox().minY());
@@ -237,7 +237,7 @@ public class NativeStructurePostProcessorEncaseTest {
StructureStart start = start(TerrainAdjustment.BURY, 64);
int minY = start.getBoundingBox().minY();
int offset = NativeStructurePostProcessor.applyVerticalShift(
int offset = NativeStructureVerticalPlacer.applyVerticalShift(
start, 0, -256, 320, true, true, band, (x, z) -> 40);
assertEquals(0, offset);
@@ -33,7 +33,7 @@ public class NativeStructurePostProcessorMonumentTest {
public void vanillaSeaLevelKeepsTheVanillaMonumentHeight() {
StructureStart start = monumentStart(1337L);
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:monument", 0, 63, -64, 320, false, false, null, (x, z) -> 0);
assertEquals(0, offset);
@@ -45,11 +45,11 @@ public class NativeStructurePostProcessorMonumentTest {
public void shiftedSeaLevelMovesTheShellAndEveryRoomTogether() {
StructureStart start = monumentStart(1337L);
OceanMonumentPieces.MonumentBuilding building = monumentBuilding(start);
List<StructurePiece> children = NativeStructurePostProcessor.monumentChildPieces(building);
List<StructurePiece> children = NativeStructureVerticalPlacer.monumentChildPieces(building);
int[] childMinY = minimumYs(children);
BoundingBox cachedBounds = start.getBoundingBox();
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:monument", 0, 50, -256, 512, false, false, null, (x, z) -> 0);
assertEquals(-13, offset);
@@ -63,7 +63,7 @@ public class NativeStructurePostProcessorMonumentTest {
assertEquals(childMinY[i] - 13, children.get(i).getBoundingBox().minY());
}
int repeatedOffset = NativeStructurePostProcessor.applyVerticalPlacement(
int repeatedOffset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:monument", 0, 50, -256, 512, false, false, null, (x, z) -> 0);
assertEquals(0, repeatedOffset);
}
@@ -72,7 +72,7 @@ public class NativeStructurePostProcessorMonumentTest {
public void configuredOffsetIsRelativeToTheActualSeaLevel() {
StructureStart start = monumentStart(1337L);
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:monument", 3, 50, -256, 512, false, false, null, (x, z) -> 0);
assertEquals(-10, offset);
@@ -85,7 +85,7 @@ public class NativeStructurePostProcessorMonumentTest {
long seed = 1337L;
ChunkPos chunkPos = new ChunkPos(0, 0);
StructureStart initial = monumentStart(seed);
NativeStructurePostProcessor.applyVerticalPlacement(
NativeStructureVerticalPlacer.applyVerticalPlacement(
initial, "minecraft:monument", 0, 50, -256, 512, false, false, null, (x, z) -> 0);
PiecesContainer regenerated = OceanMonumentStructure.regeneratePiecesAfterLoad(
@@ -94,7 +94,7 @@ public class NativeStructurePostProcessorMonumentTest {
monumentStructure(), chunkPos, 0, regenerated);
assertEquals(39, reloaded.getBoundingBox().minY());
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
reloaded, "minecraft:monument", 0, 50, -256, 512, false, false, null, (x, z) -> 0);
assertEquals(-13, offset);
assertEquals(26, reloaded.getBoundingBox().minY());
@@ -105,7 +105,7 @@ public class NativeStructurePostProcessorMonumentTest {
public void impossibleSeaLevelAlignmentFailsInsteadOfClippingTheMonument() {
StructureStart start = monumentStart(1337L);
try {
NativeStructurePostProcessor.applyVerticalPlacement(
NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:monument", 0, -50, -64, 320, false, false, null, (x, z) -> 0);
} catch (IllegalStateException error) {
assertTrue(error.getMessage().contains("cannot align"));
@@ -45,7 +45,7 @@ public class NativeStructurePostProcessorScatteredFeatureTest {
BoundingBox cachedBounds = start.getBoundingBox();
BoundingBox footprint = piece.getBoundingBox();
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:desert_pyramid", 0, 63, -64, 320, false, false, null,
(x, z) -> x == footprint.maxX() && z == footprint.maxZ() ? 64 : 92);
@@ -63,7 +63,7 @@ public class NativeStructurePostProcessorScatteredFeatureTest {
StructureStart start = jungleStart(piece);
BoundingBox footprint = piece.getBoundingBox();
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:jungle_pyramid", 4, 63, -64, 320, false, false, null,
(x, z) -> x == footprint.minX() && z == footprint.minZ() ? 88 : 70);
@@ -78,9 +78,9 @@ public class NativeStructurePostProcessorScatteredFeatureTest {
TestDesertPyramidPiece piece = new TestDesertPyramidPiece(RandomSource.create(23L), 0, 0);
StructureStart start = desertStart(piece);
int initialOffset = NativeStructurePostProcessor.applyVerticalPlacement(
int initialOffset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:desert_pyramid", 0, 63, -64, 320, false, false, null, (x, z) -> 80);
int repeatedOffset = NativeStructurePostProcessor.applyVerticalPlacement(
int repeatedOffset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:desert_pyramid", 0, 63, -64, 320, false, false, null, (x, z) -> 80);
assertEquals(17, initialOffset);
@@ -93,7 +93,7 @@ public class NativeStructurePostProcessorScatteredFeatureTest {
TestDesertPyramidPiece piece = new TestDesertPyramidPiece(RandomSource.create(29L), 0, 0);
StructureStart start = desertStart(piece);
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
start, "minecraft:desert_pyramid", 0, 63, -64, 320, false, false, null, (x, z) -> 318);
assertEquals(241, offset);
@@ -110,12 +110,12 @@ public class NativeStructurePostProcessorScatteredFeatureTest {
StructureStart jungleStart = jungleStart(jungle);
StructureStart swampStart = swampStart(swamp);
assertFalse(NativeStructurePostProcessor.requiresSurfaceTerrain(desertStart));
assertFalse(NativeStructurePostProcessor.requiresSurfaceTerrain(jungleStart));
assertFalse(NativeStructurePostProcessor.requiresSurfaceTerrain(swampStart));
assertFalse(NativeStructureSurfaceFitter.requiresSurfaceTerrain(desertStart));
assertFalse(NativeStructureSurfaceFitter.requiresSurfaceTerrain(jungleStart));
assertFalse(NativeStructureSurfaceFitter.requiresSurfaceTerrain(swampStart));
AtomicInteger terrainQueries = new AtomicInteger();
int offset = NativeStructurePostProcessor.applyVerticalPlacement(
int offset = NativeStructureVerticalPlacer.applyVerticalPlacement(
swampStart, "minecraft:swamp_hut", 0, 63, -64, 320, false, false, null,
(x, z) -> terrainQueries.incrementAndGet());
assertEquals(0, offset);
@@ -125,7 +125,7 @@ public class NativeStructurePostProcessorScatteredFeatureTest {
@Test
public void scatteredHeightFieldMatchesTheRuntimeContract() {
Field field = NativeStructurePostProcessor.resolveScatteredHeightPositionField();
Field field = NativeStructureReflection.resolveScatteredHeightPositionField();
assertEquals(ScatteredFeaturePiece.class, field.getDeclaringClass());
assertEquals(int.class, field.getType());
@@ -61,13 +61,13 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
@Test
public void onlySurfaceBeardThinStructuresPrepareTerrain() {
assertTrue(NativeStructurePostProcessor.shouldPrepareSurfaceTerrain(
assertTrue(NativeStructureSurfaceFitter.shouldPrepareSurfaceTerrain(
TerrainAdjustment.BEARD_THIN, GenerationStep.Decoration.SURFACE_STRUCTURES));
assertFalse(NativeStructurePostProcessor.shouldPrepareSurfaceTerrain(
assertFalse(NativeStructureSurfaceFitter.shouldPrepareSurfaceTerrain(
TerrainAdjustment.BURY, GenerationStep.Decoration.SURFACE_STRUCTURES));
assertFalse(NativeStructurePostProcessor.shouldPrepareSurfaceTerrain(
assertFalse(NativeStructureSurfaceFitter.shouldPrepareSurfaceTerrain(
TerrainAdjustment.BEARD_BOX, GenerationStep.Decoration.SURFACE_STRUCTURES));
assertFalse(NativeStructurePostProcessor.shouldPrepareSurfaceTerrain(
assertFalse(NativeStructureSurfaceFitter.shouldPrepareSurfaceTerrain(
TerrainAdjustment.ENCAPSULATE, GenerationStep.Decoration.SURFACE_STRUCTURES));
}
@@ -78,86 +78,86 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
TerrainAdjustment.BURY,
TerrainAdjustment.BEARD_BOX,
TerrainAdjustment.ENCAPSULATE)) {
assertFalse(NativeStructurePostProcessor.shouldPrepareSurfaceTerrain(
assertFalse(NativeStructureSurfaceFitter.shouldPrepareSurfaceTerrain(
adjustment, GenerationStep.Decoration.UNDERGROUND_STRUCTURES));
}
}
@Test
public void surfaceAnchorIsFlushInsideAndUnchangedAtRadius() {
NativeStructurePostProcessor.SurfaceAnchor anchor = anchor(80, 2);
NativeStructureSurfaceFitter.SurfaceAnchor anchor = anchor(80, 2);
assertEquals(80, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(80, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(anchor), 2, 2, 64));
assertEquals(64, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(64, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(anchor), 16, 2, 64));
assertEquals(64, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(64, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(anchor), 17, 2, 64));
}
@Test
public void surfaceAnchorRaisesAndLowersThroughTheTaper() {
NativeStructurePostProcessor.SurfaceAnchor raised = anchor(80, 2);
NativeStructurePostProcessor.SurfaceAnchor lowered = anchor(64, 2);
NativeStructureSurfaceFitter.SurfaceAnchor raised = anchor(80, 2);
NativeStructureSurfaceFitter.SurfaceAnchor lowered = anchor(64, 2);
assertEquals(68, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(68, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(raised), 10, 2, 64));
assertEquals(76, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(76, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(lowered), 10, 2, 80));
}
@Test
public void containingRigidFloorsHaveDeterministicPriority() {
NativeStructurePostProcessor.SurfaceAnchor rigid = anchor(70, 2);
NativeStructurePostProcessor.SurfaceAnchor junction = anchor(90, 1);
NativeStructureSurfaceFitter.SurfaceAnchor rigid = anchor(70, 2);
NativeStructureSurfaceFitter.SurfaceAnchor junction = anchor(90, 1);
assertEquals(70, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(70, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(rigid, junction), 2, 2, 64));
assertEquals(70, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(70, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(junction, rigid), 2, 2, 64));
NativeStructurePostProcessor.SurfaceAnchor weakTie = anchor(48, 1);
NativeStructurePostProcessor.SurfaceAnchor strongTie = anchor(80, 2);
assertEquals(80, NativeStructurePostProcessor.resolveSurfaceTarget(
NativeStructureSurfaceFitter.SurfaceAnchor weakTie = anchor(48, 1);
NativeStructureSurfaceFitter.SurfaceAnchor strongTie = anchor(80, 2);
assertEquals(80, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(weakTie, strongTie), 2, 2, 64));
assertEquals(80, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(80, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(strongTie, weakTie), 2, 2, 64));
}
@Test
public void containingFootprintOverridesAnAdjacentPiecesFalloff() {
NativeStructurePostProcessor.SurfaceAnchor local =
new NativeStructurePostProcessor.SurfaceAnchor(0, 4, 0, 4, 65, 2);
NativeStructurePostProcessor.SurfaceAnchor adjacent =
new NativeStructurePostProcessor.SurfaceAnchor(5, 9, 0, 4, 80, 2);
NativeStructureSurfaceFitter.SurfaceAnchor local =
new NativeStructureSurfaceFitter.SurfaceAnchor(0, 4, 0, 4, 65, 2);
NativeStructureSurfaceFitter.SurfaceAnchor adjacent =
new NativeStructureSurfaceFitter.SurfaceAnchor(5, 9, 0, 4, 80, 2);
assertEquals(77, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(77, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(adjacent), 4, 2, 64));
assertEquals(65, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(65, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(local, adjacent), 4, 2, 64));
assertEquals(65, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(65, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(adjacent, local), 4, 2, 64));
}
@Test
public void opposingFalloffsBlendWithoutAnAbruptMidpointSeam() {
NativeStructurePostProcessor.SurfaceAnchor high =
new NativeStructurePostProcessor.SurfaceAnchor(0, 0, 0, 0, 80, 2);
NativeStructurePostProcessor.SurfaceAnchor low =
new NativeStructurePostProcessor.SurfaceAnchor(12, 12, 0, 0, 48, 2);
int previous = NativeStructurePostProcessor.resolveSurfaceTarget(
NativeStructureSurfaceFitter.SurfaceAnchor high =
new NativeStructureSurfaceFitter.SurfaceAnchor(0, 0, 0, 0, 80, 2);
NativeStructureSurfaceFitter.SurfaceAnchor low =
new NativeStructureSurfaceFitter.SurfaceAnchor(12, 12, 0, 0, 48, 2);
int previous = NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(high, low), 0, 0, 64);
for (int x = 1; x <= 12; x++) {
int forward = NativeStructurePostProcessor.resolveSurfaceTarget(
int forward = NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(high, low), x, 0, 64);
int reversed = NativeStructurePostProcessor.resolveSurfaceTarget(
int reversed = NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(low, high), x, 0, 64);
assertEquals(forward, reversed);
assertTrue(Math.abs(forward - previous) <= 4);
previous = forward;
}
assertEquals(64, NativeStructurePostProcessor.resolveSurfaceTarget(
assertEquals(64, NativeStructureSurfaceFitter.resolveSurfaceTarget(
List.of(high, low), 6, 0, 64));
}
@@ -170,7 +170,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
put(lowered, 0, 64, 0, Blocks.GRASS_BLOCK.defaultBlockState());
put(lowered, 0, 65, 0, Blocks.DANDELION.defaultBlockState());
NativeStructurePostProcessor.applySurfaceColumn(
NativeStructureSurfaceFitter.applySurfaceColumn(
world(lowered), new BlockPos.MutableBlockPos(),
0, 0, 64, 62, -64, 319);
@@ -185,7 +185,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
put(raised, 0, 64, 0, Blocks.GRASS_BLOCK.defaultBlockState());
put(raised, 0, 65, 0, Blocks.DANDELION.defaultBlockState());
NativeStructurePostProcessor.applySurfaceColumn(
NativeStructureSurfaceFitter.applySurfaceColumn(
world(raised), new BlockPos.MutableBlockPos(),
0, 0, 64, 68, -64, 319);
@@ -205,7 +205,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
put(blocks, 0, 66, 0, log);
put(blocks, 0, 68, 0, leaves);
NativeStructurePostProcessor.applySurfaceColumn(
NativeStructureSurfaceFitter.applySurfaceColumn(
world(blocks), new BlockPos.MutableBlockPos(),
0, 0, 64, 68, -64, 319);
@@ -221,7 +221,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
put(blocks, 0, 64, 0, Blocks.GRAVEL.defaultBlockState());
put(blocks, 0, 65, 0, Blocks.WATER.defaultBlockState());
NativeStructurePostProcessor.applySurfaceColumn(
NativeStructureSurfaceFitter.applySurfaceColumn(
world(blocks), new BlockPos.MutableBlockPos(),
0, 0, 64, 62, -64, 319);
@@ -236,7 +236,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
StructureStart start = desertStart();
int minY = start.getBoundingBox().minY();
int offset = NativeStructurePostProcessor.applyVerticalShift(
int offset = NativeStructureVerticalPlacer.applyVerticalShift(
start, 0, -64, 320, true, true, null, (x, z) -> 40);
assertEquals(0, offset);
@@ -248,7 +248,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
StructureStart start = desertStart();
int minY = start.getBoundingBox().minY();
int offset = NativeStructurePostProcessor.applyVerticalShift(
int offset = NativeStructureVerticalPlacer.applyVerticalShift(
start, -8, -64, 320, true, true, null, (x, z) -> 40);
assertEquals(-8, offset);
@@ -262,7 +262,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
int maxY = start.getBoundingBox().maxY();
int expected = 40 - 1 - maxY;
int offset = NativeStructurePostProcessor.applyVerticalShift(
int offset = NativeStructureVerticalPlacer.applyVerticalShift(
start, 0, -64, 320, true, false, null, (x, z) -> 40);
assertEquals(expected, offset);
@@ -275,7 +275,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
int minY = start.getBoundingBox().minY();
int worldMinY = minY - 4;
int offset = NativeStructurePostProcessor.applyVerticalShift(
int offset = NativeStructureVerticalPlacer.applyVerticalShift(
start, 0, worldMinY, 320, true, false, null, (x, z) -> worldMinY);
assertEquals(-4, offset);
@@ -289,7 +289,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
Map<BlockPos, BlockState> blocks = new HashMap<>();
put(blocks, bounds.minX(), bounds.minY(), bounds.minZ(), Blocks.STONE.defaultBlockState());
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), bounds, "minecraft:desert_pyramid", start,
new IrisStructureTerrain().setMode(IrisStructureTerrainMode.VACUUM), null);
@@ -310,7 +310,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
put(blocks, bounds.maxX(), bounds.maxY() + 1, bounds.maxZ(),
Blocks.STONE.defaultBlockState());
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), area, "minecraft:desert_pyramid", start,
new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.FORCE_CARVE)
@@ -345,7 +345,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
put(blocks, firstBounds.minX(), y, z, Blocks.STONE.defaultBlockState());
put(blocks, gapX, y, z, Blocks.STONE.defaultBlockState());
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), area, "minecraft:ancient_city", start,
new IrisStructureTerrain().setMode(IrisStructureTerrainMode.FORCE_CARVE), null);
@@ -372,7 +372,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
new BlockPos(1, 2, 0), Blocks.DEEPSLATE.defaultBlockState(), null)));
Map<Long, int[]> columns = new HashMap<>();
assertTrue(NativeStructurePostProcessor.emitTemplateColumns(
assertTrue(NativeStructureTerrainIntegrator.emitTemplateColumns(
List.of(template), new BlockPos(0, 0, 0), Rotation.NONE,
new BoundingBox(0, 0, 0, 1, 2, 0),
(x, z, minY, maxY) -> columns.put((long) x << 32 | z & 0xffffffffL,
@@ -392,7 +392,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
new BlockPos(0, 1, 0), Blocks.STRUCTURE_VOID.defaultBlockState(), null)));
Map<Long, int[]> columns = new HashMap<>();
assertTrue(NativeStructurePostProcessor.emitTemplateColumns(
assertTrue(NativeStructureTerrainIntegrator.emitTemplateColumns(
List.of(template), new BlockPos(0, 0, 0), Rotation.NONE,
new BoundingBox(0, 0, 0, 0, 1, 0),
(x, z, minY, maxY) -> columns.put((long) x << 32 | z & 0xffffffffL,
@@ -406,7 +406,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
StructureStart start = desertStart();
BoundingBox bounds = start.getPieces().getFirst().getBoundingBox();
StructureCarvingFootprint footprint = NativeStructurePostProcessor.carveFootprint(
StructureCarvingFootprint footprint = NativeStructureTerrainIntegrator.carveFootprint(
start, 4, NativeStructurePostProcessorSurfaceTerrainTest::forbiddenTemplateManager);
assertEquals(bounds.minX() - 4, footprint.minX());
@@ -423,13 +423,13 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
public void carveFootprintIsComputedOncePerStartAndPadding() {
StructureStart start = desertStart();
StructureCarvingFootprint first = NativeStructurePostProcessor.carveFootprint(
StructureCarvingFootprint first = NativeStructureTerrainIntegrator.carveFootprint(
start, 6, NativeStructurePostProcessorSurfaceTerrainTest::forbiddenTemplateManager);
StructureCarvingFootprint repeated = NativeStructurePostProcessor.carveFootprint(
StructureCarvingFootprint repeated = NativeStructureTerrainIntegrator.carveFootprint(
start, 6, NativeStructurePostProcessorSurfaceTerrainTest::forbiddenTemplateManager);
StructureCarvingFootprint widened = NativeStructurePostProcessor.carveFootprint(
StructureCarvingFootprint widened = NativeStructureTerrainIntegrator.carveFootprint(
start, 7, NativeStructurePostProcessorSurfaceTerrainTest::forbiddenTemplateManager);
StructureCarvingFootprint other = NativeStructurePostProcessor.carveFootprint(
StructureCarvingFootprint other = NativeStructureTerrainIntegrator.carveFootprint(
desertStart(), 6, NativeStructurePostProcessorSurfaceTerrainTest::forbiddenTemplateManager);
assertSame(first, repeated);
@@ -441,13 +441,13 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
public void organicCarveNeverCutsBelowTheColumnSupportingFloor() {
StructureStart start = desertStart();
BoundingBox bounds = start.getPieces().getFirst().getBoundingBox();
NativeStructurePostProcessor.OrganicCarve carve = organicCarve(start, 6);
NativeStructureTerrainIntegrator.OrganicCarve carve = organicCarve(start, 6);
BoundingBox area = new BoundingBox(
bounds.minX() - 6, bounds.minY() - 4, bounds.minZ() - 6,
bounds.maxX() + 6, bounds.maxY() + 12, bounds.maxZ() + 6);
Map<BlockPos, BlockState> blocks = fill(area);
NativeStructurePostProcessor.carveOrganicColumns(world(blocks), area, carve);
NativeStructureTerrainIntegrator.carveOrganicColumns(world(blocks), area, carve);
int centerX = bounds.minX() + bounds.getXSpan() / 2;
int centerZ = bounds.minZ() + bounds.getZSpan() / 2;
@@ -471,9 +471,9 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
Map<BlockPos, BlockState> uniformBlocks = fill(area);
Map<BlockPos, BlockState> lobedBlocks = fill(area);
NativeStructurePostProcessor.carveOrganicColumns(
NativeStructureTerrainIntegrator.carveOrganicColumns(
world(uniformBlocks), area, organicCarve(start, 10, 0D));
NativeStructurePostProcessor.carveOrganicColumns(
NativeStructureTerrainIntegrator.carveOrganicColumns(
world(lobedBlocks), area, organicCarve(start, 10, 0.85D));
int uniform = 0;
@@ -521,9 +521,9 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
Map<BlockPos, BlockState> narrowBlocks = fill(narrow);
// Each chunk context rebuilds its own noise channels from the shared start identity.
NativeStructurePostProcessor.carveOrganicColumns(
NativeStructureTerrainIntegrator.carveOrganicColumns(
world(wideBlocks), wide, organicCarve(start, 6));
NativeStructurePostProcessor.carveOrganicColumns(
NativeStructureTerrainIntegrator.carveOrganicColumns(
world(narrowBlocks), narrow, organicCarve(start, 6));
int carved = 0;
@@ -552,7 +552,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
int centerX = bounds.minX() + bounds.getXSpan() / 2;
int centerZ = bounds.minZ() + bounds.getZSpan() / 2;
NativeStructurePostProcessor.integrateTerrain(
NativeStructureTerrainIntegrator.integrateTerrain(
world(blocks), area, "minecraft:ancient_city", start,
new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.FORCE_CARVE)
@@ -572,21 +572,21 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
@Test
public void sparseStiltGridIsDeterministicAndPreflightsGround() {
assertTrue(NativeStructurePostProcessor.isStiltColumn(0, 0, 4));
assertTrue(NativeStructurePostProcessor.isStiltColumn(-4, 8, 4));
assertFalse(NativeStructurePostProcessor.isStiltColumn(1, 0, 4));
assertTrue(NativeStructurePostProcessor.isStiltColumn(1, 1, 1));
assertTrue(NativeStructureFoundationBuilder.isStiltColumn(0, 0, 4));
assertTrue(NativeStructureFoundationBuilder.isStiltColumn(-4, 8, 4));
assertFalse(NativeStructureFoundationBuilder.isStiltColumn(1, 0, 4));
assertTrue(NativeStructureFoundationBuilder.isStiltColumn(1, 1, 1));
Map<BlockPos, BlockState> blocks = new HashMap<>();
put(blocks, 0, 7, 0, Blocks.DEEPSLATE.defaultBlockState());
put(blocks, 0, 8, 0, Blocks.SCULK_VEIN.defaultBlockState());
BlockPos.MutableBlockPos position = new BlockPos.MutableBlockPos();
assertEquals(7, NativeStructurePostProcessor.findStiltAnchorY(
assertEquals(7, NativeStructureFoundationBuilder.findStiltAnchorY(
world(blocks), 0, 0, 10, 2, -64, -64, position));
assertEquals(Integer.MIN_VALUE, NativeStructurePostProcessor.findStiltAnchorY(
assertEquals(Integer.MIN_VALUE, NativeStructureFoundationBuilder.findStiltAnchorY(
world(blocks), 0, 0, 10, 1, -64, -64, position));
assertEquals(Integer.MIN_VALUE, NativeStructurePostProcessor.findStiltAnchorY(
assertEquals(Integer.MIN_VALUE, NativeStructureFoundationBuilder.findStiltAnchorY(
world(new HashMap<>()), 0, 0, 10, 64, -64, -64, position));
}
@@ -635,7 +635,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
@Test
public void singlePoolTemplateFieldMatchesTheRuntimeContract() {
Field field = NativeStructurePostProcessor.resolveSinglePoolTemplateField();
Field field = NativeStructureReflection.resolveSinglePoolTemplateField();
assertEquals(SinglePoolElement.class, field.getDeclaringClass());
assertEquals(Either.class, field.getType());
@@ -649,12 +649,12 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
public void runtimeTemplatesAndLegacyAirUseTheExactContract() {
StructureTemplate runtimeTemplate = new StructureTemplate();
assertEquals(runtimeTemplate, NativeStructurePostProcessor.resolveTemplateReference(
assertEquals(runtimeTemplate, NativeStructureReflection.resolveTemplateReference(
Either.right(runtimeTemplate), null));
assertFalse(NativeStructurePostProcessor.shouldClearLegacyAir(79, 80, false));
assertTrue(NativeStructurePostProcessor.shouldClearLegacyAir(80, 80, false));
assertTrue(NativeStructurePostProcessor.shouldClearLegacyAir(96, 80, false));
assertFalse(NativeStructurePostProcessor.shouldClearLegacyAir(96, 80, true));
assertFalse(NativeStructureTerrainIntegrator.shouldClearLegacyAir(79, 80, false));
assertTrue(NativeStructureTerrainIntegrator.shouldClearLegacyAir(80, 80, false));
assertTrue(NativeStructureTerrainIntegrator.shouldClearLegacyAir(96, 80, false));
assertFalse(NativeStructureTerrainIntegrator.shouldClearLegacyAir(96, 80, true));
}
@Test
@@ -687,7 +687,7 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
blocks.put(belowFloorPosition, Blocks.DIRT.defaultBlockState());
blocks.put(outsidePosition, Blocks.DIRT.defaultBlockState());
NativeStructurePostProcessor.clearTemplateAir(
NativeStructureTerrainIntegrator.clearTemplateAir(
world(blocks), template, origin, 80, settings);
assertEquals(Blocks.AIR.defaultBlockState(), blocks.get(clearPosition));
@@ -699,11 +699,11 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
public void unrelatedPieceBoundsAreRejectedBeforeTemplateScanning() {
BoundingBox area = new BoundingBox(0, -64, 0, 15, 319, 15);
assertTrue(NativeStructurePostProcessor.intersects(
assertTrue(NativeStructureTerrainIntegrator.intersects(
new BoundingBox(15, 60, 15, 30, 90, 30), area));
assertFalse(NativeStructurePostProcessor.intersects(
assertFalse(NativeStructureTerrainIntegrator.intersects(
new BoundingBox(16, 60, 16, 30, 90, 30), area));
assertFalse(NativeStructurePostProcessor.intersects(
assertFalse(NativeStructureTerrainIntegrator.intersects(
new BoundingBox(0, 320, 0, 15, 350, 15), area));
}
@@ -717,23 +717,22 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
BlockState log = Blocks.OAK_LOG.defaultBlockState();
blocks.put(origin, log);
NativeStructurePostProcessor.clearTemplateAir(world(blocks), template, origin, 80, settings);
NativeStructureTerrainIntegrator.clearTemplateAir(world(blocks), template, origin, 80, settings);
assertEquals(log, blocks.get(origin));
}
private static NativeStructurePostProcessor.SurfaceAnchor anchor(int meetY, int strength) {
return new NativeStructurePostProcessor.SurfaceAnchor(0, 4, 0, 4, meetY, strength);
private static NativeStructureSurfaceFitter.SurfaceAnchor anchor(int meetY, int strength) {
return new NativeStructureSurfaceFitter.SurfaceAnchor(0, 4, 0, 4, meetY, strength);
}
private static NativeStructurePostProcessor.OrganicCarve organicCarve(StructureStart start,
int horizontalPadding) {
private static NativeStructureTerrainIntegrator.OrganicCarve organicCarve(
StructureStart start, int horizontalPadding) {
return organicCarve(start, horizontalPadding, 0.85D);
}
private static NativeStructurePostProcessor.OrganicCarve organicCarve(StructureStart start,
int horizontalPadding,
double lobeStrength) {
private static NativeStructureTerrainIntegrator.OrganicCarve organicCarve(
StructureStart start, int horizontalPadding, double lobeStrength) {
IrisStructureTerrain terrain = new IrisStructureTerrain()
.setMode(IrisStructureTerrainMode.FORCE_CARVE)
.setShape(IrisStructureCarveShape.ERODED)
@@ -743,8 +742,8 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
.setErosionStrength(1D)
.setErosionFrequency(0.05D)
.setLobeStrength(lobeStrength);
return NativeStructurePostProcessor.organicCarve(
NativeStructurePostProcessor.carveFootprint(start, horizontalPadding,
return NativeStructureTerrainIntegrator.organicCarve(
NativeStructureTerrainIntegrator.carveFootprint(start, horizontalPadding,
NativeStructurePostProcessorSurfaceTerrainTest::forbiddenTemplateManager),
terrain, IrisStructureCarveShape.ERODED, TEST_SEED);
}
@@ -778,8 +777,8 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
SLAB_WIDTH - 1 + SLAB_PADDING, transectY, SLAB_DEPTH - 1);
Map<BlockPos, BlockState> blocks = fill(area);
NativeStructurePostProcessor.carveOrganicColumns(world(blocks), area,
NativeStructurePostProcessor.organicCarve(
NativeStructureTerrainIntegrator.carveOrganicColumns(world(blocks), area,
NativeStructureTerrainIntegrator.organicCarve(
footprint, terrain, IrisStructureCarveShape.ERODED, TEST_SEED));
int[] depths = new int[SLAB_DEPTH];
@@ -11,53 +11,53 @@ import static org.junit.Assert.assertTrue;
public class NativeStructurePostProcessorVegetationTest {
@Test
public void surfaceStructuresClearTreeColumnsAutomatically() {
assertTrue(NativeStructurePostProcessor.shouldClearVegetationColumn(100, 100, false));
assertTrue(NativeStructurePostProcessor.shouldClearVegetationColumn(116, 100, false));
assertTrue(NativeStructureVegetationClearer.shouldClearVegetationColumn(100, 100, false));
assertTrue(NativeStructureVegetationClearer.shouldClearVegetationColumn(116, 100, false));
}
@Test
public void buriedStructuresPreserveUnrelatedSurfaceForest() {
assertFalse(NativeStructurePostProcessor.shouldClearVegetationColumn(99, 100, false));
assertFalse(NativeStructurePostProcessor.shouldClearVegetationColumn(20, 100, false));
assertFalse(NativeStructureVegetationClearer.shouldClearVegetationColumn(99, 100, false));
assertFalse(NativeStructureVegetationClearer.shouldClearVegetationColumn(20, 100, false));
}
@Test
public void explicitVegetationOptionForcesUnusualPlacementCleanup() {
assertTrue(NativeStructurePostProcessor.shouldClearVegetationColumn(20, 100, true));
assertTrue(NativeStructureVegetationClearer.shouldClearVegetationColumn(20, 100, true));
}
@Test
public void surfaceStructuresPreserveVegetationUnlessConfigured() {
assertFalse(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
assertFalse(NativeStructureVegetationClearer.shouldClearEntireVegetationFootprint(
GenerationStep.Decoration.SURFACE_STRUCTURES, false));
assertTrue(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
assertTrue(NativeStructureVegetationClearer.shouldClearEntireVegetationFootprint(
GenerationStep.Decoration.SURFACE_STRUCTURES, true));
}
@Test
public void undergroundStructuresPreserveSurfaceVegetationUnlessConfigured() {
assertFalse(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
assertFalse(NativeStructureVegetationClearer.shouldClearEntireVegetationFootprint(
GenerationStep.Decoration.UNDERGROUND_STRUCTURES, false));
assertTrue(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
assertTrue(NativeStructureVegetationClearer.shouldClearEntireVegetationFootprint(
GenerationStep.Decoration.UNDERGROUND_STRUCTURES, true));
}
@Test
public void allUndergroundGenerationStepsShareOneClassification() {
assertTrue(NativeStructurePostProcessor.isUndergroundStep(
assertTrue(NativeStructureVegetationClearer.isUndergroundStep(
GenerationStep.Decoration.UNDERGROUND_STRUCTURES));
assertTrue(NativeStructurePostProcessor.isUndergroundStep(
assertTrue(NativeStructureVegetationClearer.isUndergroundStep(
GenerationStep.Decoration.UNDERGROUND_DECORATION));
assertTrue(NativeStructurePostProcessor.isUndergroundStep(
assertTrue(NativeStructureVegetationClearer.isUndergroundStep(
GenerationStep.Decoration.STRONGHOLDS));
assertFalse(NativeStructurePostProcessor.isUndergroundStep(
assertFalse(NativeStructureVegetationClearer.isUndergroundStep(
GenerationStep.Decoration.SURFACE_STRUCTURES));
}
@Test
public void undergroundStructuresUseTheLowestTerrainColumn() {
BoundingBox bounds = new BoundingBox(0, 60, 0, 1, 80, 0);
int offset = NativeStructurePostProcessor.resolveBuriedOffset(
int offset = NativeStructureVerticalPlacer.resolveBuriedOffset(
bounds, 0, -64, 320, (x, z) -> x == 1 ? 76 : 100);
assertEquals(-5, offset);
}
@@ -65,7 +65,7 @@ public class NativeStructurePostProcessorVegetationTest {
@Test
public void undergroundBurialClampsToTheWorldFloorInsteadOfFailing() {
BoundingBox bounds = new BoundingBox(0, 60, 0, 1, 80, 0);
assertEquals(-2, NativeStructurePostProcessor.resolveBuriedOffset(
assertEquals(-2, NativeStructureVerticalPlacer.resolveBuriedOffset(
bounds, 0, 58, 320, (x, z) -> x == 1 ? 76 : 100));
}
}