Merge L4-terrain

This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-28 12:19:03 -04:00
commit cd61b75ff6
14 files changed
+786 -119

No files matched your search

@@ -0,0 +1,84 @@
package art.arcane.iris.generation.cache;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class ConcurrentClockCacheTest {
@Test
public void firstPublishedValueWins() {
ConcurrentClockCache<Object> cache = new ConcurrentClockCache<>(16);
Object first = new Object();
assertNull(cache.get(7L));
assertSame(first, cache.putIfAbsent(7L, first));
assertSame(first, cache.putIfAbsent(7L, new Object()));
assertSame(first, cache.get(7L));
cache.clear();
assertNull(cache.get(7L));
}
@Test
public void capacityBoundsRetainedEntries() {
ConcurrentClockCache<Long> cache = new ConcurrentClockCache<>(64);
for (long key = 0; key < 10_000; key++) {
assertEquals(Long.valueOf(key), cache.putIfAbsent(key, key));
}
AtomicInteger retained = new AtomicInteger();
cache.forEach(value -> {
retained.incrementAndGet();
assertEquals(value, cache.get(value));
});
assertEquals(cache.capacity(), retained.get());
assertTrue(cache.capacity() >= 64);
}
@Test
public void referencedEntriesSurviveAStreamOfOneTimeKeys() {
ConcurrentClockCache<Long> cache = new ConcurrentClockCache<>(4);
cache.putIfAbsent(-1L, -1L);
for (long key = 0; key < 1_000; key++) {
assertEquals(Long.valueOf(-1L), cache.get(-1L));
cache.putIfAbsent(key, key);
}
assertEquals(Long.valueOf(-1L), cache.get(-1L));
}
@Test
public void concurrentWritersAgreeOnOneValuePerKey() throws Exception {
ConcurrentClockCache<Object> cache = new ConcurrentClockCache<>(1 << 12);
List<Future<Object[]>> results = new ArrayList<>();
try (ExecutorService executor = Executors.newFixedThreadPool(8)) {
for (int thread = 0; thread < 8; thread++) {
results.add(executor.submit(() -> {
Object[] seen = new Object[256];
for (int key = 0; key < seen.length; key++) {
seen[key] = cache.putIfAbsent(key, new Object());
}
return seen;
}));
}
Object[] reference = results.getFirst().get(10, TimeUnit.SECONDS);
for (Future<Object[]> result : results) {
Object[] seen = result.get(10, TimeUnit.SECONDS);
for (int key = 0; key < seen.length; key++) {
Object cached = cache.get(key);
if (cached != null) {
assertSame(cached, seen[key]);
assertSame(reference[key], seen[key]);
}
}
}
}
}
}
@@ -2,6 +2,8 @@ package art.arcane.iris.generation.decoration;
import art.arcane.iris.generation.biome.IrisBiome;
import art.arcane.iris.generation.block.IrisBlockData;
import art.arcane.iris.generation.block.VectorMap;
import art.arcane.iris.structure.object.IrisObject;
import art.arcane.iris.pack.loading.IrisData;
import art.arcane.volmlib.util.documentation.Description;
@@ -224,6 +226,38 @@ public class IrisDepositTuningTest {
assertNotEquals(17L * samples, largeBlocks);
}
@Test
public void ellipsoidFootprintConsumesTheBuildDrawsAndMatchesItsGeometry() {
IrisData data = mock(IrisData.class);
IrisDepositGenerator generator = generatorWithState(data, true);
generator.setShape(IrisDepositShape.VANILLA_ELLIPSOID);
for (int size : new int[]{0, 1, 3, 4, 9, 17, 25, 64}) {
generator.setMinSize(size).setMaxSize(size);
for (long seed = 0; seed < 300; seed++) {
RNG built = new RNG(seed);
IrisObject clump = generator.getClump(null, built, data);
RNG sampled = new RNG(seed);
IrisDepositGenerator.ClumpFootprint footprint = generator.sampleClumpFootprint(sampled, data);
assertNotNull(footprint);
assertEquals(clump.getW(), footprint.width());
assertEquals(clump.getBlocks().size() == 0, footprint.empty());
if (!footprint.empty()) {
int minimumY = Integer.MAX_VALUE;
VectorMap<NativeBlockState>.Cursor cursor = clump.getBlocks().cursor();
while (cursor.next()) {
minimumY = Math.min(minimumY, cursor.key().getBlockY());
}
assertEquals(minimumY, footprint.minY());
}
assertEquals(built.nextLong(), sampled.nextLong());
}
}
generator.setMinSize(65).setMaxSize(65);
assertNull(generator.sampleClumpFootprint(new RNG(1L), data));
generator.setShape(IrisDepositShape.VANILLA_SCATTERED).setMinSize(4).setMaxSize(4);
assertNull(generator.sampleClumpFootprint(new RNG(1L), data));
}
@Test
public void vanillaScatteredSizeIsAnUpperCandidateBound() {
IrisData data = mock(IrisData.class);
@@ -1038,6 +1038,40 @@ public class IrisCaveCarver3DNearParityTest {
largestPlane < 192);
}
@Test
public void sharedDensityLatticeReproducesIsolatedCarvesAcrossNeighbourChunks() throws Exception {
Engine engine = createEngine(96, 90);
for (boolean warp : new boolean[]{false, true}) {
for (boolean modules : new boolean[]{false, true}) {
AtomicLong sharedSamples = new AtomicLong();
AtomicLong isolatedSamples = new AtomicLong();
IrisCaveCarver3D shared = new IrisCaveCarver3D(engine,
createProfile(warp, modules).setAdaptiveSampling(true), new CaveDensityGrid(4096));
baseDensityField.set(shared, new CountingCNG((CNG) baseDensityField.get(shared), sharedSamples));
for (int chunkX = -1; chunkX <= 1; chunkX++) {
for (int chunkZ = -1; chunkZ <= 1; chunkZ++) {
WriterCapture sharedCapture = createWriterCapture(96);
int sharedCarved = shared.carve(sharedCapture.writer, chunkX, chunkZ, fullWeights(), 0D, 0D,
null, filledHeights(90));
IrisCaveCarver3D isolated = new IrisCaveCarver3D(engine,
createProfile(warp, modules).setAdaptiveSampling(true));
baseDensityField.set(isolated, new CountingCNG((CNG) baseDensityField.get(isolated), isolatedSamples));
WriterCapture isolatedCapture = createWriterCapture(96);
int isolatedCarved = isolated.carve(isolatedCapture.writer, chunkX, chunkZ, fullWeights(), 0D, 0D,
null, filledHeights(90));
assertTrue(isolatedCarved > 0);
assertEquals(isolatedCarved, sharedCarved);
assertEquals(isolatedCapture.carvedCells, sharedCapture.carvedCells);
assertEquals(isolatedCapture.carvedLiquids, sharedCapture.carvedLiquids);
}
}
assertTrue("warp=" + warp + " modules=" + modules + " shared=" + sharedSamples.get()
+ " isolated=" + isolatedSamples.get(),
sharedSamples.get() < isolatedSamples.get() * 3 / 4);
}
}
}
private void assertExactParity(boolean warp, boolean modules, boolean adaptiveSampling) throws Exception {
Engine engine = createEngine(96, 90);
double[] columnWeights = fullWeights();
@@ -5,12 +5,14 @@ import art.arcane.iris.testsupport.KeyedBlockState;
import art.arcane.iris.pack.loading.IrisData;
import art.arcane.iris.generation.runtime.Engine;
import art.arcane.iris.generation.biome.IrisBiome;
import art.arcane.iris.generation.decoration.IrisDepositBiomeScope;
import art.arcane.iris.generation.decoration.IrisDepositGenerator;
import art.arcane.iris.generation.decoration.IrisDepositHeightDistribution;
import art.arcane.iris.generation.decoration.IrisDepositShape;
import art.arcane.iris.generation.decoration.IrisDepositVariant;
import art.arcane.iris.generation.terrain.IrisDimension;
import art.arcane.iris.generation.terrain.IrisRegion;
import art.arcane.iris.structure.object.IrisObject;
import art.arcane.iris.spi.IrisPlatform;
import art.arcane.iris.spi.IrisPlatforms;
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
@@ -25,17 +27,21 @@ import art.arcane.volmlib.util.mantle.runtime.Mantle;
import art.arcane.volmlib.util.mantle.runtime.MantleChunk;
import art.arcane.volmlib.util.matter.Matter;
import art.arcane.volmlib.util.matter.MatterCavern;
import art.arcane.volmlib.util.math.RNG;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.mockito.MockedStatic;
import art.arcane.iris.pack.loading.ResourceLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -84,8 +90,38 @@ public class IrisDepositModifierParityTest {
}
}
@SuppressWarnings("unchecked")
@Test
public void variantFreePacksSkipPerBlockCaveBiomeLookupsWithIdenticalOutput() {
for (long seed : new long[]{101L, -73L, 90181L}) {
AtomicInteger scannedLookups = new AtomicInteger();
AtomicInteger unscannedLookups = new AtomicInteger();
long[] scanned = generateConfigured(seed, false, false, true, scannedLookups);
long[] unscanned = generateConfigured(seed, false, false, false, unscannedLookups);
assertArrayEquals("seed=" + seed, unscanned, scanned);
assertTrue(scannedLookups.get() < unscannedLookups.get());
}
}
@Test
public void unmatchableSurfaceBiomeFiltersSkipClumpsWithoutChangingOutput() {
long[] expected = {-4609692219192155345L, 784L, 2118L, 53L, 67L, 11L};
AtomicInteger clumps = new AtomicInteger();
assertArrayEquals(expected, generateConfigured(101L, false, true, false, new AtomicInteger(), clumps));
assertEquals(0, clumps.get());
}
private long[] generateConfigured(long seed, boolean multicore) {
return generateConfigured(seed, multicore, true, false, new AtomicInteger());
}
private long[] generateConfigured(long seed, boolean multicore, boolean caveVariant, boolean enumerablePack,
AtomicInteger caveBiomeLookups) {
return generateConfigured(seed, multicore, caveVariant, enumerablePack, caveBiomeLookups, null);
}
@SuppressWarnings("unchecked")
private long[] generateConfigured(long seed, boolean multicore, boolean caveVariant, boolean enumerablePack,
AtomicInteger caveBiomeLookups, AtomicInteger unmatchableClumps) {
Engine engine = mock(Engine.class, RETURNS_DEEP_STUBS);
ChunkContext context = mock(ChunkContext.class, RETURNS_DEEP_STUBS);
IrisDimension dimension = new IrisDimension();
@@ -99,7 +135,9 @@ public class IrisDepositModifierParityTest {
denied.setLoadKey("denied");
IrisDepositVariant variant = new IrisDepositVariant().setMinHeight(-64).setMaxHeight(64);
variant.getRemap().put("minecraft:gold_ore", "minecraft:redstone_ore");
cave.getDepositVariants().add(variant);
if (caveVariant) {
cave.getDepositVariants().add(variant);
}
dimension.getDeposits().add(generator("granite", IrisDepositShape.IRIS, 25, 70,
IrisDepositHeightDistribution.CLIPPED_UNIFORM, "stone", "deepslate"));
region.getDeposits().add(generator("iron_ore", IrisDepositShape.VANILLA_ELLIPSOID, 20, 110,
@@ -114,11 +152,37 @@ public class IrisDepositModifierParityTest {
gold.setExcludedBiomes(new KList<>("allowed"));
gold.setDiscardChanceOnAirExposure(0.3D);
surface.getDeposits().add(gold);
if (unmatchableClumps != null) {
IrisDepositGenerator unmatchable = new CountingPaletteGenerator(state("emerald_ore"), unmatchableClumps)
.setShape(IrisDepositShape.VANILLA_ELLIPSOID).setMinSize(9).setMaxSize(9)
.setMinPerChunk(90).setMaxPerChunk(90).setMinHeight(-4).setMaxHeight(44)
.setHeightDistribution(IrisDepositHeightDistribution.UNIFORM).setSurfaceClearance(0)
.setReplaceableBlocks(new KList<>("stone"))
.setBiomeScope(IrisDepositBiomeScope.SURFACE)
.setIncludedBiomes(new KList<>("elsewhere"));
surface.getDeposits().add(unmatchable);
}
when(engine.getHeight()).thenReturn(48);
when(engine.getMinHeight()).thenReturn(-64);
when(engine.getSeedManager().getDeposit()).thenReturn(seed);
when(engine.getDimension()).thenReturn(dimension);
if (enumerablePack) {
IrisData data = mock(IrisData.class);
ResourceLoader<IrisBiome> biomes = mock(ResourceLoader.class);
ResourceLoader<IrisRegion> regions = mock(ResourceLoader.class);
when(data.getBiomeLoader()).thenReturn(biomes);
when(data.getRegionLoader()).thenReturn(regions);
when(biomes.getPossibleKeys()).thenReturn(new String[]{"allowed", "denied", "surface"});
when(biomes.load("allowed")).thenReturn(cave);
when(biomes.load("denied")).thenReturn(denied);
when(biomes.load("surface")).thenReturn(surface);
when(regions.getPossibleKeys()).thenReturn(new String[]{"region"});
when(regions.load("region")).thenReturn(region);
when(engine.getData()).thenReturn(data);
when(engine.getDimensionStackContext()).thenReturn(null);
}
when(engine.getCaveBiome(anyInt(), anyInt(), anyInt(), any())).thenAnswer(invocation -> {
caveBiomeLookups.incrementAndGet();
int x = invocation.getArgument(0);
int y = invocation.getArgument(1);
int z = invocation.getArgument(2);
@@ -366,7 +430,7 @@ public class IrisDepositModifierParityTest {
}
}
private static final class PaletteGenerator extends IrisDepositGenerator {
private static class PaletteGenerator extends IrisDepositGenerator {
private final KList<NativeBlockState> blocks;
private PaletteGenerator(NativeBlockState block) {
@@ -378,4 +442,25 @@ public class IrisDepositModifierParityTest {
return blocks;
}
}
private static final class CountingPaletteGenerator extends PaletteGenerator {
private final AtomicInteger clumps;
private CountingPaletteGenerator(NativeBlockState block, AtomicInteger clumps) {
super(block);
this.clumps = clumps;
}
@Override
public IrisObject getClump(Engine engine, RNG rng, IrisData data) {
clumps.incrementAndGet();
return super.getClump(engine, rng, data);
}
@Override
public ClumpFootprint sampleClumpFootprint(RNG rng, IrisData data) {
clumps.incrementAndGet();
return super.sampleClumpFootprint(rng, data);
}
}
}
@@ -302,7 +302,7 @@ public class Terrain3DRuntimeTest {
assertEquals(0, capacity % 16);
assertTrue(capacity >= 16);
assertTrue(capacity <= 32_768);
assertTrue(capacity * fullHeightStorage <= 64L * 1024 * 1024);
assertTrue(capacity * fullHeightStorage <= 128L * 1024 * 1024);
}
}
}
@@ -354,9 +354,10 @@ public class Terrain3DRuntimeTest {
for (int x = -65_536; x < 65_536; x++) {
assertEquals(96, runtime.column(x, -1).topY());
}
assertEquals(65_536, runtime.cachedColumnCount());
assertTrue(runtime.cachedColumnCount() > 0);
assertTrue(runtime.cachedColumnCount() <= 65_536);
assertEquals(96, runtime.column(-65_536, -1).topY());
assertEquals(65_536, runtime.cachedColumnCount());
assertTrue(runtime.cachedColumnCount() <= 65_536);
runtime.clear();
assertEquals(0, runtime.cachedColumnCount());
}