This commit is contained in:
Brian Neumann-Fopiano committed 2026-07-16 19:38:53 -04:00
1 parent e8dd4e1127
commit 0193f75daa
21 files changed
+272 -180

No files matched your search

@@ -70,10 +70,10 @@ public class CustomBiomeSource extends BiomeSource {
LinkedHashSet<Holder<Biome>> biomes = new LinkedHashSet<>();
for (IrisBiome i : engine.getAllBiomes()) {
Holder<Biome> vanillaHolder = NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative());
Holder<Biome> vanillaHolder = resolveBiomeHolder(registry, i.getStructureDerivativeKey());
if (vanillaHolder == null) {
throw new IllegalStateException("Iris structure biome derivative '"
+ i.getVanillaDerivativeKey() + "' is not registered for biome '" + i.getLoadKey() + "'");
+ i.getStructureDerivativeKey() + "' is not registered for biome '" + i.getLoadKey() + "'");
}
biomes.add(vanillaHolder);
@@ -312,10 +312,10 @@ public class CustomBiomeSource extends BiomeSource {
throw new IllegalStateException("Iris returned no surface structure biome at block "
+ blockX + "," + blockZ);
}
Holder<Biome> holder = NMSBinding.biomeToBiomeBase(biomeRegistry, irisBiome.getVanillaDerivative());
Holder<Biome> holder = resolveBiomeHolder(biomeRegistry, irisBiome.getStructureDerivativeKey());
if (holder == null) {
throw new IllegalStateException("Iris structure biome derivative '"
+ irisBiome.getVanillaDerivativeKey() + "' is not registered at block "
+ irisBiome.getStructureDerivativeKey() + "' is not registered at block "
+ blockX + "," + blockZ);
}
return holder;
@@ -371,10 +371,11 @@ public class CustomBiomeSource extends BiomeSource {
+ x + "," + y + "," + z);
}
Holder<Biome> holder = NMSBinding.biomeToBiomeBase(biomeRegistry, resolution.irisBiome.getVanillaDerivative());
Holder<Biome> holder = resolveBiomeHolder(
biomeRegistry, resolution.irisBiome.getStructureDerivativeKey());
if (holder == null) {
throw new IllegalStateException("Iris structure biome derivative '"
+ resolution.irisBiome.getVanillaDerivativeKey() + "' is not registered at block "
+ resolution.irisBiome.getStructureDerivativeKey() + "' is not registered at block "
+ resolution.blockX + "," + resolution.blockY + "," + resolution.blockZ);
}
return holder;
@@ -505,6 +506,17 @@ public class CustomBiomeSource extends BiomeSource {
return optionalReferenceHolder.get();
}
private static Holder<Biome> resolveBiomeHolder(Registry<Biome> registry, String biomeKey) {
if (registry == null || biomeKey == null || biomeKey.isBlank()) {
return null;
}
Identifier identifier = Identifier.tryParse(biomeKey);
if (identifier == null) {
return null;
}
return registry.get(ResourceKey.create(Registries.BIOME, identifier)).orElse(null);
}
private static Holder<Biome> resolveFallbackBiome(Registry<Biome> registry, Registry<Biome> customRegistry) {
Holder<Biome> plains = NMSBinding.biomeToBiomeBase(registry, org.bukkit.block.Biome.PLAINS);
if (plains != null) {
@@ -3,7 +3,6 @@ package art.arcane.iris.core.nms.v26_2_R1;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.framework.IrisStructureLocator;
import art.arcane.iris.engine.framework.NativeStructureGenerationPolicy;
import art.arcane.iris.core.structure.NativeStructureLocateCapability;
import art.arcane.iris.engine.object.IrisDimension;
import art.arcane.iris.engine.object.IrisNativeStructureDecision;
import art.arcane.iris.engine.object.IrisStructureStiltSettings;
@@ -174,7 +173,7 @@ public class IrisChunkGenerator extends CustomChunkGenerator {
String key = id.toString();
IrisNativeStructureDecision decision = NativeStructureGenerationPolicy.resolve(engine,
key, NativeStructurePostProcessor.isUndergroundStep(holder.value().step()));
if (NativeStructureLocateCapability.isPaperUnavailable(key) || !decision.generate()) {
if (!decision.generate()) {
continue;
}
candidates.add(new NativeLocateCandidate(holder, key));
@@ -0,0 +1,22 @@
package art.arcane.iris.core.nms.v26_2_R1;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class CustomBiomeSourceStructureContractTest {
@Test
public void nativeStructuresUseTerrainSafeDerivativeAtEveryBiomeBoundary() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.customBiomeSource")));
assertTrue(source.contains("resolveBiomeHolder(registry, i.getStructureDerivativeKey())"));
assertTrue(source.contains("resolveBiomeHolder(biomeRegistry, irisBiome.getStructureDerivativeKey())"));
assertTrue(source.contains("resolution.irisBiome.getStructureDerivativeKey()"));
assertFalse(source.contains("resolution.irisBiome.getVanillaDerivative()"));
}
}
@@ -17,7 +17,7 @@ import static org.junit.Assert.assertSame;
public class IrisChunkGeneratorMonumentLocateContractTest {
@Test
public void nativeLocateAllowsExplicitReplacementBeforeNativeCapabilityGate() throws IOException {
public void nativeLocateAllowsMonumentsAfterPolicyAndReachabilityChecks() throws IOException {
String source = Files.readString(Path.of(System.getProperty("iris.nmsChunkGeneratorSource")));
int findStart = source.indexOf("findNearestMapStructure(ServerLevel level");
assertTrue(findStart >= 0);
@@ -42,9 +42,9 @@ public class IrisChunkGeneratorMonumentLocateContractTest {
int reachabilityStart = source.indexOf("private Set<String> reachableStructureKeys", filterStart);
assertTrue(reachabilityStart > filterStart);
String filterMethod = source.substring(filterStart, reachabilityStart);
int monumentReject = filterMethod.indexOf("if (NativeStructureLocateCapability.isPaperUnavailable(key)");
int rejectContinue = filterMethod.indexOf("continue;", monumentReject);
int emptyNativePartition = filterMethod.indexOf("if (candidates.isEmpty())", rejectContinue);
int policyFilter = filterMethod.indexOf("if (!decision.generate())");
int filterContinue = filterMethod.indexOf("continue;", policyFilter);
int emptyNativePartition = filterMethod.indexOf("if (candidates.isEmpty())", filterContinue);
int reachabilityLookup = filterMethod.indexOf("reachableStructureKeys(level)", emptyNativePartition);
assertTrue(policyResolution >= 0);
@@ -58,10 +58,11 @@ public class IrisChunkGeneratorMonumentLocateContractTest {
assertTrue(nativeFilter >= 0);
assertTrue(delegateLocate > nativeFilter);
assertTrue(nearestSelection > delegateLocate);
assertTrue(monumentReject >= 0);
assertTrue(rejectContinue > monumentReject);
assertTrue(emptyNativePartition > rejectContinue);
assertTrue(policyFilter >= 0);
assertTrue(filterContinue > policyFilter);
assertTrue(emptyNativePartition > filterContinue);
assertTrue(reachabilityLookup > emptyNativePartition);
assertFalse(filterMethod.contains("NativeStructureLocateCapability"));
assertFalse(irisHelper.contains("NativeStructureLocateCapability.isPaperUnavailable(structureId)"));
assertTrue(irisHelper.contains("new BlockPos(result.originX(), result.baseY(), result.originZ())"));
}
@@ -173,6 +173,24 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
assertEquals(Blocks.GRASS_BLOCK.defaultBlockState(), state(raised, 0, 68, 0));
}
@Test
public void raisedSurfaceTerrainDoesNotSliceTreeBlocks() {
Map<BlockPos, BlockState> blocks = new HashMap<>();
BlockState log = Blocks.OAK_LOG.defaultBlockState();
BlockState leaves = Blocks.OAK_LEAVES.defaultBlockState();
put(blocks, 0, 63, 0, Blocks.DIRT.defaultBlockState());
put(blocks, 0, 64, 0, Blocks.GRASS_BLOCK.defaultBlockState());
put(blocks, 0, 66, 0, log);
put(blocks, 0, 68, 0, leaves);
NativeStructurePostProcessor.applySurfaceColumn(
world(blocks), new BlockPos.MutableBlockPos(),
0, 0, 64, 68, -64, 319);
assertEquals(log, state(blocks, 0, 66, 0));
assertEquals(leaves, state(blocks, 0, 68, 0));
}
@Test
public void loweredFluidColumnsRemainFluidFilled() {
Map<BlockPos, BlockState> blocks = new HashMap<>();
@@ -266,11 +284,18 @@ public class NativeStructurePostProcessorSurfaceTerrainTest {
}
@Test
public void vegetationCleanupUsesTheSameCircularTaperAsTerrain() {
BoundingBox piece = new BoundingBox(0, 60, 0, 4, 80, 4);
public void templateAirDoesNotEraseTreesInsideVillagePieces() throws Exception {
BlockPos origin = new BlockPos(0, 80, 0);
StructureTemplate template = template(List.of(
new StructureTemplate.StructureBlockInfo(BlockPos.ZERO, Blocks.AIR.defaultBlockState(), null)));
StructurePlaceSettings settings = new StructurePlaceSettings().setRotation(Rotation.NONE);
Map<BlockPos, BlockState> blocks = new HashMap<>();
BlockState log = Blocks.OAK_LOG.defaultBlockState();
blocks.put(origin, log);
assertTrue(NativeStructurePostProcessor.withinSurfaceTerrainRadius(16, 2, piece, 12));
assertFalse(NativeStructurePostProcessor.withinSurfaceTerrainRadius(16, 16, piece, 12));
NativeStructurePostProcessor.clearTemplateAir(world(blocks), template, origin, 80, settings);
assertEquals(log, blocks.get(origin));
}
private static NativeStructurePostProcessor.SurfaceAnchor anchor(int meetY, int strength) {
@@ -27,8 +27,8 @@ public class NativeStructurePostProcessorVegetationTest {
}
@Test
public void surfaceStructuresClearTheirEntireFootprintByDefault() {
assertTrue(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
public void surfaceStructuresPreserveVegetationUnlessConfigured() {
assertFalse(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
GenerationStep.Decoration.SURFACE_STRUCTURES, false));
assertTrue(NativeStructurePostProcessor.shouldClearEntireVegetationFootprint(
GenerationStep.Decoration.SURFACE_STRUCTURES, true));
@@ -21,7 +21,6 @@ package art.arcane.iris.core.commands;
import art.arcane.iris.Iris;
import art.arcane.iris.platform.bukkit.BukkitPlatform;
import art.arcane.iris.core.service.ObjectStudioSaveService;
import art.arcane.iris.core.structure.NativeStructureLocateCapability;
import art.arcane.iris.engine.framework.Engine;
import art.arcane.iris.engine.framework.IrisStructureLocator;
import art.arcane.iris.engine.framework.NativeStructureGenerationPolicy;
@@ -136,10 +135,6 @@ public class CommandFind implements DirectorExecutor {
locateIrisStructure(e, structureKey, commandSender);
return;
}
if (NativeStructureLocateCapability.isPaperUnavailable(structureKey)) {
commandSender.sendMessage(C.RED + NativeStructureLocateCapability.unavailableMessage());
return;
}
}
if (nativeStructure == null && IrisStructureLocator.isPlaced(e, structureKey)) {
@@ -21,7 +21,6 @@ package art.arcane.iris.core.commands;
import art.arcane.iris.Iris;
import art.arcane.iris.core.loader.IrisData;
import art.arcane.iris.core.structure.BulkStructureImporter;
import art.arcane.iris.core.structure.NativeStructureLocateCapability;
import art.arcane.iris.core.structure.StructureCaptureImporter;
import art.arcane.iris.core.structure.StructureImporter;
import art.arcane.iris.core.structure.StructureIndexService;
@@ -185,7 +184,6 @@ public class CommandStructure implements DirectorExecutor {
int nativeEligible = 0;
int disabled = 0;
int unreachable = 0;
int unavailable = 0;
int searchLimited = 0;
int errors = 0;
for (String keyName : structureKeys) {
@@ -228,19 +226,12 @@ public class CommandStructure implements DirectorExecutor {
continue;
}
nativeEligible++;
if (NativeStructureLocateCapability.isPaperUnavailable(keyName)) {
unavailable++;
messages.add(C.YELLOW + "[native-eligible/locate-unavailable] " + C.WHITE + keyName + C.YELLOW + ": "
+ NativeStructureLocateCapability.unavailableMessage());
continue;
}
messages.add(C.GREEN + "[native-eligible] " + C.WHITE + keyName);
}
messages.add(C.GREEN + "Structure verify: " + C.WHITE + located + C.GREEN + " Iris placements located, "
+ C.WHITE + nativeEligible + C.GREEN + " native structures eligible, "
+ C.WHITE + disabled + C.GREEN + " disabled by policy, "
+ C.WHITE + unreachable + C.GREEN + " biome-unreachable, "
+ C.WHITE + unavailable + C.GREEN + " generation-eligible but unavailable to synchronous locate, "
+ C.WHITE + searchLimited + C.GREEN + " density searches safety-limited, "
+ C.WHITE + errors + C.GREEN + " errors. Native eligibility is checked without running blocking live locates.");
sendVerificationMessages(commandSender, target, messages);
@@ -35,18 +35,17 @@ public class IrisStructureLocateCommandContractTest {
int replacementCheck = method.indexOf(
"decision.status() == NativeStructureGenerationStatus.REPLACED_BY_IRIS", policyResolution);
int replacementLocate = method.indexOf("locateIrisStructure(e, structureKey, commandSender)", replacementCheck);
int capabilityCheck = method.indexOf("NativeStructureLocateCapability.isPaperUnavailable(structureKey)", replacementLocate);
int genericIrisLookup = method.indexOf(
"nativeStructure == null && IrisStructureLocator.isPlaced(e, structureKey)", capabilityCheck);
"nativeStructure == null && IrisStructureLocator.isPlaced(e, structureKey)", replacementLocate);
int nativeLocate = method.indexOf("targetWorld.locateNearestStructure(", genericIrisLookup);
assertTrue(nativeResolution >= 0);
assertTrue(policyResolution > nativeResolution);
assertTrue(replacementCheck > policyResolution);
assertTrue(replacementLocate > replacementCheck);
assertTrue(capabilityCheck > replacementLocate);
assertTrue(genericIrisLookup > capabilityCheck);
assertTrue(genericIrisLookup > replacementLocate);
assertTrue(nativeLocate > policyResolution);
assertTrue(method.contains("decision.status() != NativeStructureGenerationStatus.REPLACED_BY_IRIS"));
assertFalse(method.contains("NativeStructureLocateCapability"));
}
@Test