Rewrite basically the whole generator again. Get rid of failsafe biomes because they are dumb

This commit is contained in:
dfsek
2020-11-16 23:32:04 -07:00
parent deb7db9b25
commit cb537d0514
20 changed files with 121 additions and 239 deletions

View File

@@ -3,7 +3,6 @@ package com.dfsek.terra.generation;
import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
import com.dfsek.terra.math.NoiseFunction2;
import com.dfsek.terra.math.NoiseFunction3;
import org.bukkit.World;
import parsii.eval.Expression;
import parsii.eval.Parser;
import parsii.eval.Scope;
@@ -19,7 +18,7 @@ public class ElevationEquation {
private final Variable xVar = s.getVariable("x");
private final Variable zVar = s.getVariable("z");
public ElevationEquation(World w, String elevateEquation, Map<String, Double> userVariables, Map<String, NoiseConfig> noiseBuilders) {
public ElevationEquation(long seed, String elevateEquation, Map<String, Double> userVariables, Map<String, NoiseConfig> noiseBuilders) {
for(Map.Entry<String, Double> entry : userVariables.entrySet()) {
s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables.
}
@@ -28,11 +27,11 @@ public class ElevationEquation {
for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
switch(e.getValue().getDimensions()) {
case 2:
NoiseFunction2 function2 = new NoiseFunction2(w, e.getValue().getBuilder());
NoiseFunction2 function2 = new NoiseFunction2(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function2);
break;
case 3:
NoiseFunction3 function3 = new NoiseFunction3(w, e.getValue().getBuilder());
NoiseFunction3 function3 = new NoiseFunction3(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function3);
break;
}

View File

@@ -1,12 +1,13 @@
package com.dfsek.terra.generation;
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
import com.dfsek.terra.generation.config.WorldGenerator;
import org.bukkit.World;
import org.polydev.gaea.generation.GenerationPhase;
import org.polydev.gaea.math.Interpolator;
public class ElevationInterpolator {
private final UserDefinedGenerator[][] gens = new UserDefinedGenerator[10][10];
private final WorldGenerator[][] gens = new WorldGenerator[10][10];
private final double[][] values = new double[18][18];
private final int xOrigin;
private final int zOrigin;
@@ -19,13 +20,13 @@ public class ElevationInterpolator {
for(int x = -2; x < 8; x++) {
for(int z = -2; z < 8; z++) {
gens[x + 2][z + 2] = (UserDefinedGenerator) grid.getBiome(xOrigin + x * 4, zOrigin + z * 4, GenerationPhase.BASE).getGenerator();
gens[x + 2][z + 2] = (WorldGenerator) grid.getBiome(xOrigin + x * 4, zOrigin + z * 4, GenerationPhase.BASE).getGenerator();
}
}
for(byte x = -1; x <= 16; x++) {
for(byte z = -1; z <= 16; z++) {
UserDefinedGenerator generator = getGenerator(x, z);
WorldGenerator generator = getGenerator(x, z);
if(compareGens((x / 4), (z / 4)) && generator.interpolateElevation()) {
Interpolator interpolator = new Interpolator(biomeAvg(x / 4, z / 4, w),
biomeAvg((x / 4) + 1, z / 4, w),
@@ -38,16 +39,16 @@ public class ElevationInterpolator {
}
}
private UserDefinedGenerator getGenerator(int x, int z) {
return (UserDefinedGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator();
private WorldGenerator getGenerator(int x, int z) {
return (WorldGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator();
}
private UserDefinedGenerator getStoredGen(int x, int z) {
private WorldGenerator getStoredGen(int x, int z) {
return gens[x + 2][z + 2];
}
private boolean compareGens(int x, int z) {
UserDefinedGenerator comp = getStoredGen(x, z);
WorldGenerator comp = getStoredGen(x, z);
for(int xi = x - 2; xi <= x + 2; xi++) {
for(int zi = z - 2; zi <= z + 2; zi++) {
@@ -69,7 +70,7 @@ public class ElevationInterpolator {
+ elevate(getStoredGen(x + 1, z + 1), x * 4 + xOrigin, z * 4 + zOrigin, w)) / 9D;
}
private double elevate(UserDefinedGenerator g, int x, int z, World w) {
private double elevate(WorldGenerator g, int x, int z, World w) {
if(g.getElevationEquation(w) != null) return g.getElevationEquation(w).getNoise(x, z);
return 0;
}

View File

@@ -9,6 +9,7 @@ import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
import com.dfsek.terra.config.genconfig.biome.BiomeSlabConfig;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.generation.config.WorldGenerator;
import com.dfsek.terra.population.CavePopulator;
import com.dfsek.terra.population.FloraPopulator;
import com.dfsek.terra.population.OrePopulator;
@@ -83,7 +84,7 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
}
private static Palette<BlockData> getPalette(int x, int y, int z, BiomeConfig c, ChunkInterpolator interpolator, ElevationInterpolator elevationInterpolator) {
Palette<BlockData> slant = ((UserDefinedGenerator) c.getBiome().getGenerator()).getSlantPalette(y);
Palette<BlockData> slant = ((WorldGenerator) c.getBiome().getGenerator()).getSlantPalette(y);
if(slant != null) {
boolean north = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z + 1), z + 1) > 0;
boolean south = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z - 1), z - 1) > 0;

View File

@@ -1,150 +0,0 @@
package com.dfsek.terra.generation;
import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
import com.dfsek.terra.generation.config.WorldGenerator;
import com.dfsek.terra.math.BlankFunction;
import com.dfsek.terra.util.DataUtil;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.Nullable;
import org.polydev.gaea.biome.Generator;
import org.polydev.gaea.math.FastNoiseLite;
import org.polydev.gaea.math.Interpolator;
import org.polydev.gaea.world.palette.Palette;
import parsii.eval.Parser;
import parsii.eval.Scope;
import parsii.tokenizer.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class UserDefinedGenerator extends Generator {
private final boolean preventSmooth;
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
private final Palette<BlockData>[] palettes = new Palette[256];
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
private final Palette<BlockData>[] slantPalettes = new Palette[256];
private final String equation;
private final String elevationEquation;
private final Map<String, Double> userVariables;
private final Map<String, NoiseConfig> noiseBuilders;
private final Map<UUID, WorldGenerator> gens = new HashMap<>();
private boolean elevationInterpolation;
public UserDefinedGenerator(String equation, @Nullable String elevateEquation, Map<String, Double> userVariables, Map<Integer, Palette<BlockData>> paletteMap, Map<Integer, Palette<BlockData>> slantPaletteMap, Map<String, NoiseConfig> noiseBuilders, boolean preventSmooth)
throws ParseException {
this.equation = equation;
this.elevationEquation = elevateEquation;
this.userVariables = userVariables;
this.noiseBuilders = noiseBuilders;
this.preventSmooth = preventSmooth;
Scope s = new Scope();
Parser p = new Parser();
for(Map.Entry<String, Double> entry : userVariables.entrySet()) {
s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables.
}
for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
int dimensions = e.getValue().getDimensions();
if(dimensions == 2 || dimensions == 3) p.registerFunction(e.getKey(), new BlankFunction(dimensions));
}
p.parse(equation, s); // Validate equation at config load time to prevent error during world load.
if(elevateEquation != null) p.parse(elevateEquation, s);
for(int y = 0; y < 256; y++) {
Palette<BlockData> d = DataUtil.BLANK_PALETTE;
for(Map.Entry<Integer, Palette<BlockData>> e : paletteMap.entrySet()) {
if(e.getKey() >= y) {
d = e.getValue();
break;
}
}
palettes[y] = d;
Palette<BlockData> slantPalette = null;
for(Map.Entry<Integer, Palette<BlockData>> e : slantPaletteMap.entrySet()) {
if(e.getKey() >= y) {
slantPalette = e.getValue();
break;
}
}
slantPalettes[y] = slantPalette;
}
}
/**
* Gets the 2D noise at a pair of coordinates using the provided FastNoiseLite instance.
*
* @param gen - The FastNoiseLite instance to use.
* @param x - The x coordinate.
* @param z - The z coordinate.
* @return double - Noise value at the specified coordinates.
*/
@Override
public double getNoise(FastNoiseLite gen, World w, int x, int z) {
return compute(w).getNoise(x, 0, z);
}
/**
* Gets the 3D noise at a pair of coordinates using the provided FastNoiseLite instance.
*
* @param gen - The FastNoiseLite instance to use.
* @param x - The x coordinate.
* @param y - The y coordinate.
* @param z - The z coordinate.
* @return double - Noise value at the specified coordinates.
*/
@Override
public double getNoise(FastNoiseLite gen, World w, int x, int y, int z) {
return compute(w).getNoise(x, y, z);
}
private WorldGenerator compute(World world) {
return gens.computeIfAbsent(world.getUID(), w -> new WorldGenerator(world, equation, elevationEquation, userVariables, noiseBuilders));
}
/**
* Gets the BlocPalette to generate the biome with.
*
* @return BlocPalette - The biome's palette.
*/
@Override
public Palette<BlockData> getPalette(int y) {
return palettes[y];
}
public Palette<BlockData> getSlantPalette(int y) {
return slantPalettes[y];
}
@Override
public boolean useMinimalInterpolation() {
return preventSmooth;
}
@Override
public Interpolator.Type getInterpolationType() {
return Interpolator.Type.LINEAR;
}
public ElevationEquation getElevationEquation(World w) {
return compute(w).getElevationEquation();
}
public boolean interpolateElevation() {
return elevationInterpolation;
}
public void setElevationInterpolation(boolean elevationInterpolation) {
this.elevationInterpolation = elevationInterpolation;
}
}

View File

@@ -6,6 +6,11 @@ import com.dfsek.terra.generation.ElevationEquation;
import com.dfsek.terra.math.NoiseFunction2;
import com.dfsek.terra.math.NoiseFunction3;
import org.bukkit.World;
import org.bukkit.block.data.BlockData;
import org.polydev.gaea.biome.Generator;
import org.polydev.gaea.math.FastNoiseLite;
import org.polydev.gaea.math.Interpolator;
import org.polydev.gaea.world.palette.Palette;
import parsii.eval.Expression;
import parsii.eval.Parser;
import parsii.eval.Scope;
@@ -14,29 +19,44 @@ import parsii.tokenizer.ParseException;
import java.util.Map;
public class WorldGenerator {
public class WorldGenerator extends Generator {
private final ElevationEquation elevationEquation;
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
private final Palette<BlockData>[] palettes;
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
private final Palette<BlockData>[] slantPalettes;
private final boolean preventSmooth;
private boolean elevationInterpolation = true;
private final Expression noiseExp;
private final Scope s = new Scope();
private final Variable xVar = s.getVariable("x");
private final Variable yVar = s.getVariable("y");
private final Variable zVar = s.getVariable("z");
public WorldGenerator(World w, String equation, String elevateEquation, Map<String, Double> userVariables, Map<String, NoiseConfig> noiseBuilders) {
@SuppressWarnings({"rawtypes", "unchecked"})
public WorldGenerator(long seed, String equation, String elevateEquation, Map<String, Double> userVariables, Map<String, NoiseConfig> noiseBuilders, Palette[] palettes, Palette[] slantPalettes, boolean preventSmooth) {
for(Map.Entry<String, Double> entry : userVariables.entrySet()) {
s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables.
}
Parser p = new Parser();
this.preventSmooth = preventSmooth;
this.palettes = palettes;
this.slantPalettes = slantPalettes;
for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
switch(e.getValue().getDimensions()) {
case 2:
NoiseFunction2 function2 = new NoiseFunction2(w, e.getValue().getBuilder());
NoiseFunction2 function2 = new NoiseFunction2(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function2);
break;
case 3:
NoiseFunction3 function3 = new NoiseFunction3(w, e.getValue().getBuilder());
NoiseFunction3 function3 = new NoiseFunction3(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function3);
break;
}
@@ -45,21 +65,68 @@ public class WorldGenerator {
this.noiseExp = p.parse(equation, s);
if(elevateEquation != null) {
Debug.info("Using elevation equation");
this.elevationEquation = new ElevationEquation(w, elevateEquation, userVariables, noiseBuilders);
this.elevationEquation = new ElevationEquation(seed, elevateEquation, userVariables, noiseBuilders);
} else this.elevationEquation = null;
} catch(ParseException e) {
throw new IllegalArgumentException();
}
}
public double getNoise(int x, int y, int z) {
public ElevationEquation getElevationEquation() {
return elevationEquation;
}
@Override
public double getNoise(FastNoiseLite fastNoiseLite, World world, int x, int z) {
xVar.setValue(x);
yVar.setValue(0);
zVar.setValue(z);
return noiseExp.evaluate();
}
@Override
public double getNoise(FastNoiseLite fastNoiseLite, World world, int x, int y, int z) {
xVar.setValue(x);
yVar.setValue(y);
zVar.setValue(z);
return noiseExp.evaluate();
}
public ElevationEquation getElevationEquation() {
/**
* Gets the BlocPalette to generate the biome with.
*
* @return BlocPalette - The biome's palette.
*/
@Override
public Palette<BlockData> getPalette(int y) {
return palettes[y];
}
public Palette<BlockData> getSlantPalette(int y) {
return slantPalettes[y];
}
@Override
public boolean useMinimalInterpolation() {
return preventSmooth;
}
@Override
public Interpolator.Type getInterpolationType() {
return Interpolator.Type.LINEAR;
}
public ElevationEquation getElevationEquation(World w) {
return elevationEquation;
}
public boolean interpolateElevation() {
return elevationInterpolation;
}
public WorldGenerator setElevationInterpolation(boolean elevationInterpolation) {
this.elevationInterpolation = elevationInterpolation;
return this;
}
}