implement check cache

This commit is contained in:
dfsek committed 2020-12-30 21:03:28 -07:00
1 parent 8049824170
commit bccfcdf9a1
10 files changed
+92 -116

No files matched your search

@@ -13,6 +13,7 @@ public class TerraWorld {
private final ConfigPack config; private final ConfigPack config;
private final boolean safe; private final boolean safe;
private final TerraProfiler profiler; private final TerraProfiler profiler;
private final World world;
public TerraWorld(World w, ConfigPack c, TerraPlugin main) { public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
@@ -20,9 +21,14 @@ public class TerraWorld {
profiler = new TerraProfiler(w); profiler = new TerraProfiler(w);
this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(w.getSeed(), c, main).build(); this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(w.getSeed(), c, main).build();
this.zone = grid.getZone(); this.zone = grid.getZone();
this.world = w;
safe = true; safe = true;
} }
public World getWorld() {
return world;
}
public static boolean isTerraWorld(World w) { public static boolean isTerraWorld(World w) {
return w.getGenerator().getHandle() instanceof GeneratorWrapper; return w.getGenerator().getHandle() instanceof GeneratorWrapper;
} }
@@ -17,6 +17,7 @@ import com.dfsek.terra.api.structures.script.builders.StructureFunctionBuilder;
import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.structures.structure.buffer.Buffer; import com.dfsek.terra.api.structures.structure.buffer.Buffer;
import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer;
import com.dfsek.terra.api.structures.world.CheckCache;
import com.dfsek.terra.registry.ScriptRegistry; import com.dfsek.terra.registry.ScriptRegistry;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
@@ -31,7 +32,7 @@ public class StructureScript {
private final String id; private final String id;
private final LinkedHashMap<Location, StructureBuffer> cache; private final LinkedHashMap<Location, StructureBuffer> cache;
public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry) { public StructureScript(InputStream inputStream, TerraPlugin main, ScriptRegistry registry, CheckCache cache) {
Parser parser; Parser parser;
try { try {
parser = new Parser(IOUtils.toString(inputStream)); parser = new Parser(IOUtils.toString(inputStream));
@@ -39,7 +40,7 @@ public class StructureScript {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
parser.addFunction("block", new BlockFunctionBuilder(main)) parser.addFunction("block", new BlockFunctionBuilder(main))
.addFunction("check", new CheckFunctionBuilder(main)) .addFunction("check", new CheckFunctionBuilder(main, cache))
.addFunction("structure", new StructureFunctionBuilder(registry, main)) .addFunction("structure", new StructureFunctionBuilder(registry, main))
.addFunction("randomInt", new RandomFunctionBuilder()) .addFunction("randomInt", new RandomFunctionBuilder())
.addFunction("recursions", new RecursionsFunctionBuilder()) .addFunction("recursions", new RecursionsFunctionBuilder())
@@ -6,20 +6,23 @@ import com.dfsek.terra.api.structures.parser.lang.Returnable;
import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.api.structures.script.functions.CheckFunction; import com.dfsek.terra.api.structures.script.functions.CheckFunction;
import com.dfsek.terra.api.structures.tokenizer.Position; import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.api.structures.world.CheckCache;
import java.util.List; import java.util.List;
public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> { public class CheckFunctionBuilder implements FunctionBuilder<CheckFunction> {
private final TerraPlugin main; private final TerraPlugin main;
private final CheckCache cache;
public CheckFunctionBuilder(TerraPlugin main) { public CheckFunctionBuilder(TerraPlugin main, CheckCache cache) {
this.main = main; this.main = main;
this.cache = cache;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Override @Override
public CheckFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException { public CheckFunction build(List<Returnable<?>> argumentList, Position position) throws ParseException {
return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), position); return new CheckFunction(main, (Returnable<Number>) argumentList.get(0), (Returnable<Number>) argumentList.get(1), (Returnable<Number>) argumentList.get(2), cache, position);
} }
@Override @Override
@@ -1,5 +1,6 @@
package com.dfsek.terra.api.structures.script.functions; package com.dfsek.terra.api.structures.script.functions;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.math.vector.Location; import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector2; import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3; import com.dfsek.terra.api.math.vector.Vector3;
@@ -11,8 +12,11 @@ import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.structures.structure.RotationUtil; import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.structure.buffer.Buffer; import com.dfsek.terra.api.structures.structure.buffer.Buffer;
import com.dfsek.terra.api.structures.tokenizer.Position; import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.api.structures.world.LandCheck; import com.dfsek.terra.api.structures.world.CheckCache;
import com.dfsek.terra.api.structures.world.OceanCheck; import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.templates.BiomeTemplate;
import net.jafama.FastMath; import net.jafama.FastMath;
import java.util.Random; import java.util.Random;
@@ -21,13 +25,15 @@ public class CheckFunction implements Function<String> {
private final TerraPlugin main; private final TerraPlugin main;
private final Returnable<Number> x, y, z; private final Returnable<Number> x, y, z;
private final Position position; private final Position position;
private final CheckCache cache;
public CheckFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, Position position) { public CheckFunction(TerraPlugin main, Returnable<Number> x, Returnable<Number> y, Returnable<Number> z, CheckCache cache, Position position) {
this.main = main; this.main = main;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
this.position = position; this.position = position;
this.cache = cache;
} }
@Override @Override
@@ -49,11 +55,23 @@ public class CheckFunction implements Function<String> {
} }
private String apply(Location vector, World world) { private String apply(Location vector, World world) {
if(new LandCheck(world, main).check(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ())) TerraWorld tw = main.getWorld(world);
return "LAND"; double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), world);
if(new OceanCheck(world, main).check(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()))
return "OCEAN"; if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
return "AIR";
TerraBiomeGrid grid = tw.getGrid();
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(vector.getBlockX(), vector.getBlockZ(), GenerationPhase.POPULATE);
BiomeTemplate c = b.getConfig();
if(vector.getY() > c.getSeaLevel()) return "AIR"; // Above sea level
return "OCEAN"; // Below sea level
}
private double sample(int x, int y, int z, World w) {
int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16);
return cache.get(w, x, z).sample(x - (cx << 4), y, z - (cz << 4));
} }
@Override @Override
@@ -1,25 +0,0 @@
package com.dfsek.terra.api.structures.world;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.templates.BiomeTemplate;
public class AirCheck extends SpawnCheck {
public AirCheck(World world, TerraPlugin main) {
super(world, main);
}
@Override
public boolean check(int x, int y, int z) {
TerraWorld tw = main.getWorld(world);
TerraBiomeGrid g = tw.getGrid();
UserDefinedBiome b = (UserDefinedBiome) g.getBiome(x, z, GenerationPhase.POPULATE);
BiomeTemplate c = b.getConfig();
if(y <= c.getSeaLevel()) return false;
return sample(x, y, z, g) <= 0;
}
}
@@ -0,0 +1,49 @@
package com.dfsek.terra.api.structures.world;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.generation.math.Sampler;
import net.jafama.FastMath;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class CheckCache {
private final Map<Long, Container> cache;
private final TerraPlugin main;
public CheckCache(TerraPlugin main) {
cache = new HashMap<>();
this.main = main;
}
public Sampler get(World world, int x, int z) {
return cache.computeIfAbsent(world.getSeed(), seed -> new Container(world, new LinkedHashMap<Long, Sampler>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Long, Sampler> eldest) {
return size() > main.getTerraConfig().getCheckCache();
}
})).get(x, z);
}
private class Container {
private final World world;
private final Map<Long, Sampler> cache;
private Container(World world, Map<Long, Sampler> cache) {
this.world = world;
this.cache = cache;
}
public Sampler get(int x, int z) {
int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16);
long key = (((long) cx) << 32) | (cz & 0xffffffffL);
TerraWorld tw = main.getWorld(world);
return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, tw.getGrid(), world, 4, 8));
}
}
}
@@ -1,17 +0,0 @@
package com.dfsek.terra.api.structures.world;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
public class LandCheck extends SpawnCheck {
public LandCheck(World world, TerraPlugin main) {
super(world, main);
}
@Override
public boolean check(int x, int y, int z) {
TerraWorld tw = main.getWorld(world);
return sample(x, y, z, tw.getGrid()) > 0;
}
}
@@ -1,25 +0,0 @@
package com.dfsek.terra.api.structures.world;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.templates.BiomeTemplate;
public class OceanCheck extends SpawnCheck {
public OceanCheck(World world, TerraPlugin main) {
super(world, main);
}
@Override
public boolean check(int x, int y, int z) {
TerraWorld tw = main.getWorld(world);
TerraBiomeGrid grid = tw.getGrid();
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(x, z, GenerationPhase.POPULATE);
BiomeTemplate c = b.getConfig();
if(y > c.getSeaLevel()) return false;
return sample(x, y, z, grid) <= 0;
}
}
@@ -1,36 +0,0 @@
package com.dfsek.terra.api.structures.world;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.generation.math.Sampler;
import net.jafama.FastMath;
import java.util.LinkedHashMap;
import java.util.Map;
public abstract class SpawnCheck {
protected final World world;
protected final TerraPlugin main;
private final Map<Long, Sampler> cache;
protected SpawnCheck(World world, TerraPlugin main) {
this.world = world;
this.main = main;
cache = new LinkedHashMap<Long, Sampler>() {
@Override
protected boolean removeEldestEntry(Map.Entry<Long, Sampler> eldest) {
return size() > main.getTerraConfig().getCheckCache();
}
};
}
public abstract boolean check(int x, int y, int z);
protected double sample(int x, int y, int z, TerraBiomeGrid grid) {
int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16);
long key = (((long) cx) << 32) | (cz & 0xffffffffL);
return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, grid, world, 4, 8)).sample(x - (cx << 4), y, z - (cz << 4));
}
}
@@ -9,6 +9,7 @@ import com.dfsek.terra.api.LoaderRegistrar;
import com.dfsek.terra.api.loot.LootTable; import com.dfsek.terra.api.loot.LootTable;
import com.dfsek.terra.api.platform.TerraPlugin; import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.structures.script.StructureScript; import com.dfsek.terra.api.structures.script.StructureScript;
import com.dfsek.terra.api.structures.world.CheckCache;
import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.Palette;
@@ -148,8 +149,9 @@ public class ConfigPack implements LoaderRegistrar {
abstractConfigLoader abstractConfigLoader
.registerLoader(LootTable.class, new LootTableLoader(loader, main)); // These loaders need access to the Loader instance to get files. .registerLoader(LootTable.class, new LootTableLoader(loader, main)); // These loaders need access to the Loader instance to get files.
CheckCache checkCache = new CheckCache(main);
loader.open("structures/data", ".tesf").then(streams -> streams.forEach(stream -> { loader.open("structures/data", ".tesf").then(streams -> streams.forEach(stream -> {
StructureScript structureScript = new StructureScript(stream, main, scriptRegistry); StructureScript structureScript = new StructureScript(stream, main, scriptRegistry, checkCache);
scriptRegistry.add(structureScript.getId(), structureScript); scriptRegistry.add(structureScript.getId(), structureScript);
})).close(); })).close();