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
+1 -1
View File
@@ -35,7 +35,7 @@ val versionObj = Version("1", "4", "0", true)
version = versionObj version = versionObj
dependencies { dependencies {
val gaeaVersion = "1.14.2" val gaeaVersion = "1.14.3"
compileOnly(name = "Gaea-${gaeaVersion}", group = "") compileOnly(name = "Gaea-${gaeaVersion}", group = "")
testImplementation(name = "Gaea-${gaeaVersion}", group = "") testImplementation(name = "Gaea-${gaeaVersion}", group = "")
Binary file not shown.
@@ -1,7 +1,8 @@
package com.dfsek.terra.biome; package com.dfsek.terra.biome;
import com.dfsek.terra.config.genconfig.biome.GeneratorOptions;
import com.dfsek.terra.generation.UserDefinedDecorator; import com.dfsek.terra.generation.UserDefinedDecorator;
import com.dfsek.terra.generation.UserDefinedGenerator; import org.bukkit.World;
import org.polydev.gaea.biome.Biome; import org.polydev.gaea.biome.Biome;
import org.polydev.gaea.biome.Decorator; import org.polydev.gaea.biome.Decorator;
import org.polydev.gaea.biome.Generator; import org.polydev.gaea.biome.Generator;
@@ -13,14 +14,14 @@ import java.util.List;
* Class representing a config-defined biome * Class representing a config-defined biome
*/ */
public class UserDefinedBiome implements Biome { public class UserDefinedBiome implements Biome {
private final UserDefinedGenerator gen; private final GeneratorOptions gen;
private final UserDefinedDecorator decorator; private final UserDefinedDecorator decorator;
private final org.bukkit.block.Biome vanilla; private final org.bukkit.block.Biome vanilla;
private final String id; private final String id;
private final boolean erode; private final boolean erode;
public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, UserDefinedGenerator gen, boolean erode, String id) { public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, GeneratorOptions gen, boolean erode, String id) {
this.vanilla = vanilla; this.vanilla = vanilla;
this.decorator = dec; this.decorator = dec;
this.gen = gen; this.gen = gen;
@@ -45,7 +46,7 @@ public class UserDefinedBiome implements Biome {
*/ */
@Override @Override
public Generator getGenerator() { public Generator getGenerator() {
return gen; return gen.getGenerator(0);
} }
/** /**
@@ -75,4 +76,9 @@ public class UserDefinedBiome implements Biome {
public boolean isErodible() { public boolean isErodible() {
return erode; return erode;
} }
@Override
public Generator getGenerator(World w) {
return gen.getGenerator(w.getSeed());
}
} }
@@ -1,61 +0,0 @@
package com.dfsek.terra.biome.failsafe;
import org.bukkit.Bukkit;
import org.polydev.gaea.biome.Biome;
import parsii.tokenizer.ParseException;
/**
* What happens if terrain generation is attempted with an unrecoverable config error.
*/
@SuppressWarnings("unused")
public enum FailType {
/**
* Return failover biome, then shut down server to minimize damage.
* Generally the safest option.
*/
SHUTDOWN {
@Override
public Biome fail() {
Bukkit.getServer().shutdown();
try {
return new FailoverBiome();
} catch(ParseException e) {
e.printStackTrace();
return null;
}
}
},
/**
* Returns null, hard crashing the server, but not generating any corrupted terrain.<br>
* This option is <b>NOT</b> stable, but it has the least risk of blank chunks being generated.
* However, it has the highest risk of corruption!
*/
CRASH {
@Override
public Biome fail() {
return null;
}
},
/**
* Returns a failover biome, which generates completely blank chunks.
* Recommended for debugging.
*/
FAILOVER {
@Override
public Biome fail() {
try {
return new FailoverBiome();
} catch(ParseException e) {
e.printStackTrace();
return null;
}
}
};
/**
* Performs the action specified by the enum type to occur on failure of terrain generation.
*
* @return Failover biome, if specified, null if not.
*/
public abstract Biome fail();
}
@@ -1,13 +0,0 @@
package com.dfsek.terra.biome.failsafe;
import com.dfsek.terra.biome.UserDefinedBiome;
import parsii.tokenizer.ParseException;
/**
* Blank biome to generate in case of a severe config error
*/
public final class FailoverBiome extends UserDefinedBiome {
public FailoverBiome() throws ParseException {
super(org.bukkit.block.Biome.PLAINS, new FailoverDecorator(), new FailoverGenerator(), false, "FAILSAFE");
}
}
@@ -1,10 +0,0 @@
package com.dfsek.terra.biome.failsafe;
import com.dfsek.terra.generation.UserDefinedDecorator;
import org.polydev.gaea.math.ProbabilityCollection;
public final class FailoverDecorator extends UserDefinedDecorator {
public FailoverDecorator() {
super(new ProbabilityCollection<>(), new ProbabilityCollection<>(), 0, 0);
}
}
@@ -1,24 +0,0 @@
package com.dfsek.terra.biome.failsafe;
import com.dfsek.terra.generation.UserDefinedGenerator;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.polydev.gaea.world.palette.Palette;
import org.polydev.gaea.world.palette.RandomPalette;
import parsii.tokenizer.ParseException;
import java.util.HashMap;
import java.util.Random;
import java.util.TreeMap;
public final class FailoverGenerator extends UserDefinedGenerator {
private static final TreeMap<Integer, Palette<BlockData>> palette = new TreeMap<>();
static {
palette.put(255, new RandomPalette<BlockData>(new Random(2403)).add(Material.STONE.createBlockData(), 1));
}
public FailoverGenerator() throws ParseException {
super("0", null, new HashMap<>(), palette, new TreeMap<>(), new HashMap<>(), false);
}
}
@@ -57,7 +57,7 @@ public class TerraBiomeGrid extends BiomeGrid {
if(failNum % 256 == 0) if(failNum % 256 == 0)
LangUtil.log("error.severe-config", Level.SEVERE, String.valueOf(x), String.valueOf(z)); LangUtil.log("error.severe-config", Level.SEVERE, String.valueOf(x), String.valueOf(z));
failNum++; failNum++;
return ConfigUtil.failType.fail(); return null;
} }
if(erode != null && b.isErodible() && erode.isEroded(xp, zp)) { if(erode != null && b.isErodible() && erode.isEroded(xp, zp)) {
return erosionGrid.getBiome(xp, zp, phase); return erosionGrid.getBiome(xp, zp, phase);
@@ -3,7 +3,6 @@ package com.dfsek.terra.config.base;
import com.dfsek.terra.Debug; import com.dfsek.terra.Debug;
import com.dfsek.terra.Terra; import com.dfsek.terra.Terra;
import com.dfsek.terra.TerraWorld; import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.failsafe.FailType;
import com.dfsek.terra.config.exception.ConfigException; import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.util.TagUtil; import com.dfsek.terra.util.TagUtil;
@@ -23,7 +22,6 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
public final class ConfigUtil { public final class ConfigUtil {
@@ -31,7 +29,6 @@ public final class ConfigUtil {
public static long dataSave; // Period of population data saving, in ticks. public static long dataSave; // Period of population data saving, in ticks.
public static boolean masterDisableCaves; public static boolean masterDisableCaves;
public static int cacheSize; public static int cacheSize;
public static FailType failType;
public static void loadConfig(JavaPlugin main) { public static void loadConfig(JavaPlugin main) {
main.saveDefaultConfig(); main.saveDefaultConfig();
@@ -54,14 +51,6 @@ public final class ConfigUtil {
} }
} }
String fail = config.getString("fail-type", "SHUTDOWN");
try {
failType = FailType.valueOf(fail);
} catch(IllegalArgumentException e) {
LangUtil.log("config.invalid-failover", Level.SEVERE, fail);
}
Logger logger = main.getLogger(); Logger logger = main.getLogger();
logger.info("Loading config values"); logger.info("Loading config values");
@@ -9,7 +9,6 @@ import com.dfsek.terra.config.exception.ConfigException;
import com.dfsek.terra.config.exception.NotFoundException; import com.dfsek.terra.config.exception.NotFoundException;
import com.dfsek.terra.config.genconfig.structure.StructureConfig; import com.dfsek.terra.config.genconfig.structure.StructureConfig;
import com.dfsek.terra.generation.UserDefinedDecorator; import com.dfsek.terra.generation.UserDefinedDecorator;
import com.dfsek.terra.generation.UserDefinedGenerator;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.InvalidConfigurationException;
import org.polydev.gaea.math.Range; import org.polydev.gaea.math.Range;
@@ -171,8 +170,7 @@ public class BiomeConfig extends TerraConfig {
try { try {
// Get UserDefinedBiome instance representing this config. // Get UserDefinedBiome instance representing this config.
UserDefinedGenerator gen = new UserDefinedGenerator(eq, elevation, config.getDefinedVariables(), palette.getPaletteMap(), slant, config.getNoiseBuilders(), getBoolean("prevent-smooth", false)); GeneratorOptions gen = new GeneratorOptions(eq, elevation, config.getDefinedVariables(), palette.getPaletteMap(), slant, config.getNoiseBuilders(), getBoolean("prevent-smooth", false), doElevationInterpolation);
gen.setElevationInterpolation(doElevationInterpolation);
this.biome = new UserDefinedBiome(vanillaBiome, dec, gen, getBoolean("erodible", false), biomeID); this.biome = new UserDefinedBiome(vanillaBiome, dec, gen, getBoolean("erodible", false), biomeID);
} catch(ParseException e) { } catch(ParseException e) {
e.printStackTrace(); e.printStackTrace();
@@ -1,15 +1,11 @@
package com.dfsek.terra.generation; package com.dfsek.terra.config.genconfig.biome;
import com.dfsek.terra.config.genconfig.noise.NoiseConfig; import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
import com.dfsek.terra.generation.config.WorldGenerator; import com.dfsek.terra.generation.config.WorldGenerator;
import com.dfsek.terra.math.BlankFunction; import com.dfsek.terra.math.BlankFunction;
import com.dfsek.terra.util.DataUtil; import com.dfsek.terra.util.DataUtil;
import org.bukkit.World;
import org.bukkit.block.data.BlockData; import org.bukkit.block.data.BlockData;
import org.jetbrains.annotations.Nullable; 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 org.polydev.gaea.world.palette.Palette;
import parsii.eval.Parser; import parsii.eval.Parser;
import parsii.eval.Scope; import parsii.eval.Scope;
@@ -17,10 +13,10 @@ import parsii.tokenizer.ParseException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.UUID;
public class GeneratorOptions {
public class UserDefinedGenerator extends Generator { private final Map<Long, WorldGenerator> generators = new HashMap<>();
private final boolean preventSmooth; private final boolean preventSmooth;
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"}) @SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
@@ -34,11 +30,9 @@ public class UserDefinedGenerator extends Generator {
private final Map<String, Double> userVariables; private final Map<String, Double> userVariables;
private final Map<String, NoiseConfig> noiseBuilders; private final Map<String, NoiseConfig> noiseBuilders;
private final Map<UUID, WorldGenerator> gens = new HashMap<>(); private final boolean elevationInterpolation;
private boolean elevationInterpolation;
public GeneratorOptions(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, 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 { throws ParseException {
this.equation = equation; this.equation = equation;
this.elevationEquation = elevateEquation; this.elevationEquation = elevateEquation;
@@ -77,74 +71,11 @@ public class UserDefinedGenerator extends Generator {
} }
slantPalettes[y] = slantPalette; 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; this.elevationInterpolation = elevationInterpolation;
} }
public WorldGenerator getGenerator(long seed) {
return generators.computeIfAbsent(seed, s -> new WorldGenerator(seed, equation, elevationEquation, userVariables, noiseBuilders, palettes, slantPalettes, preventSmooth)
.setElevationInterpolation(elevationInterpolation));
}
} }
@@ -3,7 +3,6 @@ package com.dfsek.terra.generation;
import com.dfsek.terra.config.genconfig.noise.NoiseConfig; import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
import com.dfsek.terra.math.NoiseFunction2; import com.dfsek.terra.math.NoiseFunction2;
import com.dfsek.terra.math.NoiseFunction3; import com.dfsek.terra.math.NoiseFunction3;
import org.bukkit.World;
import parsii.eval.Expression; import parsii.eval.Expression;
import parsii.eval.Parser; import parsii.eval.Parser;
import parsii.eval.Scope; import parsii.eval.Scope;
@@ -19,7 +18,7 @@ public class ElevationEquation {
private final Variable xVar = s.getVariable("x"); private final Variable xVar = s.getVariable("x");
private final Variable zVar = s.getVariable("z"); 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()) { for(Map.Entry<String, Double> entry : userVariables.entrySet()) {
s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables. 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()) { for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
switch(e.getValue().getDimensions()) { switch(e.getValue().getDimensions()) {
case 2: case 2:
NoiseFunction2 function2 = new NoiseFunction2(w, e.getValue().getBuilder()); NoiseFunction2 function2 = new NoiseFunction2(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function2); p.registerFunction(e.getKey(), function2);
break; break;
case 3: case 3:
NoiseFunction3 function3 = new NoiseFunction3(w, e.getValue().getBuilder()); NoiseFunction3 function3 = new NoiseFunction3(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function3); p.registerFunction(e.getKey(), function3);
break; break;
} }
@@ -1,12 +1,13 @@
package com.dfsek.terra.generation; package com.dfsek.terra.generation;
import com.dfsek.terra.biome.grid.TerraBiomeGrid; import com.dfsek.terra.biome.grid.TerraBiomeGrid;
import com.dfsek.terra.generation.config.WorldGenerator;
import org.bukkit.World; import org.bukkit.World;
import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.generation.GenerationPhase;
import org.polydev.gaea.math.Interpolator; import org.polydev.gaea.math.Interpolator;
public class ElevationInterpolator { 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 double[][] values = new double[18][18];
private final int xOrigin; private final int xOrigin;
private final int zOrigin; private final int zOrigin;
@@ -19,13 +20,13 @@ public class ElevationInterpolator {
for(int x = -2; x < 8; x++) { for(int x = -2; x < 8; x++) {
for(int z = -2; z < 8; z++) { 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 x = -1; x <= 16; x++) {
for(byte z = -1; z <= 16; z++) { 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()) { if(compareGens((x / 4), (z / 4)) && generator.interpolateElevation()) {
Interpolator interpolator = new Interpolator(biomeAvg(x / 4, z / 4, w), Interpolator interpolator = new Interpolator(biomeAvg(x / 4, z / 4, w),
biomeAvg((x / 4) + 1, z / 4, w), biomeAvg((x / 4) + 1, z / 4, w),
@@ -38,16 +39,16 @@ public class ElevationInterpolator {
} }
} }
private UserDefinedGenerator getGenerator(int x, int z) { private WorldGenerator getGenerator(int x, int z) {
return (UserDefinedGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator(); 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]; return gens[x + 2][z + 2];
} }
private boolean compareGens(int x, int z) { 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 xi = x - 2; xi <= x + 2; xi++) {
for(int zi = z - 2; zi <= z + 2; zi++) { 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; + 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); if(g.getElevationEquation(w) != null) return g.getElevationEquation(w).getNoise(x, z);
return 0; return 0;
} }
@@ -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.BiomeConfig;
import com.dfsek.terra.config.genconfig.biome.BiomeSlabConfig; import com.dfsek.terra.config.genconfig.biome.BiomeSlabConfig;
import com.dfsek.terra.config.lang.LangUtil; 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.CavePopulator;
import com.dfsek.terra.population.FloraPopulator; import com.dfsek.terra.population.FloraPopulator;
import com.dfsek.terra.population.OrePopulator; 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) { 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) { if(slant != null) {
boolean north = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z + 1), z + 1) > 0; 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; boolean south = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z - 1), z - 1) > 0;
@@ -6,6 +6,11 @@ import com.dfsek.terra.generation.ElevationEquation;
import com.dfsek.terra.math.NoiseFunction2; import com.dfsek.terra.math.NoiseFunction2;
import com.dfsek.terra.math.NoiseFunction3; import com.dfsek.terra.math.NoiseFunction3;
import org.bukkit.World; 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.Expression;
import parsii.eval.Parser; import parsii.eval.Parser;
import parsii.eval.Scope; import parsii.eval.Scope;
@@ -14,29 +19,44 @@ import parsii.tokenizer.ParseException;
import java.util.Map; import java.util.Map;
public class WorldGenerator { public class WorldGenerator extends Generator {
private final ElevationEquation elevationEquation; 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 Expression noiseExp;
private final Scope s = new Scope(); private final Scope s = new Scope();
private final Variable xVar = s.getVariable("x"); private final Variable xVar = s.getVariable("x");
private final Variable yVar = s.getVariable("y"); private final Variable yVar = s.getVariable("y");
private final Variable zVar = s.getVariable("z"); 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()) { for(Map.Entry<String, Double> entry : userVariables.entrySet()) {
s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables. s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables.
} }
Parser p = new Parser(); Parser p = new Parser();
this.preventSmooth = preventSmooth;
this.palettes = palettes;
this.slantPalettes = slantPalettes;
for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) { for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
switch(e.getValue().getDimensions()) { switch(e.getValue().getDimensions()) {
case 2: case 2:
NoiseFunction2 function2 = new NoiseFunction2(w, e.getValue().getBuilder()); NoiseFunction2 function2 = new NoiseFunction2(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function2); p.registerFunction(e.getKey(), function2);
break; break;
case 3: case 3:
NoiseFunction3 function3 = new NoiseFunction3(w, e.getValue().getBuilder()); NoiseFunction3 function3 = new NoiseFunction3(seed, e.getValue().getBuilder());
p.registerFunction(e.getKey(), function3); p.registerFunction(e.getKey(), function3);
break; break;
} }
@@ -45,21 +65,68 @@ public class WorldGenerator {
this.noiseExp = p.parse(equation, s); this.noiseExp = p.parse(equation, s);
if(elevateEquation != null) { if(elevateEquation != null) {
Debug.info("Using elevation equation"); 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; } else this.elevationEquation = null;
} catch(ParseException e) { } catch(ParseException e) {
throw new IllegalArgumentException(); 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); xVar.setValue(x);
yVar.setValue(y); yVar.setValue(y);
zVar.setValue(z); zVar.setValue(z);
return noiseExp.evaluate(); 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; return elevationEquation;
} }
public boolean interpolateElevation() {
return elevationInterpolation;
}
public WorldGenerator setElevationInterpolation(boolean elevationInterpolation) {
this.elevationInterpolation = elevationInterpolation;
return this;
}
} }
@@ -2,7 +2,6 @@ package com.dfsek.terra.math;
import com.dfsek.terra.config.base.ConfigUtil; import com.dfsek.terra.config.base.ConfigUtil;
import com.dfsek.terra.generation.config.NoiseBuilder; import com.dfsek.terra.generation.config.NoiseBuilder;
import org.bukkit.World;
import org.polydev.gaea.math.FastNoiseLite; import org.polydev.gaea.math.FastNoiseLite;
import parsii.eval.Expression; import parsii.eval.Expression;
@@ -12,8 +11,8 @@ public class NoiseFunction2 implements NoiseFunction {
private final Cache cache = new Cache(); private final Cache cache = new Cache();
private final FastNoiseLite gen; private final FastNoiseLite gen;
public NoiseFunction2(World world, NoiseBuilder builder) { public NoiseFunction2(long seed, NoiseBuilder builder) {
this.gen = builder.build((int) world.getSeed()); this.gen = builder.build((int) seed);
} }
@Override @Override
@@ -1,7 +1,6 @@
package com.dfsek.terra.math; package com.dfsek.terra.math;
import com.dfsek.terra.generation.config.NoiseBuilder; import com.dfsek.terra.generation.config.NoiseBuilder;
import org.bukkit.World;
import org.polydev.gaea.math.FastNoiseLite; import org.polydev.gaea.math.FastNoiseLite;
import parsii.eval.Expression; import parsii.eval.Expression;
@@ -10,8 +9,8 @@ import java.util.List;
public class NoiseFunction3 implements NoiseFunction { public class NoiseFunction3 implements NoiseFunction {
private final FastNoiseLite gen; private final FastNoiseLite gen;
public NoiseFunction3(World world, NoiseBuilder builder) { public NoiseFunction3(long seed, NoiseBuilder builder) {
this.gen = builder.build((int) world.getSeed()); this.gen = builder.build((int) seed);
} }
@Override @Override
@@ -5,7 +5,7 @@ import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.base.ConfigPack; import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig; import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
import com.dfsek.terra.generation.ElevationEquation; import com.dfsek.terra.generation.ElevationEquation;
import com.dfsek.terra.generation.UserDefinedGenerator; import com.dfsek.terra.generation.config.WorldGenerator;
import org.bukkit.World; import org.bukkit.World;
import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.generation.GenerationPhase;
@@ -21,7 +21,7 @@ public class AirSpawn extends Requirement {
UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE); UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE);
BiomeConfig c = wc.getBiome(b); BiomeConfig c = wc.getBiome(b);
if(y <= c.getOcean().getSeaLevel()) return false; if(y <= c.getOcean().getSeaLevel()) return false;
ElevationEquation elevationEquation = ((UserDefinedGenerator) b.getGenerator()).getElevationEquation(getWorld()); ElevationEquation elevationEquation = ((WorldGenerator) b.getGenerator()).getElevationEquation(getWorld());
int yf = y - ((elevationEquation == null) ? 0 : (int) elevationEquation.getNoise(x, z)); int yf = y - ((elevationEquation == null) ? 0 : (int) elevationEquation.getNoise(x, z));
return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) <= 0; return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) <= 0;
} }
@@ -3,7 +3,7 @@ package com.dfsek.terra.structure.spawn;
import com.dfsek.terra.TerraWorld; import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.generation.ElevationEquation; import com.dfsek.terra.generation.ElevationEquation;
import com.dfsek.terra.generation.UserDefinedGenerator; import com.dfsek.terra.generation.config.WorldGenerator;
import org.bukkit.World; import org.bukkit.World;
import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.generation.GenerationPhase;
@@ -16,7 +16,7 @@ public class LandSpawn extends Requirement {
public boolean matches(int x, int y, int z) { public boolean matches(int x, int y, int z) {
TerraWorld tw = TerraWorld.getWorld(getWorld()); TerraWorld tw = TerraWorld.getWorld(getWorld());
UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE); UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE);
ElevationEquation elevationEquation = ((UserDefinedGenerator) b.getGenerator()).getElevationEquation(getWorld()); ElevationEquation elevationEquation = ((WorldGenerator) b.getGenerator()).getElevationEquation(getWorld());
int yf = y - ((elevationEquation == null) ? 0 : (int) elevationEquation.getNoise(x, z)); int yf = y - ((elevationEquation == null) ? 0 : (int) elevationEquation.getNoise(x, z));
return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) > 0; return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) > 0;
} }
@@ -4,7 +4,7 @@ import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.biome.UserDefinedBiome; import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.genconfig.biome.BiomeConfig; import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
import com.dfsek.terra.generation.ElevationEquation; import com.dfsek.terra.generation.ElevationEquation;
import com.dfsek.terra.generation.UserDefinedGenerator; import com.dfsek.terra.generation.config.WorldGenerator;
import org.bukkit.World; import org.bukkit.World;
import org.polydev.gaea.generation.GenerationPhase; import org.polydev.gaea.generation.GenerationPhase;
@@ -19,7 +19,7 @@ public class OceanSpawn extends Requirement {
UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE); UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE);
BiomeConfig c = tw.getConfig().getBiome(b); BiomeConfig c = tw.getConfig().getBiome(b);
if(y > c.getOcean().getSeaLevel()) return false; if(y > c.getOcean().getSeaLevel()) return false;
ElevationEquation elevationEquation = ((UserDefinedGenerator) b.getGenerator()).getElevationEquation(getWorld()); ElevationEquation elevationEquation = ((WorldGenerator) b.getGenerator()).getElevationEquation(getWorld());
int yf = y - ((elevationEquation == null) ? 0 : (int) elevationEquation.getNoise(x, z)); int yf = y - ((elevationEquation == null) ? 0 : (int) elevationEquation.getNoise(x, z));
return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) <= 0; return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) <= 0;
} }