mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-10-27 06:20:02 +00:00
Stabilized deposit overlap order
- Clumps prepare in parallel and place in dimension region biome order - Placement evaluates host rules against preceding deposits - Each clump uses independent deterministic random state - Configured attempt counts are sampled once per chunk - Block traversal reuses cursor coordinates - Tests cover reversed worker completion and generation context cleanup
This commit is contained in:
1 parent
17c927acdd
commit
47f77df0e8
3 files changed
+321
-53
No files matched your search
@@ -40,9 +40,14 @@ import art.arcane.volmlib.util.mantle.runtime.MantleChunk;
|
||||
import art.arcane.volmlib.util.math.RNG;
|
||||
import art.arcane.volmlib.util.matter.MatterCavern;
|
||||
import art.arcane.iris.util.common.parallel.BurstExecutor;
|
||||
import art.arcane.iris.util.common.math.IrisBlockVector;
|
||||
import art.arcane.volmlib.util.scheduling.PrecisionStopwatch;
|
||||
import art.arcane.iris.spi.PlatformBlockState;
|
||||
import art.arcane.iris.util.common.data.B;
|
||||
import art.arcane.iris.util.common.data.VectorMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockState> {
|
||||
private final RNG rng;
|
||||
@@ -62,37 +67,42 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
public void generateDeposits(Hunk<PlatformBlockState> terrain, int x, int z, boolean multicore, ChunkContext context) {
|
||||
IrisRegion region = context.getRegion().get(7, 7);
|
||||
IrisBiome biome = context.getBiome().get(7, 7);
|
||||
BurstExecutor burst = burst().burst(multicore);
|
||||
List<IrisDepositGenerator> generators = new ArrayList<>(
|
||||
getDimension().getDeposits().size() + region.getDeposits().size() + biome.getDeposits().size());
|
||||
generators.addAll(getDimension().getDeposits());
|
||||
generators.addAll(region.getDeposits());
|
||||
generators.addAll(biome.getDeposits());
|
||||
if (generators.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BurstExecutor burst = burst().burst(multicore);
|
||||
long seed = x * 341873128712L + z * 132897987541L;
|
||||
long mask = 0;
|
||||
PreparedDeposit[] prepared = new PreparedDeposit[generators.size()];
|
||||
MantleChunk chunk = getEngine().getMantle().getMantle().getChunk(x, z).use();
|
||||
try {
|
||||
for (IrisDepositGenerator k : getDimension().getDeposits()) {
|
||||
long finalSeed = seed * ++mask;
|
||||
burst.queue(scopedDepositTask(
|
||||
() -> generate(k, chunk, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context), context));
|
||||
try {
|
||||
for (int i = 0; i < generators.size(); i++) {
|
||||
int index = i;
|
||||
IrisDepositGenerator generator = generators.get(i);
|
||||
RNG generatorRng = rng.nextParallelRNG(seed * (i + 1L));
|
||||
burst.queue(scopedDepositTask(
|
||||
() -> prepared[index] = prepare(generator, generatorRng, x, z, null, context), context));
|
||||
}
|
||||
} finally {
|
||||
// complete() must run before release() even when queueing throws — already
|
||||
// submitted burst tasks must never write into a released chunk.
|
||||
burst.complete();
|
||||
}
|
||||
|
||||
for (IrisDepositGenerator k : region.getDeposits()) {
|
||||
long finalSeed = seed * ++mask;
|
||||
burst.queue(scopedDepositTask(
|
||||
() -> generate(k, chunk, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context), context));
|
||||
}
|
||||
|
||||
for (IrisDepositGenerator k : biome.getDeposits()) {
|
||||
long finalSeed = seed * ++mask;
|
||||
burst.queue(scopedDepositTask(
|
||||
() -> generate(k, chunk, terrain, rng.nextParallelRNG(finalSeed), x, z, false, context), context));
|
||||
try (IrisContext.Scope chunkScope = IrisContext.open(getEngine(), context.getGenerationSessionId(), context)) {
|
||||
for (PreparedDeposit deposit : prepared) {
|
||||
if (deposit != null) {
|
||||
place(deposit, chunk, terrain, x, z, null, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
// complete() must run before release() even when queueing throws — already
|
||||
// submitted burst tasks must never write into a released chunk.
|
||||
try {
|
||||
burst.complete();
|
||||
} finally {
|
||||
chunk.release();
|
||||
}
|
||||
chunk.release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,17 +125,27 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
}
|
||||
|
||||
public void generate(IrisDepositGenerator k, MantleChunk chunk, Hunk<PlatformBlockState> data, RNG rng, int cx, int cz, boolean safe, HeightMap he, ChunkContext context) {
|
||||
IrisDimensionCarvingResolver.State carvingState = new IrisDimensionCarvingResolver.State();
|
||||
if (k.getSpawnChance() < rng.d())
|
||||
return;
|
||||
place(prepare(k, rng, cx, cz, he, context), chunk, data, cx, cz, he, context);
|
||||
}
|
||||
|
||||
private PreparedDeposit prepare(IrisDepositGenerator k, RNG rng, int cx, int cz, HeightMap he, ChunkContext context) {
|
||||
if (k.getSpawnChance() < rng.d()) {
|
||||
return new PreparedDeposit(k, false, List.of());
|
||||
}
|
||||
|
||||
boolean oreDeposit = k.isOre(getData());
|
||||
boolean needsCaveBiome = oreDeposit || k.usesCaveBiomeFilter();
|
||||
IrisDimensionCarvingResolver.State carvingState = needsCaveBiome ? new IrisDimensionCarvingResolver.State() : null;
|
||||
|
||||
for (int l = 0; l < rng.i(k.getMinPerChunk(), k.getMaxPerChunk() + 1); l++) {
|
||||
if (k.getPerClumpSpawnChance() < rng.d())
|
||||
int attempts = rng.i(k.getMinPerChunk(), k.getMaxPerChunk() + 1);
|
||||
List<PreparedClump> clumps = new ArrayList<>(Math.max(0, attempts));
|
||||
for (int l = 0; l < attempts; l++) {
|
||||
RNG clumpRng = rng.nextParallelRNG(l + 1L);
|
||||
if (k.getPerClumpSpawnChance() < clumpRng.d()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IrisObject clump = k.getClump(getEngine(), rng, getData());
|
||||
IrisObject clump = k.getClump(getEngine(), clumpRng, getData());
|
||||
|
||||
int dim = clump.getW();
|
||||
int min = dim / 2;
|
||||
@@ -136,8 +156,8 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
max = 9;
|
||||
}
|
||||
|
||||
int x = rng.i(min, max + 1);
|
||||
int z = rng.i(min, max + 1);
|
||||
int x = clumpRng.i(min, max + 1);
|
||||
int z = clumpRng.i(min, max + 1);
|
||||
int terrainSurface = getDepositTerrainSurface(cx, cz, x, z, he, context);
|
||||
int height = k.getPlacementScope() == IrisDepositPlacementScope.TERRAIN
|
||||
? depositSurfaceLimit(terrainSurface, k.getSurfaceClearance())
|
||||
@@ -148,19 +168,20 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
}
|
||||
|
||||
int y = sampleHeight(
|
||||
k.getHeightDistribution(), rng, k.getMinHeight(), k.getMaxHeight(),
|
||||
k.getHeightDistribution(), clumpRng, k.getMinHeight(), k.getMaxHeight(),
|
||||
Math.min(height, getEngine().getHeight() - 1));
|
||||
if (y == Integer.MIN_VALUE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean clippedHeight = k.getHeightDistribution() == IrisDepositHeightDistribution.CLIPPED_UNIFORM;
|
||||
if (clippedHeight && y > height - 2)
|
||||
if (clippedHeight && y > height - 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int biomeY = Math.max(0, Math.min(getEngine().getHeight() - 1, y));
|
||||
IrisBiome surfaceBiome = context.getBiome().get(x, z);
|
||||
IrisBiome depositBiome = oreDeposit || k.usesCaveBiomeFilter()
|
||||
IrisBiome depositBiome = needsCaveBiome
|
||||
? getEngine().getCaveBiome(
|
||||
(cx << 4) + x, biomeY, (cz << 4) + z, carvingState)
|
||||
: null;
|
||||
@@ -172,13 +193,13 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
if (depositBiome != null) {
|
||||
double frequencyMultiplier = depositBiome.getOreDepositFrequencyMultiplier();
|
||||
if (frequencyMultiplier < 1D
|
||||
&& !passesOreFrequency(frequencyMultiplier, rng.d())) {
|
||||
&& !passesOreFrequency(frequencyMultiplier, clumpRng.d())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
double sizeMultiplier = depositBiome.getOreDepositSizeMultiplier();
|
||||
if (sizeMultiplier != 1D) {
|
||||
IrisObject scaledClump = k.getClump(getEngine(), rng, getData(), sizeMultiplier);
|
||||
IrisObject scaledClump = k.getClump(getEngine(), clumpRng, getData(), sizeMultiplier);
|
||||
int scaledDimension = scaledClump.getW();
|
||||
x = clampDepositCenter(x, scaledDimension, 16);
|
||||
if (clippedHeight) {
|
||||
@@ -190,9 +211,30 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
}
|
||||
}
|
||||
|
||||
IrisDimension dimension = getDimension();
|
||||
clumps.add(new PreparedClump(clump, x, y, z, clumpRng));
|
||||
}
|
||||
return new PreparedDeposit(k, oreDeposit, clumps);
|
||||
}
|
||||
|
||||
for (art.arcane.iris.util.common.math.IrisBlockVector j : clump.getBlocks().keys()) {
|
||||
private void place(PreparedDeposit deposit, MantleChunk chunk, Hunk<PlatformBlockState> data,
|
||||
int cx, int cz, HeightMap he, ChunkContext context) {
|
||||
if (deposit.clumps().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
IrisDepositGenerator k = deposit.generator();
|
||||
boolean oreDeposit = deposit.ore();
|
||||
IrisDimensionCarvingResolver.State carvingState = new IrisDimensionCarvingResolver.State();
|
||||
IrisDimension dimension = getDimension();
|
||||
for (PreparedClump prepared : deposit.clumps()) {
|
||||
IrisObject clump = prepared.object();
|
||||
int x = prepared.x();
|
||||
int y = prepared.y();
|
||||
int z = prepared.z();
|
||||
RNG rng = prepared.rng();
|
||||
|
||||
VectorMap<PlatformBlockState>.Cursor cursor = clump.getBlocks().cursor();
|
||||
while (cursor.next()) {
|
||||
IrisBlockVector j = cursor.key();
|
||||
int nx = j.getBlockX() + x;
|
||||
int ny = j.getBlockY() + y;
|
||||
int nz = j.getBlockZ() + z;
|
||||
@@ -236,7 +278,7 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
}
|
||||
|
||||
if (chunk.get(nx, ny, nz, MatterCavern.class) == null) {
|
||||
PlatformBlockState ore = clump.getBlocks().get(j);
|
||||
PlatformBlockState ore = cursor.value();
|
||||
PlatformBlockState remapped = resolveDepositVariant(
|
||||
cx, cz, nx, ny, nz, ore, dimension, context, carvingState);
|
||||
PlatformBlockState finalBlock = remapped != null
|
||||
@@ -421,4 +463,10 @@ public class IrisDepositModifier extends EngineAssignedModifier<PlatformBlockSta
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private record PreparedDeposit(IrisDepositGenerator generator, boolean ore, List<PreparedClump> clumps) {
|
||||
}
|
||||
|
||||
private record PreparedClump(IrisObject object, int x, int y, int z, RNG rng) {
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user