Column biome fallback

- Column biome hunk takes its fallback biome from the caller
- The fallback resolves on first unset read
- Bukkit chunk generator supplies plains
- Core keeps no new Bukkit coupling
This commit is contained in:
Brian Neumann-Fopiano committed 2026-09-29 01:12:16 -04:00
1 parent 08ffb96680
commit b7626ab23f
3 files changed
+16 -11

No files matched your search

@@ -18,26 +18,29 @@
package art.arcane.iris.generation.chunk; package art.arcane.iris.generation.chunk;
import art.arcane.iris.platform.bukkit.BukkitBiome;
import art.arcane.volmlib.nativelib.terrain.NativeBiome; import art.arcane.volmlib.nativelib.terrain.NativeBiome;
import art.arcane.volmlib.util.hunk.HunkMutationSupport; import art.arcane.volmlib.util.hunk.HunkMutationSupport;
import art.arcane.volmlib.util.hunk.storage.StorageHunk; import art.arcane.volmlib.util.hunk.storage.StorageHunk;
import org.bukkit.block.Biome;
import java.util.function.Supplier;
/** /**
* Biome output for one Bukkit chunk, read back only by the generation stages. The biome actuator writes whole * Biome output for one Bukkit chunk, read back only by the generation stages. The biome actuator writes whole
* columns, so storage stays at one entry per column until a partial column write arrives; that write switches * columns, so storage stays at one entry per column until a partial column write arrives; that write switches
* the hunk to full resolution. Reads, clamping and the plains fallback match {@link LinkedTerrainChunk}. * the hunk to full resolution. Reads and clamping match {@link LinkedTerrainChunk}; unset cells read the
* caller's fallback biome, resolved on first use.
*/ */
public final class ColumnBiomeHunk extends StorageHunk<NativeBiome> { public final class ColumnBiomeHunk extends StorageHunk<NativeBiome> {
private static final int CHUNK_SIZE = 16; private static final int CHUNK_SIZE = 16;
private final NativeBiome[] columns = new NativeBiome[CHUNK_SIZE * CHUNK_SIZE]; private final NativeBiome[] columns = new NativeBiome[CHUNK_SIZE * CHUNK_SIZE];
private NativeBiome[] cells; private NativeBiome[] cells;
private final Supplier<NativeBiome> fallback;
private volatile NativeBiome defaultBiome; private volatile NativeBiome defaultBiome;
public ColumnBiomeHunk(int height) { public ColumnBiomeHunk(int height, Supplier<NativeBiome> fallback) {
super(CHUNK_SIZE, height, CHUNK_SIZE); super(CHUNK_SIZE, height, CHUNK_SIZE);
this.fallback = fallback;
} }
@Override @Override
@@ -63,12 +66,12 @@ public final class ColumnBiomeHunk extends StorageHunk<NativeBiome> {
if (biome != null) { if (biome != null) {
return biome; return biome;
} }
NativeBiome fallback = defaultBiome; NativeBiome resolved = defaultBiome;
if (fallback == null) { if (resolved == null) {
fallback = BukkitBiome.of(Biome.PLAINS); resolved = fallback.get();
defaultBiome = fallback; defaultBiome = resolved;
} }
return fallback; return resolved;
} }
private void fillColumn(int x, int z, NativeBiome biome) { private void fillColumn(int x, int z, NativeBiome biome) {
@@ -74,6 +74,7 @@ import art.arcane.volmlib.util.collection.KList;
import art.arcane.volmlib.util.math.M; import art.arcane.volmlib.util.math.M;
import art.arcane.volmlib.util.hunk.Hunk; import art.arcane.volmlib.util.hunk.Hunk;
import art.arcane.iris.generation.chunk.ColumnBiomeHunk; import art.arcane.iris.generation.chunk.ColumnBiomeHunk;
import art.arcane.iris.platform.bukkit.BukkitBiome;
import art.arcane.iris.generation.chunk.ChunkDataHunkHolder; import art.arcane.iris.generation.chunk.ChunkDataHunkHolder;
import art.arcane.iris.generation.context.ChunkContext; import art.arcane.iris.generation.context.ChunkContext;
import art.arcane.iris.generation.context.IrisContext; import art.arcane.iris.generation.context.IrisContext;
@@ -90,6 +91,7 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldInitEvent;
import org.bukkit.block.Biome;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
import org.bukkit.generator.BlockPopulator; import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
@@ -1312,7 +1314,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
selected.generateChunk(engine, TerrainChunk.create(d), x, z); selected.generateChunk(engine, TerrainChunk.create(d), x, z);
} else { } else {
ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(d); ChunkDataHunkHolder blocks = new ChunkDataHunkHolder(d);
Hunk<NativeBiome> biomes = new ColumnBiomeHunk(d.getMaxHeight() - d.getMinHeight()); Hunk<NativeBiome> biomes = new ColumnBiomeHunk(d.getMaxHeight() - d.getMinHeight(), () -> BukkitBiome.of(Biome.PLAINS));
try (GenerationHistoryRuntimeRouter.CoordinateScope historyScope = try (GenerationHistoryRuntimeRouter.CoordinateScope historyScope =
openGenerationHistoryCoordinateScope(engine, x << 4, z << 4); openGenerationHistoryCoordinateScope(engine, x << 4, z << 4);
GenerationSessionLease lease = engine.acquireGenerationLease("bukkit_terrain_stage"); GenerationSessionLease lease = engine.acquireGenerationLease("bukkit_terrain_stage");
@@ -121,7 +121,7 @@ public class LinkedTerrainChunkTest {
for (int trial = 0; trial < 12; trial++) { for (int trial = 0; trial < 12; trial++) {
Random random = new Random(9127L + trial); Random random = new Random(9127L + trial);
TerrainChunkBiomeHunkView expected = new TerrainChunkBiomeHunkView(chunk()); TerrainChunkBiomeHunkView expected = new TerrainChunkBiomeHunkView(chunk());
ColumnBiomeHunk actual = new ColumnBiomeHunk(16); ColumnBiomeHunk actual = new ColumnBiomeHunk(16, () -> plains);
int operations = 1 + random.nextInt(80); int operations = 1 + random.nextInt(80);
for (int operation = 0; operation < operations; operation++) { for (int operation = 0; operation < operations; operation++) {
NativeBiome biome = palette[random.nextInt(palette.length)]; NativeBiome biome = palette[random.nextInt(palette.length)];