mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-22 16:17:44 +00:00
Merged terrain assembly improvements
- Ceiling layer thickness resolves independently from surface layers - Locked strata repeat correctly above the internal height reference - Cave scratch releases generation references after each pass - Terrain actuators omit redundant setup and checks
This commit is contained in:
commit
a68cad5893
16 files changed
+446
-223
No files matched your search
@@ -11,7 +11,6 @@ import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PackBiomeLayerValidatorTest {
|
||||
@@ -19,14 +18,12 @@ public class PackBiomeLayerValidatorTest {
|
||||
public TemporaryFolder temporaryFolder = new TemporaryFolder();
|
||||
|
||||
@Test
|
||||
public void rejectsMoreCeilingLayersThanLayers() throws Exception {
|
||||
public void acceptsMoreCeilingLayersThanSurfaceLayers() throws Exception {
|
||||
File pack = temporaryFolder.newFolder("pack");
|
||||
write(pack, "biomes/nested/cave.json",
|
||||
"{\"layers\":[{}],\"caveCeilingLayers\":[{},{},{}]}");
|
||||
|
||||
assertEquals(List.of(
|
||||
"Biome 'nested/cave' declares 3 caveCeilingLayers but only 1 layers. caveCeilingLayers reuses the layers height generators and must not have more entries."
|
||||
), PackBiomeLayerValidator.validateCeilingLayerCounts(new File(pack, "biomes")));
|
||||
assertTrue(PackBiomeLayerValidator.validateLayers(new File(pack, "biomes")).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -35,9 +32,7 @@ public class PackBiomeLayerValidatorTest {
|
||||
write(pack, "biomes/defaulted.json", "{\"name\":\"Defaulted\"}");
|
||||
write(pack, "biomes/implicit.json", "{\"caveCeilingLayers\":[{},{}]}");
|
||||
|
||||
assertEquals(List.of(
|
||||
"Biome 'implicit' declares 2 caveCeilingLayers but only 1 layers. caveCeilingLayers reuses the layers height generators and must not have more entries."
|
||||
), PackBiomeLayerValidator.validateCeilingLayerCounts(new File(pack, "biomes")));
|
||||
assertTrue(PackBiomeLayerValidator.validateLayers(new File(pack, "biomes")).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -45,7 +40,7 @@ public class PackBiomeLayerValidatorTest {
|
||||
File pack = temporaryFolder.newFolder("pack");
|
||||
write(pack, "biomes/ok.json", "{\"layers\":[{},{},{}],\"caveCeilingLayers\":[{},{}]}");
|
||||
|
||||
assertTrue(PackBiomeLayerValidator.validateCeilingLayerCounts(new File(pack, "biomes")).isEmpty());
|
||||
assertTrue(PackBiomeLayerValidator.validateLayers(new File(pack, "biomes")).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,11 +51,11 @@ public class PackBiomeLayerValidatorTest {
|
||||
assertEquals(List.of(
|
||||
"Biome 'bad' layers must be an array.",
|
||||
"Biome 'bad' caveCeilingLayers must be an array."
|
||||
), PackBiomeLayerValidator.validateCeilingLayerCounts(new File(pack, "biomes")));
|
||||
), PackBiomeLayerValidator.validateLayers(new File(pack, "biomes")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ceilingLayerOverflowBlocksFullPackValidation() throws Exception {
|
||||
public void independentCeilingLayersPassFullPackValidation() throws Exception {
|
||||
File pack = temporaryFolder.newFolder("pack");
|
||||
write(pack, "dimensions/main.json", "{\"regions\":[\"region\"]}");
|
||||
write(pack, "regions/region.json", "{\"landBiomes\":[\"biome\"]}");
|
||||
@@ -68,9 +63,7 @@ public class PackBiomeLayerValidatorTest {
|
||||
|
||||
PackValidationResult result = PackValidator.validate(pack);
|
||||
|
||||
assertFalse(result.isLoadable());
|
||||
assertTrue(result.getBlockingErrors().contains(
|
||||
"Biome 'biome' declares 2 caveCeilingLayers but only 1 layers. caveCeilingLayers reuses the layers height generators and must not have more entries."));
|
||||
assertTrue(result.getBlockingErrors().toString(), result.isLoadable());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+42
@@ -35,12 +35,15 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
@@ -114,6 +117,45 @@ public class IrisCaveCarver3DNearParityTest {
|
||||
carveForcedAirField.setAccessible(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void carvingReleasesSectionReferencesAfterSuccessAndFailure() throws Exception {
|
||||
for (boolean fail : new boolean[]{false, true}) {
|
||||
Engine engine = createEngine(128, 110);
|
||||
IrisCaveProfile profile = createProfile(false, false).setAdaptiveSampling(false)
|
||||
.setAllowFluid(false).setDetailWeight(0D)
|
||||
.setDensityThreshold(new IrisStyledRange(2D, 2D, new IrisGeneratorStyle(NoiseStyle.FLAT)));
|
||||
IrisCaveCarver3D carver = new IrisCaveCarver3D(engine, profile);
|
||||
WriterCapture capture = createWriterCapture(128);
|
||||
if (fail) {
|
||||
AtomicInteger samples = new AtomicInteger();
|
||||
CNG density = mock(CNG.class);
|
||||
doAnswer(invocation -> {
|
||||
if (samples.incrementAndGet() > 300) {
|
||||
throw new IllegalStateException("Density sample failed");
|
||||
}
|
||||
return -1D;
|
||||
}).when(density).noiseFastSigned3D(anyDouble(), anyDouble(), anyDouble());
|
||||
baseDensityField.set(carver, density);
|
||||
assertThrows(IllegalStateException.class, () -> carver.carve(capture.writer, 0, 0,
|
||||
fullWeights(), 0D, 0D, null, filledHeights(110)));
|
||||
} else {
|
||||
carver.carve(capture.writer, 0, 0, fullWeights(), 0D, 0D, null, filledHeights(110));
|
||||
}
|
||||
assertFalse(capture.carvedCells.isEmpty());
|
||||
Field scratchField = IrisCaveCarver3D.class.getDeclaredField("scratchCache");
|
||||
scratchField.setAccessible(true);
|
||||
ThreadLocal<?> scratchCache = (ThreadLocal<?>) scratchField.get(carver);
|
||||
CaveCarveScratch scratch = (CaveCarveScratch) scratchCache.get();
|
||||
assertTrue(scratch.sectionMatter.length > 0);
|
||||
for (Matter matter : scratch.sectionMatter) {
|
||||
assertNull(matter);
|
||||
}
|
||||
for (MatterSlice<?> slice : scratch.sectionSlices) {
|
||||
assertNull(slice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parallelDensityPreservesExactAndAdaptiveCavernsAndLiquids() throws Exception {
|
||||
try (ForkJoinPool pool = new ForkJoinPool(4)) {
|
||||
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
package art.arcane.iris.engine.mantle.components;
|
||||
|
||||
import art.arcane.iris.engine.IrisComplex;
|
||||
import art.arcane.iris.engine.framework.Engine;
|
||||
import art.arcane.iris.engine.framework.EngineMetrics;
|
||||
import art.arcane.iris.engine.mantle.EngineMantle;
|
||||
import art.arcane.iris.engine.mantle.MantleWriter;
|
||||
import art.arcane.iris.engine.object.IrisBiome;
|
||||
import art.arcane.iris.engine.object.IrisCaveProfile;
|
||||
import art.arcane.iris.engine.object.IrisDimension;
|
||||
import art.arcane.iris.engine.object.IrisRegion;
|
||||
import art.arcane.iris.engine.object.IrisWorld;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.project.context.ChunkContext;
|
||||
import art.arcane.iris.util.project.stream.ProceduralStream;
|
||||
import art.arcane.volmlib.util.mantle.runtime.Mantle;
|
||||
import art.arcane.volmlib.util.matter.Matter;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyDouble;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class MantleCarvingComponentScratchTest {
|
||||
private MantleCarvingComponent component;
|
||||
private IrisDimension dimension;
|
||||
private ChunkContext context;
|
||||
private MantleWriter writer;
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void prepare() {
|
||||
Engine engine = mock(Engine.class);
|
||||
EngineMantle mantle = mock(EngineMantle.class);
|
||||
when(mantle.getEngine()).thenReturn(engine);
|
||||
component = new MantleCarvingComponent(mantle);
|
||||
dimension = new IrisDimension();
|
||||
when(engine.getDimension()).thenReturn(dimension);
|
||||
when(engine.getWorld()).thenReturn(mock(IrisWorld.class));
|
||||
when(engine.getMetrics()).thenReturn(new EngineMetrics(16));
|
||||
IrisComplex complex = mock(IrisComplex.class);
|
||||
when(complex.allowsMantleChunkWrite(anyInt(), anyInt())).thenReturn(true);
|
||||
ProceduralStream<Double> heights = mock(ProceduralStream.class);
|
||||
when(heights.getDouble(anyDouble(), anyDouble())).thenAnswer(invocation -> {
|
||||
double x = invocation.getArgument(0);
|
||||
return x < 0D ? 90D : 70D;
|
||||
});
|
||||
when(complex.getNaturalHeightStream()).thenReturn(heights);
|
||||
ProceduralStream<IrisRegion> regions = mock(ProceduralStream.class);
|
||||
ProceduralStream<IrisBiome> biomes = mock(ProceduralStream.class);
|
||||
ProceduralStream<PlatformBlockState> fluids = mock(ProceduralStream.class);
|
||||
when(regions.get(anyDouble(), anyDouble())).thenReturn(new IrisRegion());
|
||||
when(biomes.get(anyDouble(), anyDouble())).thenReturn(new IrisBiome());
|
||||
when(complex.getRegionStream()).thenReturn(regions);
|
||||
when(complex.getNaturalTrueBiomeStream()).thenReturn(biomes);
|
||||
when(complex.getCaveBiomeStream()).thenReturn(biomes);
|
||||
when(complex.getFluidStream()).thenReturn(fluids);
|
||||
context = mock(ChunkContext.class);
|
||||
when(context.getComplex()).thenReturn(complex);
|
||||
writer = mock(MantleWriter.class);
|
||||
Mantle<Matter> storage = mock(Mantle.class);
|
||||
when(storage.getWorldHeight()).thenReturn(128);
|
||||
when(writer.getMantle()).thenReturn(storage);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nestedGenerationPreservesOuterColumnHeights() throws Exception {
|
||||
IrisCaveCarver3D carver = installProfile();
|
||||
AtomicBoolean entered = new AtomicBoolean();
|
||||
AtomicInteger calls = new AtomicInteger();
|
||||
doAnswer(invocation -> {
|
||||
int chunkX = invocation.getArgument(1);
|
||||
int[] heights = invocation.getArgument(7);
|
||||
int expectedHeight = chunkX < 0 ? 90 : 70;
|
||||
assertEquals(expectedHeight, heights[0]);
|
||||
calls.incrementAndGet();
|
||||
if (entered.compareAndSet(false, true)) {
|
||||
component.generateLayer(writer, -3, -3, context);
|
||||
}
|
||||
for (int height : heights) {
|
||||
assertEquals(expectedHeight, height);
|
||||
}
|
||||
return 0;
|
||||
}).when(carver).carve(any(), anyInt(), anyInt(), any(), anyDouble(), anyDouble(),
|
||||
any(), any(), any(), any(), any());
|
||||
|
||||
component.generateLayer(writer, 2, 2, context);
|
||||
|
||||
assertEquals(2, calls.get());
|
||||
assertReleased();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generationReleasesConfigurationReferencesWhenCarvingFails() throws Exception {
|
||||
IrisCaveCarver3D carver = installProfile();
|
||||
doAnswer(invocation -> {
|
||||
throw new IllegalStateException("Carving failed");
|
||||
}).when(carver).carve(any(), anyInt(), anyInt(), any(), anyDouble(), anyDouble(),
|
||||
any(), any(), any(), any(), any());
|
||||
assertThrows(IllegalStateException.class, () -> component.generateLayer(writer, 2, 2, context));
|
||||
assertReleased();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void changedProfilesReuseNumericBuffersWithoutKeepingProfileKeys() throws Exception {
|
||||
Object firstBuffer = null;
|
||||
for (int index = 0; index < 4; index++) {
|
||||
installProfile();
|
||||
component.generateLayer(writer, 2, 2, context);
|
||||
Object scratch = assertReleased();
|
||||
List<?> buffers = (List<?>) field(scratch, "weightBuffers");
|
||||
assertEquals(1, buffers.size());
|
||||
if (firstBuffer == null) {
|
||||
firstBuffer = buffers.get(0);
|
||||
} else {
|
||||
assertSame(firstBuffer, buffers.get(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IrisCaveCarver3D installProfile() throws Exception {
|
||||
IrisCaveProfile profile = new IrisCaveProfile().setEnabled(true);
|
||||
dimension.setCaveProfile(profile);
|
||||
IrisCaveCarver3D carver = mock(IrisCaveCarver3D.class);
|
||||
Map<IrisCaveProfile, IrisCaveCarver3D> carvers = new IdentityHashMap<>();
|
||||
carvers.put(profile, carver);
|
||||
Field cache = MantleCarvingComponent.class.getDeclaredField("profileCarvers");
|
||||
cache.setAccessible(true);
|
||||
cache.set(component, carvers);
|
||||
return carver;
|
||||
}
|
||||
|
||||
private Object assertReleased() throws Exception {
|
||||
Field scratchField = MantleCarvingComponent.class.getDeclaredField("BLEND_SCRATCH");
|
||||
scratchField.setAccessible(true);
|
||||
ThreadLocal<?> scratchCache = (ThreadLocal<?>) scratchField.get(null);
|
||||
Object scratch = scratchCache.get();
|
||||
for (String name : List.of("profileField", "kernelProfiles", "fieldRegions", "fieldSurfaceBiomes", "fieldCaveBiomes")) {
|
||||
for (Object value : (Object[]) field(scratch, name)) {
|
||||
assertNull(value);
|
||||
}
|
||||
}
|
||||
assertEquals(0, ((Map<?, ?>) field(scratch, "columnProfileWeights")).size());
|
||||
assertEquals(0, ((List<?>) field(scratch, "profileOrder")).size());
|
||||
assertFalse((boolean) field(scratch, "inUse"));
|
||||
return scratch;
|
||||
}
|
||||
|
||||
private Object field(Object object, String name) throws Exception {
|
||||
Field field = object.getClass().getDeclaredField(name);
|
||||
field.setAccessible(true);
|
||||
return field.get(object);
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.core.loader.IrisData;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class IrisBiomeCeilingLayerGuardTest {
|
||||
private static IrisBiome biome(int layers, int ceilingLayers) {
|
||||
IrisBiome biome = new IrisBiome();
|
||||
KList<IrisBiomePaletteLayer> surface = new KList<>();
|
||||
for (int i = 0; i < layers; i++) {
|
||||
surface.add(new IrisBiomePaletteLayer().zero());
|
||||
}
|
||||
KList<IrisBiomePaletteLayer> ceiling = new KList<>();
|
||||
for (int i = 0; i < ceilingLayers; i++) {
|
||||
IrisBiomePaletteLayer layer = new IrisBiomePaletteLayer().zero();
|
||||
layer.setMinHeight(0);
|
||||
layer.setMaxHeight(0);
|
||||
ceiling.add(layer);
|
||||
}
|
||||
biome.setLayers(surface);
|
||||
biome.setCaveCeilingLayers(ceiling);
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void moreCeilingLayersThanLayersMustNotThrow() {
|
||||
IrisBiome biome = biome(1, 3);
|
||||
|
||||
KList<PlatformBlockState> result = biome.generateCeilingLayers(
|
||||
new IrisDimension(), 0, 0, new RNG(1), 8, 64, mock(IrisData.class), null);
|
||||
|
||||
assertTrue("extra ceiling layers are skipped, not crashed on", result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inRangeCeilingLayersKeepWorking() {
|
||||
IrisBiome biome = biome(3, 2);
|
||||
|
||||
KList<PlatformBlockState> result = biome.generateCeilingLayers(
|
||||
new IrisDimension(), 0, 0, new RNG(1), 8, 64, mock(IrisData.class), null);
|
||||
|
||||
assertTrue("zeroed palettes with zero heights produce no blocks", result.isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void omittedCeilingLayersLeaveCavesUnchanged() {
|
||||
assertTrue(new IrisBiome().getCaveCeilingLayers().isEmpty());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotSame;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class IrisBiomeCeilingLayerTest {
|
||||
@Test
|
||||
public void emitsEveryCeilingLayerWithoutSurfaceLayers() {
|
||||
PlatformBlockState first = mock(PlatformBlockState.class);
|
||||
PlatformBlockState second = mock(PlatformBlockState.class);
|
||||
PlatformBlockState third = mock(PlatformBlockState.class);
|
||||
IrisBiome biome = new IrisBiome().setLayers(new KList<>()).setCaveCeilingLayers(
|
||||
new KList<>(layer(first, 2), layer(second, 1), layer(third, 2)));
|
||||
|
||||
KList<PlatformBlockState> result = biome.generateCeilingLayers(
|
||||
new IrisDimension(), 13, -27, new RNG(1), 8, 64, null, null);
|
||||
|
||||
assertEquals(List.of(first, first, second, third, third), result);
|
||||
assertNull(biome.getLayerHeightGenerators().getIfPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void ceilingThicknessDoesNotDependOnSurfaceDefinitionOrWarmOrder() {
|
||||
IrisBiome first = variableBiome(1, 1);
|
||||
IrisBiome second = variableBiome(7, 31);
|
||||
RNG rng = new RNG(37);
|
||||
second.getLayerHeightGenerators(rng, null);
|
||||
for (int x = -200; x <= 200; x += 7) {
|
||||
KList<PlatformBlockState> firstCeiling = first.generateCeilingLayers(
|
||||
new IrisDimension(), x, -x, rng, 100, 120, null, null);
|
||||
KList<PlatformBlockState> secondCeiling = second.generateCeilingLayers(
|
||||
new IrisDimension(), x, -x, rng, 100, 120, null, null);
|
||||
assertEquals(firstCeiling.size(), secondCeiling.size());
|
||||
}
|
||||
first.getLayerHeightGenerators(rng, null);
|
||||
assertNotSame(first.getLayerHeightGenerators().getIfPresent().get(0),
|
||||
first.getLayerCeilingHeightGenerators().getIfPresent().get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void capsCeilingLayersAtAvailableDepth() {
|
||||
PlatformBlockState first = mock(PlatformBlockState.class);
|
||||
PlatformBlockState second = mock(PlatformBlockState.class);
|
||||
IrisBiome biome = new IrisBiome().setCaveCeilingLayers(new KList<>(layer(first, 2), layer(second, 3)));
|
||||
assertEquals(List.of(first, first, second), biome.generateCeilingLayers(
|
||||
new IrisDimension(), 0, 0, new RNG(1), 3, 64, null, null));
|
||||
assertTrue(biome.generateCeilingLayers(
|
||||
new IrisDimension(), 0, 0, new RNG(1), 0, 64, null, null).isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void omittedCeilingLayersLeaveCavesUnchanged() {
|
||||
assertTrue(new IrisBiome().getCaveCeilingLayers().isEmpty());
|
||||
}
|
||||
|
||||
static IrisBiomePaletteLayer layer(PlatformBlockState block, int thickness) {
|
||||
IrisBiomePaletteLayer layer = new IrisBiomePaletteLayer().setMinHeight(thickness).setMaxHeight(thickness);
|
||||
layer.getBlockData().aquire(() -> new KList<>(block));
|
||||
return layer;
|
||||
}
|
||||
|
||||
private static IrisBiome variableBiome(int surfaceMinimum, int surfaceMaximum) {
|
||||
PlatformBlockState block = mock(PlatformBlockState.class);
|
||||
return new IrisBiome()
|
||||
.setLayers(new KList<>(layer(block, surfaceMinimum).setMaxHeight(surfaceMaximum)))
|
||||
.setCaveCeilingLayers(new KList<>(layer(block, 1).setMaxHeight(9)));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package art.arcane.iris.engine.object;
|
||||
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.volmlib.util.collection.KList;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class IrisBiomeLockedLayerTest {
|
||||
@Test
|
||||
public void repeatsLockedLayersAcrossTheReferenceHeight() {
|
||||
PlatformBlockState first = mock(PlatformBlockState.class);
|
||||
PlatformBlockState second = mock(PlatformBlockState.class);
|
||||
PlatformBlockState third = mock(PlatformBlockState.class);
|
||||
IrisBiome biome = new IrisBiome().setLockLayers(true).setLockLayersMax(8).setLayers(new KList<>(
|
||||
IrisBiomeCeilingLayerTest.layer(first, 1),
|
||||
IrisBiomeCeilingLayerTest.layer(second, 1),
|
||||
IrisBiomeCeilingLayerTest.layer(third, 1)));
|
||||
List<PlatformBlockState> cycle = List.of(first, second, third);
|
||||
int[] heights = {1, 509, 512, 513, 1000, Integer.MAX_VALUE};
|
||||
int[][] expectedCycles = {{1, 0, 2}, {0, 2, 1}, {0, 2, 1}, {2, 1, 0}, {1, 0, 2}, {1, 0, 2}};
|
||||
for (int index = 0; index < heights.length; index++) {
|
||||
KList<PlatformBlockState> blocks = biome.generateLockedLayers(
|
||||
13, -27, new RNG(37), 8, heights[index], null, null);
|
||||
assertEquals(8, blocks.size());
|
||||
for (int depth = 0; depth < blocks.size(); depth++) {
|
||||
assertEquals(cycle.get(expectedCycles[index][depth % 3]), blocks.get(depth));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user