drastically optimize ChunkLocalCachingBiomeProvider

This commit is contained in:
dfsek 2022-06-13 23:13:41 -07:00
parent d80d653d3a
commit 9f6dcfd71b

View File

@ -1,6 +1,7 @@
package com.dfsek.terra.api.world.biome.generation; package com.dfsek.terra.api.world.biome.generation;
import com.dfsek.terra.api.util.Column; import com.dfsek.terra.api.util.Column;
import com.dfsek.terra.api.util.generic.Construct;
import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.api.world.info.WorldProperties;
@ -18,15 +19,16 @@ import java.util.Optional;
* for the chunk, and a slower dynamically-sized cache for out-of-chunk biomes. * for the chunk, and a slower dynamically-sized cache for out-of-chunk biomes.
*/ */
public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider { public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider {
private final Biome[][][] cache; private final BiomeChunk[] chunks = new BiomeChunk[9];
private final Column<Biome>[][] columnCache = new Column[16][16]; private final Column<Biome>[] columnCache = new Column[256]; // x + z * 16
private final int chunkX; private final int chunkX;
private final int chunkZ; private final int chunkZ;
private final int height;
protected ChunkLocalCachingBiomeProvider(BiomeProvider delegate, WorldProperties worldProperties, int chunkX, int chunkZ) { protected ChunkLocalCachingBiomeProvider(BiomeProvider delegate, WorldProperties worldProperties, int chunkX, int chunkZ) {
super(delegate, worldProperties.getMinHeight(), worldProperties.getMaxHeight()); super(delegate, worldProperties.getMinHeight(), worldProperties.getMaxHeight());
this.cache = new Biome[16][maxY - minY][16]; this.height = maxY - minY;
this.chunkX = chunkX; this.chunkX = chunkX;
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
} }
@ -38,11 +40,23 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider {
@Override @Override
public Biome getBiome(int x, int y, int z, long seed) { public Biome getBiome(int x, int y, int z, long seed) {
if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { int localChunkX = FastMath.floorDiv(x, 16) - this.chunkX + 1;
Biome biome = cache[x & 15][y - minY][z & 15]; int localChunkZ = FastMath.floorDiv(z, 16) - this.chunkZ + 1;
if(localChunkX >= 0 && localChunkZ >= 0 && localChunkX <= 2 && localChunkZ <= 2) {
int chunkIndex = localChunkX + localChunkZ * 3;
BiomeChunk chunk = chunks[chunkIndex];
if(chunk == null) {
chunk = new BiomeChunk(height);
chunks[chunkIndex] = chunk;
}
int biomeIndex = (x & 15) + 16 * (z & 15) + 256 * (y - minY);
Biome biome = chunk.cache[biomeIndex];
if(biome == null) { if(biome == null) {
biome = delegate.getBiome(x, y, z, seed); biome = delegate.getBiome(x, y, z, seed);
cache[x & 15][y - minY][z & 15] = biome; chunk.cache[biomeIndex] = biome;
} }
return biome; return biome;
} }
@ -58,10 +72,11 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider {
@Override @Override
public Column<Biome> getColumn(int x, int z, long seed, int min, int max) { public Column<Biome> getColumn(int x, int z, long seed, int min, int max) {
if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) { if(FastMath.floorDiv(x, 16) == chunkX && FastMath.floorDiv(z, 16) == chunkZ) {
Column<Biome> column = columnCache[x & 15][z & 15]; int index = (x & 15) + (16 * (z & 15));
Column<Biome> column = columnCache[index];
if(column == null) { if(column == null) {
column = delegate.getColumn(x, z, seed, min, max); column = delegate.getColumn(x, z, seed, min, max);
columnCache[x & 15][z & 15] = column; columnCache[index] = column;
} }
return column; return column;
} }
@ -72,4 +87,12 @@ public class ChunkLocalCachingBiomeProvider extends CachingBiomeProvider {
public Iterable<Biome> getBiomes() { public Iterable<Biome> getBiomes() {
return delegate.getBiomes(); return delegate.getBiomes();
} }
private static class BiomeChunk {
final Biome[] cache; // x + z * 16 + y * 256
private BiomeChunk(int height) {
this.cache = new Biome[16 * 16 * height];
}
}
} }