mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-27 06:20:02 +00:00
Merge L4-terrain
This commit is contained in:
commit
cd61b75ff6
14 files changed
+786
-119
No files matched your search
+84
@@ -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);
|
||||
|
||||
+34
@@ -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();
|
||||
|
||||
+88
-3
@@ -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());
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user