drastically simplify generator API

This commit is contained in:
dfsek
2021-12-02 19:45:22 -07:00
parent 71a39ba05b
commit e533555b52
26 changed files with 103 additions and 236 deletions
@@ -7,12 +7,6 @@
package com.dfsek.terra.addons.chunkgenerator.generation.generators; package com.dfsek.terra.addons.chunkgenerator.generation.generators;
import com.dfsek.terra.api.properties.Context;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.WritableWorld;
import com.dfsek.terra.api.world.chunk.generation.util.math.SamplerProvider;
import net.jafama.FastMath; import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -21,38 +15,36 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.dfsek.terra.addons.chunkgenerator.PaletteUtil; import com.dfsek.terra.addons.chunkgenerator.PaletteUtil;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProviderImpl;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteInfo; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteInfo;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.profiler.ProfileFrame; import com.dfsek.terra.api.profiler.ProfileFrame;
import com.dfsek.terra.api.util.math.Sampler; import com.dfsek.terra.api.util.math.Sampler;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.WritableWorld;
import com.dfsek.terra.api.world.biome.GenerationSettings; import com.dfsek.terra.api.world.biome.GenerationSettings;
import com.dfsek.terra.api.world.biome.TerraBiome; import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoChunk;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.Palette; import com.dfsek.terra.api.world.chunk.generation.util.Palette;
public class NoiseChunkGenerator3D implements ChunkGenerator { public class NoiseChunkGenerator3D implements ChunkGenerator {
private final ConfigPack configPack;
private final Platform platform; private final Platform platform;
private final List<GenerationStage> generationStages = new ArrayList<>(); private final List<GenerationStage> generationStages = new ArrayList<>();
private final int elevationBlend; private final SamplerProviderImpl samplerCache;
private final SamplerProvider samplerCache;
private final BlockState air; private final BlockState air;
public NoiseChunkGenerator3D(ConfigPack c, Platform platform, int elevationBlend) { public NoiseChunkGenerator3D(ConfigPack c, Platform platform, int elevationBlend) {
this.configPack = c;
this.platform = platform; this.platform = platform;
this.air = platform.getWorldHandle().air(); this.air = platform.getWorldHandle().air();
this.elevationBlend = elevationBlend; this.samplerCache = new SamplerProviderImpl(platform, c.getBiomeProvider(), elevationBlend);
c.getStages().forEach(stage -> generationStages.add(stage.newInstance(c))); c.getStages().forEach(stage -> generationStages.add(stage.newInstance(c)));
} }
@@ -63,37 +55,37 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
int chunkX) { int chunkX) {
try(ProfileFrame ignore = platform.getProfiler().profile("chunk_base_3d")) { try(ProfileFrame ignore = platform.getProfiler().profile("chunk_base_3d")) {
BiomeProvider grid = world.getBiomeProvider(); BiomeProvider grid = world.getBiomeProvider();
int xOrig = (chunkX << 4); int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4); int zOrig = (chunkZ << 4);
Sampler sampler = samplerCache.getChunk(chunkX, chunkZ); Sampler sampler = samplerCache.getChunk(chunkX, chunkZ, world);
long seed = world.getSeed(); long seed = world.getSeed();
for(int x = 0; x < 16; x++) { for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) { for(int z = 0; z < 16; z++) {
int paletteLevel = 0; int paletteLevel = 0;
int cx = xOrig + x; int cx = xOrig + x;
int cz = zOrig + z; int cz = zOrig + z;
TerraBiome biome = grid.getBiome(cx, cz, seed); TerraBiome biome = grid.getBiome(cx, cz, seed);
PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class);
GenerationSettings generationSettings = biome.getGenerator(); GenerationSettings generationSettings = biome.getGenerator();
int sea = paletteInfo.getSeaLevel(); int sea = paletteInfo.getSeaLevel();
Palette seaPalette = paletteInfo.getOcean(); Palette seaPalette = paletteInfo.getOcean();
BlockState data; BlockState data;
for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) { for(int y = world.getMaxHeight() - 1; y >= world.getMinHeight(); y--) {
if(sampler.sample(x, y, z) > 0) { if(sampler.sample(x, y, z) > 0) {
data = PaletteUtil.getPalette(x, y, z, generationSettings, sampler, paletteInfo).get(paletteLevel, cx, y, cz, data = PaletteUtil.getPalette(x, y, z, generationSettings, sampler, paletteInfo).get(paletteLevel, cx, y, cz,
seed); seed);
chunk.setBlock(x, y, z, data); chunk.setBlock(x, y, z, data);
paletteLevel++; paletteLevel++;
} else if(y <= sea) { } else if(y <= sea) {
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig, seed)); chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig, seed));
@@ -107,11 +99,6 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
} }
} }
@Override
public Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth) {
return new Sampler3D(chunkX, chunkZ, provider, world, elevationSmooth);
}
@Override @Override
public List<GenerationStage> getGenerationStages() { public List<GenerationStage> getGenerationStages() {
return generationStages; return generationStages;
@@ -121,7 +108,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
public BlockState getBlock(ServerWorld world, int x, int y, int z) { public BlockState getBlock(ServerWorld world, int x, int y, int z) {
BiomeProvider provider = world.getBiomeProvider(); BiomeProvider provider = world.getBiomeProvider();
TerraBiome biome = provider.getBiome(x, z, world.getSeed()); TerraBiome biome = provider.getBiome(x, z, world.getSeed());
Sampler sampler = world.getConfig().getSamplerCache().get(x, z); Sampler sampler = samplerCache.get(x, z, world);
PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class); PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class);
Palette palette = PaletteUtil.getPalette(x, y, z, biome.getGenerator(), sampler, paletteInfo); Palette palette = PaletteUtil.getPalette(x, y, z, biome.getGenerator(), sampler, paletteInfo);
@@ -139,4 +126,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
return paletteInfo.getOcean().get(paletteInfo.getSeaLevel() - y, x, y, z, world.getSeed()); return paletteInfo.getOcean().get(paletteInfo.getSeaLevel() - y, x, y, z, world.getSeed());
} else return air; } else return air;
} }
public SamplerProviderImpl samplerProvider() {
return samplerCache;
}
} }
@@ -7,7 +7,6 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.World; import com.dfsek.terra.api.world.World;
import net.jafama.FastMath; import net.jafama.FastMath;
@@ -36,20 +35,22 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
/** /**
* Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates. * Instantiates a 3D ChunkInterpolator3D at a pair of chunk coordinates.
* * @param chunkX X coordinate of the chunk.
* @param chunkX X coordinate of the chunk.
* @param chunkZ Z coordinate of the chunk. * @param chunkZ Z coordinate of the chunk.
* @param provider Biome Provider to use for biome fetching. * @param provider Biome Provider to use for biome fetching.
* @param min
* @param max
*/ */
public ChunkInterpolator3D(World w, int chunkX, int chunkZ, BiomeProvider provider, public ChunkInterpolator3D(long seed, int chunkX, int chunkZ, BiomeProvider provider,
BiFunction<GenerationSettings, Vector3, Double> noiseGetter) { BiFunction<GenerationSettings, Vector3, Double> noiseGetter, int min, int max) {
this.noiseGetter = noiseGetter; this.noiseGetter = noiseGetter;
this.min = min;
this.max = max;
int xOrigin = chunkX << 4; int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4; int zOrigin = chunkZ << 4;
this.max = w.getMaxHeight(); int range = this.max - this.min + 1;
this.min = w.getMinHeight();
int range = max - min + 1;
int size = range >> 2; int size = range >> 2;
@@ -57,7 +58,6 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
double[][][] noiseStorage = new double[5][5][size + 1]; double[][][] noiseStorage = new double[5][5][size + 1];
long seed = w.getSeed();
for(int x = 0; x < 5; x++) { for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) { for(int z = 0; z < 5; z++) {
@@ -76,7 +76,7 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
} }
for(int y = 0; y < size + 1; y++) { for(int y = 0; y < size + 1; y++) {
noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + min, (z << 2) + zOrigin); noiseStorage[x][z][y] = computeNoise(genMap, (x << 2) + xOrigin, (y << 2) + this.min, (z << 2) + zOrigin);
} }
} }
} }
@@ -16,12 +16,10 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
public class ElevationInterpolator { public class ElevationInterpolator {
private final double[][] values = new double[18][18]; private final double[][] values = new double[18][18];
public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeProvider provider, int smooth) { public ElevationInterpolator(long seed, int chunkX, int chunkZ, BiomeProvider provider, int smooth) {
int xOrigin = chunkX << 4; int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4; int zOrigin = chunkZ << 4;
long seed = world.getSeed();
GenerationSettings[][] gens = new GenerationSettings[18 + 2 * smooth][18 + 2 * smooth]; GenerationSettings[][] gens = new GenerationSettings[18 + 2 * smooth][18 + 2 * smooth];
// Precompute generators. // Precompute generators.
@@ -7,9 +7,6 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.World;
import net.jafama.FastMath; import net.jafama.FastMath;
import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ChunkInterpolator3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.ChunkInterpolator3D;
@@ -22,11 +19,12 @@ public class Sampler3D implements Sampler {
private final ChunkInterpolator3D interpolator; private final ChunkInterpolator3D interpolator;
private final ElevationInterpolator elevationInterpolator; private final ElevationInterpolator elevationInterpolator;
public Sampler3D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) { public Sampler3D(int x, int z, long seed, int minHeight, int maxHeight, BiomeProvider provider, int elevationSmooth) {
this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler() this.interpolator = new ChunkInterpolator3D(seed, x, z, provider, (generator, coord) -> generator.getBaseSampler()
.noise(coord, .noise(coord,
world.getSeed())); seed),
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth); minHeight, maxHeight);
this.elevationInterpolator = new ElevationInterpolator(seed, x, z, provider, elevationSmooth);
} }
@Override @Override
@@ -17,8 +17,7 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers; package com.dfsek.terra.addons.chunkgenerator.generation.math.samplers;
import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.chunk.generation.util.math.SamplerProvider;
import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader;
@@ -28,35 +27,38 @@ import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.util.MathUtil;
import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.util.math.Sampler; import com.dfsek.terra.api.util.math.Sampler;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
public class SamplerProviderImpl implements SamplerProvider { public class SamplerProviderImpl {
private final LoadingCache<Long, Sampler> cache; private final LoadingCache<Pair<Long, World>, Sampler> cache;
public SamplerProviderImpl(Platform platform, ServerWorld world) {
public SamplerProviderImpl(Platform platform, BiomeProvider provider, int elevationSmooth) {
cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache()) cache = CacheBuilder.newBuilder().maximumSize(platform.getTerraConfig().getSamplerCache())
.build(new CacheLoader<>() { .build(new CacheLoader<>() {
@Override @Override
public Sampler load(@NotNull Long key) { public Sampler load(@NotNull Pair<Long, World> pair) {
long key = pair.getLeft();
int cx = (int) (key >> 32); int cx = (int) (key >> 32);
int cz = (int) key.longValue(); int cz = (int) key;
return world.getGenerator().createSampler(cx, cz, world.getBiomeProvider(), world, World world = pair.getRight();
world.getConfig().elevationBlend()); return new Sampler3D(cx, cz, world.getSeed(), world.getMinHeight(), world.getMaxHeight(), provider, elevationSmooth);
} }
}); });
} }
@Override public Sampler get(int x, int z, World world) {
public Sampler get(int x, int z) {
int cx = FastMath.floorDiv(x, 16); int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16); int cz = FastMath.floorDiv(z, 16);
return getChunk(cx, cz); return getChunk(cx, cz, world);
} }
@Override public Sampler getChunk(int cx, int cz, World world) {
public Sampler getChunk(int cx, int cz) {
long key = MathUtil.squash(cx, cz); long key = MathUtil.squash(cx, cz);
return cache.getUnchecked(key); return cache.getUnchecked(Pair.of(key, world));
} }
} }
@@ -22,6 +22,6 @@ public class BiomeArgumentParser implements ArgumentParser<TerraBiome> {
@Override @Override
public TerraBiome parse(CommandSender sender, String arg) { public TerraBiome parse(CommandSender sender, String arg) {
Player player = (Player) sender; Player player = (Player) sender;
return player.world().getConfig().getRegistry(TerraBiome.class).get(arg).orElse(null); return player.world().getPack().getRegistry(TerraBiome.class).get(arg).orElse(null);
} }
} }
@@ -25,7 +25,7 @@ public class BiomeTabCompleter implements TabCompleter {
@Override @Override
public List<String> complete(CommandSender sender) { public List<String> complete(CommandSender sender) {
Player player = (Player) sender; Player player = (Player) sender;
return player.world().getConfig().getRegistry(TerraBiome.class).entries().stream().map(TerraBiome::getID).collect( return player.world().getPack().getRegistry(TerraBiome.class).entries().stream().map(TerraBiome::getID).collect(
Collectors.toList()); Collectors.toList());
} }
} }
@@ -21,6 +21,6 @@ public class ScriptArgumentParser implements ArgumentParser<Structure> {
@Override @Override
public Structure parse(CommandSender sender, String arg) { public Structure parse(CommandSender sender, String arg) {
return ((Player) sender).world().getConfig().getRegistry(Structure.class).get(arg).orElse(null); return ((Player) sender).world().getPack().getRegistry(Structure.class).get(arg).orElse(null);
} }
} }
@@ -21,6 +21,6 @@ public class StructureArgumentParser implements ArgumentParser<ConfiguredStructu
@Override @Override
public ConfiguredStructure parse(CommandSender sender, String arg) { public ConfiguredStructure parse(CommandSender sender, String arg) {
return ((Player) sender).world().getConfig().getRegistry(ConfiguredStructure.class).get(arg).orElse(null); return ((Player) sender).world().getPack().getRegistry(ConfiguredStructure.class).get(arg).orElse(null);
} }
} }
@@ -24,7 +24,7 @@ public class ScriptCompleter implements TabCompleter {
@Override @Override
public List<String> complete(CommandSender sender) { public List<String> complete(CommandSender sender) {
return ((Player) sender).world().getConfig().getRegistry(Structure.class).entries().stream().map(Structure::getID).collect( return ((Player) sender).world().getPack().getRegistry(Structure.class).entries().stream().map(Structure::getID).collect(
Collectors.toList()); Collectors.toList());
} }
} }
@@ -25,6 +25,6 @@ public class StructureCompleter implements TabCompleter {
@Override @Override
public List<String> complete(CommandSender sender) { public List<String> complete(CommandSender sender) {
Player player = (Player) sender; Player player = (Player) sender;
return new ArrayList<>(player.world().getConfig().getRegistry(ConfiguredStructure.class).keys()); return new ArrayList<>(player.world().getPack().getRegistry(ConfiguredStructure.class).keys());
} }
} }
@@ -29,6 +29,6 @@ public class BufferedEntity implements BufferedItem {
@Override @Override
public void paste(Vector3 origin, WritableWorld world) { public void paste(Vector3 origin, WritableWorld world) {
Entity entity = world.spawnEntity(origin.clone().add(0.5, 0, 0.5), type); Entity entity = world.spawnEntity(origin.clone().add(0.5, 0, 0.5), type);
platform.getEventManager().callEvent(new EntitySpawnEvent(entity.world().getConfig().getPack(), entity)); platform.getEventManager().callEvent(new EntitySpawnEvent(entity.world().getPack(), entity));
} }
} }
@@ -46,7 +46,7 @@ public class BufferedLootApplication implements BufferedItem {
return; return;
} }
LootPopulateEvent event = new LootPopulateEvent(container, table, world.getConfig().getPack(), structure); LootPopulateEvent event = new LootPopulateEvent(container, table, world.getPack(), structure);
platform.getEventManager().callEvent(event); platform.getEventManager().callEvent(event);
if(event.isCancelled()) return; if(event.isCancelled()) return;
@@ -7,23 +7,24 @@
package com.dfsek.terra.addon.terrascript.check; package com.dfsek.terra.addon.terrascript.check;
import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.World;
import net.jafama.FastMath; import net.jafama.FastMath;
import java.util.Map; import java.util.Map;
import com.dfsek.terra.addons.chunkgenerator.generation.generators.NoiseChunkGenerator3D;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProviderImpl;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function; import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable; import com.dfsek.terra.addons.terrascript.parser.lang.variables.Variable;
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments; import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
import com.dfsek.terra.addons.terrascript.tokenizer.Position; import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.util.RotationUtil; import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.util.vector.Vector2; import com.dfsek.terra.api.util.vector.Vector2;
import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.chunk.generation.util.math.SamplerProvider; import com.dfsek.terra.api.world.WritableWorld;
public class CheckFunction implements Function<String> { public class CheckFunction implements Function<String> {
@@ -70,8 +71,8 @@ public class CheckFunction implements Function<String> {
private String apply(Vector3 vector, WritableWorld world) { private String apply(Vector3 vector, WritableWorld world) {
int y = vector.getBlockY(); int y = vector.getBlockY();
if(y >= world.getMaxHeight() || y < 0) return "AIR"; if(y >= world.getMaxHeight() || y < 0) return "AIR";
SamplerProvider cache = world.getGenerator().getSamplerCache(); SamplerProviderImpl cache = ((NoiseChunkGenerator3D) world.getGenerator()).samplerProvider();
double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache); double comp = sample(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ(), cache, world);
if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land. if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
@@ -83,9 +84,9 @@ public class CheckFunction implements Function<String> {
//return "OCEAN"; // Below sea level //return "OCEAN"; // Below sea level
} }
private double sample(int x, int y, int z, SamplerProvider cache) { private double sample(int x, int y, int z, SamplerProviderImpl cache, World world) {
int cx = FastMath.floorDiv(x, 16); int cx = FastMath.floorDiv(x, 16);
int cz = FastMath.floorDiv(z, 16); int cz = FastMath.floorDiv(z, 16);
return cache.get(x, z).sample(x - (cx << 4), y, z - (cz << 4)); return cache.get(x, z, world).sample(x - (cx << 4), y, z - (cz << 4));
} }
} }
@@ -1,6 +1,7 @@
package com.dfsek.terra.api.world; package com.dfsek.terra.api.world;
import com.dfsek.terra.api.Handle; import com.dfsek.terra.api.Handle;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
@@ -15,4 +16,6 @@ public interface World extends Handle {
ChunkGenerator getGenerator(); ChunkGenerator getGenerator();
BiomeProvider getBiomeProvider(); BiomeProvider getBiomeProvider();
ConfigPack getPack();
} }
@@ -7,27 +7,21 @@
package com.dfsek.terra.api.world.chunk.generation; package com.dfsek.terra.api.world.chunk.generation;
import com.dfsek.terra.api.properties.PropertyHolder;
import com.dfsek.terra.api.world.World;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.util.math.Sampler;
import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.util.vector.integer.Vector3Int; import com.dfsek.terra.api.util.vector.integer.Vector3Int;
import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.WritableWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
public interface ChunkGenerator { public interface ChunkGenerator {
void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WritableWorld world, void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WritableWorld world,
int chunkZ, int chunkX); int chunkZ, int chunkX);
Sampler createSampler(int chunkX, int chunkZ, BiomeProvider provider, World world, int elevationSmooth);
List<GenerationStage> getGenerationStages(); List<GenerationStage> getGenerationStages();
@@ -1,17 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the common/api directory.
*/
package com.dfsek.terra.api.world.chunk.generation.util.math;
import com.dfsek.terra.api.util.math.Sampler;
public interface SamplerProvider {
Sampler get(int x, int z);
Sampler getChunk(int cx, int cz);
}
@@ -1,91 +0,0 @@
/*
* This file is part of Terra.
*
* Terra is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Terra is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Terra. If not, see <https://www.gnu.org/licenses/>.
*/
package com.dfsek.terra.config.dummy;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.world.chunk.Chunk;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
public class DummyServerWorld implements ServerWorld {
@Override
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
throw new UnsupportedOperationException("Cannot spawn entity in DummyWorld");
}
@Override
public void setBlockData(int x, int y, int z, BlockState data, boolean physics) {
throw new UnsupportedOperationException("Cannot set block in DummyWorld");
}
@Override
public long getSeed() {
return 2403L;
}
@Override
public int getMaxHeight() {
return 255;
}
@Override
public Chunk getChunkAt(int x, int z) {
throw new UnsupportedOperationException("Cannot get chunk in DummyWorld");
}
@Override
public BlockState getBlockData(int x, int y, int z) {
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
}
@Override
public BlockEntity getBlockState(int x, int y, int z) {
throw new UnsupportedOperationException("Cannot get block in DummyWorld");
}
@Override
public int getMinHeight() {
return 0;
}
@Override
public ChunkGenerator getGenerator() {
throw new UnsupportedOperationException("Cannot get generator of DummyWorld");
}
@Override
public BiomeProvider getBiomeProvider() {
throw new UnsupportedOperationException("Cannot get biome provider of DummyWorld");
}
@Override
public WorldConfig getConfig() {
throw new UnsupportedOperationException("Cannot get config of DummyWorld");
}
@Override
public Object getHandle() {
throw new UnsupportedOperationException("Cannot get handle of DummyWorld");
}
}
@@ -30,9 +30,6 @@ import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.tectonic.loading.TypeRegistry; import com.dfsek.tectonic.loading.TypeRegistry;
import com.dfsek.tectonic.loading.object.ObjectTemplate; import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.tectonic.yaml.YamlConfiguration; import com.dfsek.tectonic.yaml.YamlConfiguration;
import com.dfsek.terra.api.world.ServerWorld;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -76,10 +73,10 @@ import com.dfsek.terra.api.registry.exception.DuplicateEntryException;
import com.dfsek.terra.api.registry.meta.RegistryFactory; import com.dfsek.terra.api.registry.meta.RegistryFactory;
import com.dfsek.terra.api.util.generic.pair.Pair; import com.dfsek.terra.api.util.generic.pair.Pair;
import com.dfsek.terra.api.util.reflection.ReflectionUtil; import com.dfsek.terra.api.util.reflection.ReflectionUtil;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider; import com.dfsek.terra.api.world.chunk.generation.util.provider.ChunkGeneratorProvider;
import com.dfsek.terra.api.world.chunk.generation.util.provider.GenerationStageProvider; import com.dfsek.terra.api.world.chunk.generation.util.provider.GenerationStageProvider;
import com.dfsek.terra.config.dummy.DummyServerWorld;
import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.ZIPLoader; import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader; import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader;
@@ -28,7 +28,6 @@ import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.world.ServerWorld; import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.registry.LockedRegistryImpl; import com.dfsek.terra.registry.LockedRegistryImpl;
import com.dfsek.terra.world.SamplerProviderImpl;
public class WorldConfigImpl implements WorldConfig { public class WorldConfigImpl implements WorldConfig {
@@ -209,6 +209,6 @@ public class TerraBukkitPlugin extends JavaPlugin {
return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> { return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> {
ConfigPack pack = platform.getConfigRegistry().get(id).orElseThrow(() -> new IllegalArgumentException("No such config pack \"" + id + "\"")); ConfigPack pack = platform.getConfigRegistry().get(id).orElseThrow(() -> new IllegalArgumentException("No such config pack \"" + id + "\""));
return pack.getGeneratorProvider().newInstance(pack); return pack.getGeneratorProvider().newInstance(pack);
}), platform.getRawConfigRegistry().get(id).orElseThrow(), platform); }), platform.getRawConfigRegistry().get(id).orElseThrow());
} }
} }
@@ -17,16 +17,6 @@
package com.dfsek.terra.bukkit.generator; package com.dfsek.terra.bukkit.generator;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.bukkit.world.BukkitProtoWorld;
import com.dfsek.terra.bukkit.world.BukkitServerWorld;
import com.dfsek.terra.world.SamplerProviderImpl;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.generator.BiomeProvider; import org.bukkit.generator.BiomeProvider;
@@ -40,8 +30,13 @@ import java.util.List;
import java.util.Random; import java.util.Random;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.ServerWorld;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper; import com.dfsek.terra.api.world.chunk.generation.util.GeneratorWrapper;
import com.dfsek.terra.bukkit.world.BukkitProtoWorld;
import com.dfsek.terra.bukkit.world.BukkitServerWorld;
public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper { public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGenerator implements GeneratorWrapper {
@@ -51,12 +46,10 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
private ServerWorld terraWorld; private ServerWorld terraWorld;
private final ConfigPack pack; private final ConfigPack pack;
private final Platform platform;
public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack, Platform platform) { public BukkitChunkGeneratorWrapper(ChunkGenerator delegate, ConfigPack pack) {
this.delegate = delegate; this.delegate = delegate;
this.pack = pack; this.pack = pack;
this.platform = platform;
} }
@Override @Override
@@ -1,5 +1,7 @@
package com.dfsek.terra.bukkit.world; package com.dfsek.terra.bukkit.world;
import com.dfsek.terra.api.config.ConfigPack;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.generator.LimitedRegion; import org.bukkit.generator.LimitedRegion;
@@ -78,6 +80,11 @@ public class BukkitProtoWorld implements ProtoWorld {
return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack().getBiomeProvider(); return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack().getBiomeProvider();
} }
@Override
public ConfigPack getPack() {
return ((BukkitChunkGeneratorWrapper) delegate.getWorld().getGenerator()).getPack();
}
@Override @Override
public int centerChunkX() { public int centerChunkX() {
return delegate.getCenterChunkX(); return delegate.getCenterChunkX();
@@ -22,6 +22,7 @@ import java.util.UUID;
import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.WorldConfig; import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.entity.EntityType;
@@ -44,18 +45,6 @@ public class BukkitServerWorld implements ServerWorld {
this.delegate = delegate; this.delegate = delegate;
} }
public UUID getUID() {
return delegate.getUID();
}
public boolean isChunkGenerated(int x, int z) {
return delegate.isChunkGenerated(x, z);
}
public File getWorldFolder() {
return delegate.getWorldFolder();
}
@Override @Override
public Entity spawnEntity(double x, double y, double z, EntityType entityType) { public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
return new BukkitEntity( return new BukkitEntity(
@@ -104,12 +93,12 @@ public class BukkitServerWorld implements ServerWorld {
@Override @Override
public BiomeProvider getBiomeProvider() { public BiomeProvider getBiomeProvider() {
return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getWorldConfig().getProvider(); return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getPack().getBiomeProvider();
} }
@Override @Override
public WorldConfig getConfig() { public ConfigPack getPack() {
return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getWorldConfig(); return ((BukkitChunkGeneratorWrapper) delegate.getGenerator()).getPack();
} }
@Override @Override
@@ -17,6 +17,7 @@
package com.dfsek.terra.fabric.mixin.implementations.world; package com.dfsek.terra.fabric.mixin.implementations.world;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import net.minecraft.block.FluidBlock; import net.minecraft.block.FluidBlock;
@@ -59,7 +60,7 @@ import com.dfsek.terra.fabric.util.FabricUtil;
@Mixin(ChunkRegion.class) @Mixin(ChunkRegion.class)
@Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$", remap = Interface.Remap.NONE)) @Implements(@Interface(iface = ProtoWorld.class, prefix = "terraWorld$", remap = Interface.Remap.NONE))
public abstract class ChunkRegionMixin { public abstract class ChunkRegionMixin {
private WorldConfig config; private ConfigPack config;
@Shadow @Shadow
@Final @Final
@@ -80,7 +81,7 @@ public abstract class ChunkRegionMixin {
method = "<init>(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V") method = "<init>(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V")
public void injectConstructor(net.minecraft.server.world.ServerWorld world, List<net.minecraft.world.chunk.Chunk> list, ChunkStatus chunkStatus, int i, public void injectConstructor(net.minecraft.server.world.ServerWorld world, List<net.minecraft.world.chunk.Chunk> list, ChunkStatus chunkStatus, int i,
CallbackInfo ci) { CallbackInfo ci) {
this.config = ((ServerWorld) world).getConfig(); this.config = ((ServerWorld) world).getPack();
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
@@ -149,7 +150,7 @@ public abstract class ChunkRegionMixin {
return (ServerWorld) world; return (ServerWorld) world;
} }
public WorldConfig terraWorld$getConfig() { public ConfigPack terraWorld$getPack() {
return config; return config;
} }
@@ -17,6 +17,8 @@
package com.dfsek.terra.fabric.mixin.implementations.world; package com.dfsek.terra.fabric.mixin.implementations.world;
import com.dfsek.terra.api.config.ConfigPack;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.WorldGenerationProgressListener; import net.minecraft.server.WorldGenerationProgressListener;
import net.minecraft.server.world.ServerChunkManager; import net.minecraft.server.world.ServerChunkManager;
@@ -60,7 +62,7 @@ import com.dfsek.terra.fabric.util.FabricUtil;
@Mixin(net.minecraft.server.world.ServerWorld.class) @Mixin(net.minecraft.server.world.ServerWorld.class)
@Implements(@Interface(iface = ServerWorld.class, prefix = "terra$", remap = Interface.Remap.NONE)) @Implements(@Interface(iface = ServerWorld.class, prefix = "terra$", remap = Interface.Remap.NONE))
public abstract class ServerWorldMixin { public abstract class ServerWorldMixin {
private WorldConfig config; private ConfigPack config;
@Shadow @Shadow
@Final @Final
private ServerChunkManager chunkManager; private ServerChunkManager chunkManager;
@@ -80,7 +82,7 @@ public abstract class ServerWorldMixin {
net.minecraft.world.gen.chunk.ChunkGenerator chunkGenerator, boolean debugWorld, long seed, net.minecraft.world.gen.chunk.ChunkGenerator chunkGenerator, boolean debugWorld, long seed,
List<Spawner> spawners, boolean shouldTickTime, CallbackInfo ci) { List<Spawner> spawners, boolean shouldTickTime, CallbackInfo ci) {
if(chunkGenerator instanceof FabricChunkGeneratorWrapper) { if(chunkGenerator instanceof FabricChunkGeneratorWrapper) {
config = ((FabricChunkGeneratorWrapper) chunkGenerator).getPack().toWorldConfig((ServerWorld) this); config = ((FabricChunkGeneratorWrapper) chunkGenerator).getPack();
} }
} }
@@ -129,7 +131,7 @@ public abstract class ServerWorldMixin {
return ((TerraBiomeSource) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager().getChunkGenerator().getBiomeSource()).getProvider(); return ((TerraBiomeSource) ((net.minecraft.server.world.ServerWorld) (Object) this).getChunkManager().getChunkGenerator().getBiomeSource()).getProvider();
} }
public WorldConfig terra$getConfig() { public ConfigPack terra$getPack() {
return config; return config;
} }