mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-26 05:50:39 +00:00
Skip impossible deposit variants
- Scan pack once per data load for declared depositVariants - Placed ores skip the per-block cave biome lookup when none exist
This commit is contained in:
1 parent
2ce36eb6f1
commit
b47c7ae6aa
2 files changed
+96
-4
No files matched your search
@@ -45,15 +45,20 @@ import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
|||||||
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
|
import art.arcane.volmlib.nativelib.terrain.NativeBlockState;
|
||||||
import art.arcane.iris.generation.block.B;
|
import art.arcane.iris.generation.block.B;
|
||||||
import art.arcane.iris.generation.block.VectorMap;
|
import art.arcane.iris.generation.block.VectorMap;
|
||||||
|
import art.arcane.iris.pack.loading.IrisData;
|
||||||
|
import art.arcane.iris.pack.loading.IrisRegistrant;
|
||||||
|
import art.arcane.iris.pack.loading.ResourceLoader;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState> {
|
public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState> {
|
||||||
private static final int CLUMPS_PER_BATCH = 8;
|
private static final int CLUMPS_PER_BATCH = 8;
|
||||||
private static final int PREPARATION_BATCH_COUNT = 4;
|
private static final int PREPARATION_BATCH_COUNT = 4;
|
||||||
|
|
||||||
private final RNG rng;
|
private final RNG rng;
|
||||||
|
private volatile DepositVariantScan variantScan;
|
||||||
|
|
||||||
public IrisDepositModifier(Engine engine) {
|
public IrisDepositModifier(Engine engine) {
|
||||||
super(engine, "Deposit");
|
super(engine, "Deposit");
|
||||||
@@ -271,6 +276,7 @@ public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState
|
|||||||
boolean oreDeposit = deposit.ore();
|
boolean oreDeposit = deposit.ore();
|
||||||
IrisDimensionCarvingResolver.State carvingState = new IrisDimensionCarvingResolver.State();
|
IrisDimensionCarvingResolver.State carvingState = new IrisDimensionCarvingResolver.State();
|
||||||
IrisDimension dimension = getDimension();
|
IrisDimension dimension = getDimension();
|
||||||
|
boolean variants = depositVariantsPossible();
|
||||||
for (PreparedClump prepared : deposit.clumps()) {
|
for (PreparedClump prepared : deposit.clumps()) {
|
||||||
IrisObject clump = prepared.object();
|
IrisObject clump = prepared.object();
|
||||||
int x = prepared.x();
|
int x = prepared.x();
|
||||||
@@ -325,8 +331,8 @@ public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState
|
|||||||
|
|
||||||
if (chunk.get(nx, ny, nz, MatterCavern.class) == null) {
|
if (chunk.get(nx, ny, nz, MatterCavern.class) == null) {
|
||||||
NativeBlockState ore = cursor.value();
|
NativeBlockState ore = cursor.value();
|
||||||
NativeBlockState remapped = resolveDepositVariant(
|
NativeBlockState remapped = variants ? resolveDepositVariant(
|
||||||
cx, cz, nx, ny, nz, ore, dimension, context, carvingState);
|
cx, cz, nx, ny, nz, ore, dimension, context, carvingState) : null;
|
||||||
NativeBlockState finalBlock = remapped != null
|
NativeBlockState finalBlock = remapped != null
|
||||||
? remapped
|
? remapped
|
||||||
: B.toDeepSlateOre(current, ore);
|
: B.toDeepSlateOre(current, ore);
|
||||||
@@ -460,6 +466,51 @@ public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState
|
|||||||
return Math.max(minimum, Math.min(center, maximum));
|
return Math.max(minimum, Math.min(center, maximum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The per-block variant lookup resolves a cave biome for every placed ore, but it can only ever match when
|
||||||
|
* some biome, region or the dimension of the loaded pack declares variants. Anything the scan cannot
|
||||||
|
* enumerate (stacked dimensions, unreadable loaders) keeps the lookup.
|
||||||
|
*/
|
||||||
|
private boolean depositVariantsPossible() {
|
||||||
|
IrisData data = getData();
|
||||||
|
DepositVariantScan scan = variantScan;
|
||||||
|
if (scan == null || scan.data() != data) {
|
||||||
|
scan = new DepositVariantScan(data, scanDepositVariants(data));
|
||||||
|
variantScan = scan;
|
||||||
|
}
|
||||||
|
return scan.possible();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean scanDepositVariants(IrisData data) {
|
||||||
|
IrisDimension dimension = getDimension();
|
||||||
|
if (data == null || dimension == null || getEngine().getDimensionStackContext() != null
|
||||||
|
|| dimension.getDepositVariants() == null || !dimension.getDepositVariants().isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Boolean regions = declaresVariants(data.getRegionLoader(), IrisRegion::getDepositVariants);
|
||||||
|
Boolean biomes = declaresVariants(data.getBiomeLoader(), IrisBiome::getDepositVariants);
|
||||||
|
return regions == null || regions || biomes == null || biomes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T extends IrisRegistrant> Boolean declaresVariants(ResourceLoader<T> loader,
|
||||||
|
Function<T, ? extends List<IrisDepositVariant>> variants) {
|
||||||
|
String[] keys = loader == null ? null : loader.getPossibleKeys();
|
||||||
|
if (keys == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (String key : keys) {
|
||||||
|
T loaded = loader.load(key);
|
||||||
|
if (loaded == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
List<IrisDepositVariant> declared = variants.apply(loaded);
|
||||||
|
if (declared == null || !declared.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private NativeBlockState resolveDepositVariant(int cx, int cz, int nx, int localY, int nz, NativeBlockState ore, IrisDimension dimension, ChunkContext context, IrisDimensionCarvingResolver.State carvingState) {
|
private NativeBlockState resolveDepositVariant(int cx, int cz, int nx, int localY, int nz, NativeBlockState ore, IrisDimension dimension, ChunkContext context, IrisDimensionCarvingResolver.State carvingState) {
|
||||||
int worldX = (cx << 4) + nx;
|
int worldX = (cx << 4) + nx;
|
||||||
int worldZ = (cz << 4) + nz;
|
int worldZ = (cz << 4) + nz;
|
||||||
@@ -548,6 +599,9 @@ public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState
|
|||||||
private record DepositPlan(IrisDepositGenerator generator, long seed, boolean ore, int attempts) {
|
private record DepositPlan(IrisDepositGenerator generator, long seed, boolean ore, int attempts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private record DepositVariantScan(IrisData data, boolean possible) {
|
||||||
|
}
|
||||||
|
|
||||||
private record PreparedDeposit(IrisDepositGenerator generator, boolean ore, List<PreparedClump> clumps) {
|
private record PreparedDeposit(IrisDepositGenerator generator, boolean ore, List<PreparedClump> clumps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-2
@@ -30,12 +30,15 @@ import org.junit.Before;
|
|||||||
import org.junit.ClassRule;
|
import org.junit.ClassRule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.mockito.MockedStatic;
|
import org.mockito.MockedStatic;
|
||||||
|
import art.arcane.iris.pack.loading.ResourceLoader;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
@@ -84,8 +87,25 @@ 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private long[] generateConfigured(long seed, boolean multicore) {
|
private long[] generateConfigured(long seed, boolean multicore) {
|
||||||
|
return generateConfigured(seed, multicore, true, false, new AtomicInteger());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private long[] generateConfigured(long seed, boolean multicore, boolean caveVariant, boolean enumerablePack,
|
||||||
|
AtomicInteger caveBiomeLookups) {
|
||||||
Engine engine = mock(Engine.class, RETURNS_DEEP_STUBS);
|
Engine engine = mock(Engine.class, RETURNS_DEEP_STUBS);
|
||||||
ChunkContext context = mock(ChunkContext.class, RETURNS_DEEP_STUBS);
|
ChunkContext context = mock(ChunkContext.class, RETURNS_DEEP_STUBS);
|
||||||
IrisDimension dimension = new IrisDimension();
|
IrisDimension dimension = new IrisDimension();
|
||||||
@@ -99,7 +119,9 @@ public class IrisDepositModifierParityTest {
|
|||||||
denied.setLoadKey("denied");
|
denied.setLoadKey("denied");
|
||||||
IrisDepositVariant variant = new IrisDepositVariant().setMinHeight(-64).setMaxHeight(64);
|
IrisDepositVariant variant = new IrisDepositVariant().setMinHeight(-64).setMaxHeight(64);
|
||||||
variant.getRemap().put("minecraft:gold_ore", "minecraft:redstone_ore");
|
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,
|
dimension.getDeposits().add(generator("granite", IrisDepositShape.IRIS, 25, 70,
|
||||||
IrisDepositHeightDistribution.CLIPPED_UNIFORM, "stone", "deepslate"));
|
IrisDepositHeightDistribution.CLIPPED_UNIFORM, "stone", "deepslate"));
|
||||||
region.getDeposits().add(generator("iron_ore", IrisDepositShape.VANILLA_ELLIPSOID, 20, 110,
|
region.getDeposits().add(generator("iron_ore", IrisDepositShape.VANILLA_ELLIPSOID, 20, 110,
|
||||||
@@ -118,7 +140,23 @@ public class IrisDepositModifierParityTest {
|
|||||||
when(engine.getMinHeight()).thenReturn(-64);
|
when(engine.getMinHeight()).thenReturn(-64);
|
||||||
when(engine.getSeedManager().getDeposit()).thenReturn(seed);
|
when(engine.getSeedManager().getDeposit()).thenReturn(seed);
|
||||||
when(engine.getDimension()).thenReturn(dimension);
|
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 -> {
|
when(engine.getCaveBiome(anyInt(), anyInt(), anyInt(), any())).thenAnswer(invocation -> {
|
||||||
|
caveBiomeLookups.incrementAndGet();
|
||||||
int x = invocation.getArgument(0);
|
int x = invocation.getArgument(0);
|
||||||
int y = invocation.getArgument(1);
|
int y = invocation.getArgument(1);
|
||||||
int z = invocation.getArgument(2);
|
int z = invocation.getArgument(2);
|
||||||
|
|||||||
Reference in new issue
Block a user