Cleared records under native writes

- Added DeferredPlacementRecords to gate tracking on Identifier and TileWrapper slices
- Cleared deferred custom and tile records at positions native structure placement changed
- Implemented block change tracking in the Bukkit and modded structure policies
- Covered invalidation through the custom block materialization pass
- Covered modded wrapper change tracking and protected cells
- Passed disabled change sets in existing wrapper tests
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-16 19:36:35 -04:00
1 parent a3eccd8a65
commit ff537f4abc
7 files changed
+357 -9

No files matched your search

@@ -2,6 +2,7 @@ package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.terrain.structure.StructureStagePolicy;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.generation.mantle.DeferredPlacementRecords;
import art.arcane.iris.generation.terrain.IrisMaterialPalette;
import art.arcane.iris.structure.nativegen.GenerationWritePolicy;
import art.arcane.iris.structure.nativegen.IrisStructurePolicy;
@@ -13,6 +14,7 @@ import art.arcane.iris.structure.nativegen.StructureLocateSearch;
import art.arcane.iris.structure.placement.IrisStructureLocator;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.NativeModdedStructureStage;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureVolumeSource;
import art.arcane.volmlib.nativelib.terrain.NativeBlockChangeSet;
import art.arcane.volmlib.nativelib.terrain.NativeBlockPositionPredicate;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
import art.arcane.volmlib.nativelib.terrain.structure.StructureLocateSearchAccess;
@@ -107,6 +109,16 @@ final class ModdedNativeStructurePolicy implements NativeModdedStructureStage.Po
context.getDimensionStackContext(), context.getMinHeight());
}
@Override
public NativeBlockChangeSet trackBlockChanges(Engine context, NativeBlockChangeSet.Bounds bounds) {
return DeferredPlacementRecords.track(context, bounds);
}
@Override
public void invalidateBlockChanges(Engine context, NativeBlockChangeSet changes) {
DeferredPlacementRecords.invalidate(context, changes);
}
@Override
public IntBinaryOperator surfaceHeight(Engine context) {
return (x, z) -> Engine.hostHeight(context, x, z, true) + context.getMinHeight();
@@ -3,6 +3,7 @@ package art.arcane.iris.modded;
import art.arcane.volmlib.nativelib.minecraft26_2.modded.ModdedNativeStructureWorldgenAccess;
import art.arcane.iris.structure.placement.IrisStructureTerrain;
import art.arcane.volmlib.nativelib.terrain.NativeBlockChangeSet;
import art.arcane.volmlib.util.structure.StructureTerrainMode;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructurePostProcessor;
import art.arcane.volmlib.nativelib.minecraft26_2.terrain.NativeStructureTerrainIntegrator;
@@ -231,7 +232,8 @@ public class ModdedNativeStructureWorldgenAccessTest {
(x, z) -> SURFACE_FIRST_FREE_Y,
(x, z) -> FLOOR_FIRST_FREE_Y,
true,
position -> false);
position -> false,
NativeBlockChangeSet.disabled());
int x = generationCenter.getMiddleBlockX();
int z = generationCenter.getMiddleBlockZ();
@@ -249,7 +251,8 @@ public class ModdedNativeStructureWorldgenAccessTest {
(x, z) -> SURFACE_FIRST_FREE_Y,
(x, z) -> FLOOR_FIRST_FREE_Y,
false,
position::equals);
position::equals,
NativeBlockChangeSet.disabled());
assertSame(Blocks.DIRT, access.getBlockState(position).getBlock());
assertFalse(access.ensureCanWrite(position));
@@ -270,6 +273,37 @@ public class ModdedNativeStructureWorldgenAccessTest {
assertEquals(1, recording.mutations);
}
@Test
public void acceptedWritesAndReportedChangesAreTrackedOutsideProtectedCells() {
RecordingDelegate recording = new RecordingDelegate();
BlockPos protectedCell = generationCenter().getMiddleBlockPosition(70);
WorldGenLevel delegate = recording.world();
NativeBlockChangeSet changes = NativeBlockChangeSet.create(
ModdedNativeStructureWorldgenAccess.changeBounds(delegate, generationCenter()));
ModdedNativeStructureWorldgenAccess access = ModdedNativeStructureWorldgenAccess.create(
delegate, generationCenter(),
(x, z) -> SURFACE_FIRST_FREE_Y,
(x, z) -> FLOOR_FIRST_FREE_Y,
false,
protectedCell::equals,
changes);
BlockPos written = protectedCell.above();
BlockPos removed = protectedCell.east();
BlockPos reported = protectedCell.above(2);
assertFalse(access.setBlock(protectedCell, Blocks.STONE.defaultBlockState(), 2));
assertTrue(access.setBlock(written, Blocks.STONE.defaultBlockState(), 2));
assertTrue(access.removeBlock(removed, false));
access.recordBlockChange(reported.getX(), reported.getY(), reported.getZ());
access.recordBlockChange(protectedCell.getX(), protectedCell.getY(), protectedCell.getZ());
assertEquals(3, changes.size());
assertTrue(changes.contains(written.getX(), written.getY(), written.getZ()));
assertTrue(changes.contains(removed.getX(), removed.getY(), removed.getZ()));
assertTrue(changes.contains(reported.getX(), reported.getY(), reported.getZ()));
assertFalse(changes.contains(protectedCell.getX(), protectedCell.getY(), protectedCell.getZ()));
}
@Test
public void statuslessChunkReadsPreserveWorldgenDelegateSemantics() {
RecordingDelegate recording = new RecordingDelegate();
@@ -320,7 +354,8 @@ public class ModdedNativeStructureWorldgenAccessTest {
(x, z) -> SURFACE_FIRST_FREE_Y,
(x, z) -> FLOOR_FIRST_FREE_Y,
false,
position -> false);
position -> false,
NativeBlockChangeSet.disabled());
}
private static ChunkPos generationCenter() {