mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2025-07-04 00:45:57 +00:00
replace dumb caches with guava caches
This commit is contained in:
parent
8fd3530653
commit
cbc2885c16
@ -32,21 +32,21 @@ import com.dfsek.terra.debug.Debug;
|
|||||||
import com.dfsek.terra.generation.math.SamplerCache;
|
import com.dfsek.terra.generation.math.SamplerCache;
|
||||||
import com.dfsek.terra.registry.LootRegistry;
|
import com.dfsek.terra.registry.LootRegistry;
|
||||||
import com.dfsek.terra.registry.ScriptRegistry;
|
import com.dfsek.terra.registry.ScriptRegistry;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
public class StructureScript {
|
public class StructureScript {
|
||||||
private final Block block;
|
private final Block block;
|
||||||
private final String id;
|
private final String id;
|
||||||
String tempID;
|
String tempID;
|
||||||
private final Map<Location, StructureBuffer> cache;
|
private final Cache<Location, StructureBuffer> cache;
|
||||||
private final TerraPlugin main;
|
private final TerraPlugin main;
|
||||||
|
|
||||||
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException {
|
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, LootRegistry lootRegistry, SamplerCache cache) throws ParseException {
|
||||||
@ -88,12 +88,7 @@ public class StructureScript {
|
|||||||
this.id = parser.getID();
|
this.id = parser.getID();
|
||||||
tempID = id;
|
tempID = id;
|
||||||
this.main = main;
|
this.main = main;
|
||||||
this.cache = Collections.synchronizedMap(new LinkedHashMap<Location, StructureBuffer>() {
|
this.cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getStructureCache()).build();
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(Map.Entry<Location, StructureBuffer> eldest) {
|
|
||||||
return this.size() > main.getTerraConfig().getStructureCache();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -122,12 +117,14 @@ public class StructureScript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
|
private StructureBuffer computeBuffer(Location location, Random random, Rotation rotation) {
|
||||||
synchronized(cache) {
|
try {
|
||||||
return cache.computeIfAbsent(location, loc -> {
|
return cache.get(location, () -> {
|
||||||
StructureBuffer buf = new StructureBuffer(loc);
|
StructureBuffer buf = new StructureBuffer(location);
|
||||||
buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0)));
|
buf.setSucceeded(applyBlock(new TerraImplementationArguments(buf, rotation, random, 0)));
|
||||||
return buf;
|
return buf;
|
||||||
});
|
});
|
||||||
|
} catch(ExecutionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package com.dfsek.terra.biome;
|
|
||||||
|
|
||||||
import com.dfsek.terra.api.math.vector.Vector2;
|
|
||||||
import com.dfsek.terra.biome.pipeline.BiomeHolder;
|
|
||||||
import com.google.common.cache.CacheBuilder;
|
|
||||||
import com.google.common.cache.CacheLoader;
|
|
||||||
import com.google.common.cache.LoadingCache;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
public class BiomeCache {
|
|
||||||
LoadingCache<Vector2, BiomeHolder> cache;
|
|
||||||
|
|
||||||
public BiomeCache() {
|
|
||||||
cache = CacheBuilder.newBuilder()
|
|
||||||
.maximumSize(1024)
|
|
||||||
.build(
|
|
||||||
new CacheLoader<Vector2, BiomeHolder>() {
|
|
||||||
@Override
|
|
||||||
public BiomeHolder load(@NotNull Vector2 key) throws Exception {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -50,11 +50,7 @@ public class StandardBiomeProvider implements BiomeProvider {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TerraBiome getBiome(int x, int z) {
|
public TerraBiome getBiome(int x, int z) {
|
||||||
try {
|
return biomeCache.getUnchecked(new Vector2(x, z));
|
||||||
return biomeCache.get(new Vector2(x, z));
|
|
||||||
} catch(ExecutionException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getResolution() {
|
public int getResolution() {
|
||||||
|
@ -10,44 +10,38 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
|
|||||||
import com.dfsek.terra.api.world.carving.Worm;
|
import com.dfsek.terra.api.world.carving.Worm;
|
||||||
import com.dfsek.terra.biome.BiomeProvider;
|
import com.dfsek.terra.biome.BiomeProvider;
|
||||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
public class CarverCache {
|
public class CarverCache {
|
||||||
|
|
||||||
private final World w;
|
private final LoadingCache<Long, List<Worm.WormPoint>> cache;
|
||||||
private final Map<Long, List<Worm.WormPoint>> carvers;
|
private final UserDefinedCarver carver;
|
||||||
private final TerraPlugin main;
|
|
||||||
|
|
||||||
public CarverCache(World w, TerraPlugin main) {
|
public CarverCache(World w, TerraPlugin main, UserDefinedCarver carver) {
|
||||||
this.w = w;
|
this.carver = carver;
|
||||||
this.main = main;
|
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getCarverCacheSize())
|
||||||
carvers = Collections.synchronizedMap(new LinkedHashMap<Long, List<Worm.WormPoint>>() {
|
.build(new CacheLoader<Long, List<Worm.WormPoint>>() {
|
||||||
@Override
|
@Override
|
||||||
protected boolean removeEldestEntry(Map.Entry eldest) {
|
public List<Worm.WormPoint> load(@NotNull Long key) {
|
||||||
return this.size() > main.getTerraConfig().getCarverCacheSize();
|
int chunkX = (int) (key >> 32);
|
||||||
}
|
int chunkZ = (int) key.longValue();
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ, UserDefinedCarver carver) {
|
|
||||||
synchronized(carvers) {
|
|
||||||
return carvers.computeIfAbsent(MathUtil.squash(chunkX, chunkZ), key -> {
|
|
||||||
BiomeProvider provider = main.getWorld(w).getBiomeProvider();
|
BiomeProvider provider = main.getWorld(w).getBiomeProvider();
|
||||||
if(carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + carver.hashCode())))) {
|
if(CarverCache.this.carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + CarverCache.this.carver.hashCode())))) {
|
||||||
long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed());
|
long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed());
|
||||||
carver.getSeedVar().setValue(seed);
|
CarverCache.this.carver.getSeedVar().setValue(seed);
|
||||||
Random r = new FastRandom(seed);
|
Random r = new FastRandom(seed);
|
||||||
Worm carving = carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16)));
|
Worm carving = CarverCache.this.carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), CarverCache.this.carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16)));
|
||||||
List<Worm.WormPoint> points = new GlueList<>();
|
List<Worm.WormPoint> points = new GlueList<>();
|
||||||
for(int i = 0; i < carving.getLength(); i++) {
|
for(int i = 0; i < carving.getLength(); i++) {
|
||||||
carving.step();
|
carving.step();
|
||||||
TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w));
|
TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w));
|
||||||
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(carver)) { // Stop if we enter a biome this carver is not present in
|
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in
|
||||||
return new GlueList<>();
|
return new GlueList<>();
|
||||||
}
|
}
|
||||||
points.add(carving.getPoint());
|
points.add(carving.getPoint());
|
||||||
@ -55,7 +49,11 @@ public class CarverCache {
|
|||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
return new GlueList<>();
|
return new GlueList<>();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ) {
|
||||||
|
return cache.getUnchecked(MathUtil.squash(chunkX, chunkZ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.dfsek.terra.api.world.carving.Worm;
|
|||||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||||
import com.dfsek.terra.config.templates.BiomeTemplate;
|
import com.dfsek.terra.config.templates.BiomeTemplate;
|
||||||
import com.dfsek.terra.config.templates.CarverTemplate;
|
import com.dfsek.terra.config.templates.CarverTemplate;
|
||||||
|
import com.dfsek.terra.debug.Debug;
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
import parsii.eval.Expression;
|
import parsii.eval.Expression;
|
||||||
import parsii.eval.Parser;
|
import parsii.eval.Parser;
|
||||||
@ -100,11 +101,12 @@ public class UserDefinedCarver extends Carver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void carve(int chunkX, int chunkZ, World w, BiConsumer<Vector3, CarvingType> consumer) {
|
public void carve(int chunkX, int chunkZ, World w, BiConsumer<Vector3, CarvingType> consumer) {
|
||||||
CarverCache cache = cacheMap.computeIfAbsent(w, world -> new CarverCache(world, main));
|
CarverCache cache = cacheMap.computeIfAbsent(w, world -> new CarverCache(world, main, this));
|
||||||
|
if(cacheMap.size() > 1) Debug.info("Map size: " + cacheMap.size());
|
||||||
int carvingRadius = getCarvingRadius();
|
int carvingRadius = getCarvingRadius();
|
||||||
for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) {
|
for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) {
|
||||||
for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) {
|
for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) {
|
||||||
cache.getPoints(x, z, this).forEach(point -> {
|
cache.getPoints(x, z).forEach(point -> {
|
||||||
Vector3 origin = point.getOrigin();
|
Vector3 origin = point.getOrigin();
|
||||||
if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk.
|
if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk.
|
||||||
return;
|
return;
|
||||||
|
@ -4,11 +4,13 @@ import com.dfsek.terra.TerraWorld;
|
|||||||
import com.dfsek.terra.api.math.MathUtil;
|
import com.dfsek.terra.api.math.MathUtil;
|
||||||
import com.dfsek.terra.api.platform.TerraPlugin;
|
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||||
import com.dfsek.terra.api.platform.world.World;
|
import com.dfsek.terra.api.platform.world.World;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.cache.LoadingCache;
|
||||||
import net.jafama.FastMath;
|
import net.jafama.FastMath;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SamplerCache {
|
public class SamplerCache {
|
||||||
@ -35,14 +37,18 @@ public class SamplerCache {
|
|||||||
private class Container {
|
private class Container {
|
||||||
private final World world;
|
private final World world;
|
||||||
private final TerraWorld terraWorld;
|
private final TerraWorld terraWorld;
|
||||||
private final Map<Long, Sampler> cache = Collections.synchronizedMap(new LinkedHashMap<Long, Sampler>() {
|
private final LoadingCache<Long, Sampler> cache;
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(Map.Entry<Long, Sampler> eldest) {
|
|
||||||
return this.size() > main.getTerraConfig().getSamplerCache();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
private Container(World world) {
|
private Container(World world) {
|
||||||
|
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getSamplerCache())
|
||||||
|
.build(new CacheLoader<Long, Sampler>() {
|
||||||
|
@Override
|
||||||
|
public Sampler load(@NotNull Long key) {
|
||||||
|
int cx = (int) (key >> 32);
|
||||||
|
int cz = (int) key.longValue();
|
||||||
|
return new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend());
|
||||||
|
}
|
||||||
|
});
|
||||||
this.world = world;
|
this.world = world;
|
||||||
terraWorld = main.getWorld(world);
|
terraWorld = main.getWorld(world);
|
||||||
}
|
}
|
||||||
@ -55,9 +61,7 @@ public class SamplerCache {
|
|||||||
|
|
||||||
public Sampler getChunk(int cx, int cz) {
|
public Sampler getChunk(int cx, int cz) {
|
||||||
long key = MathUtil.squash(cx, cz);
|
long key = MathUtil.squash(cx, cz);
|
||||||
synchronized(cache) {
|
return cache.getUnchecked(key);
|
||||||
return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,7 @@ public class BiomeTest {
|
|||||||
BiomeSource source = new RandomSource(climate, sourceSampler);
|
BiomeSource source = new RandomSource(climate, sourceSampler);
|
||||||
|
|
||||||
|
|
||||||
BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> {
|
BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> new BiomePipeline.BiomePipelineBuilder(2)
|
||||||
BiomePipeline pipeline = new BiomePipeline.BiomePipelineBuilder(2)
|
|
||||||
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(1))))
|
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(1))))
|
||||||
.addStage(new MutatorStage(new ReplaceMutator("OCEAN_TEMP", oceanBiomes, whiteNoise(243))))
|
.addStage(new MutatorStage(new ReplaceMutator("OCEAN_TEMP", oceanBiomes, whiteNoise(243))))
|
||||||
.addStage(new MutatorStage(new ReplaceMutator("LAND_TEMP", landBiomes, whiteNoise(243))))
|
.addStage(new MutatorStage(new ReplaceMutator("LAND_TEMP", landBiomes, whiteNoise(243))))
|
||||||
@ -76,10 +75,7 @@ public class BiomeTest {
|
|||||||
.addStage(new MutatorStage(new BorderMutator("OCEAN", "LAND", whiteNoise(1234), beachBiomes)))
|
.addStage(new MutatorStage(new BorderMutator("OCEAN", "LAND", whiteNoise(1234), beachBiomes)))
|
||||||
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(6))))
|
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(6))))
|
||||||
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(6))))
|
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(6))))
|
||||||
.build(source);
|
.build(source), null).build(0);
|
||||||
System.out.println("Size: " + pipeline.getSize());
|
|
||||||
return pipeline;
|
|
||||||
}, null).build(0);
|
|
||||||
|
|
||||||
|
|
||||||
int size = 1000;
|
int size = 1000;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user