completely redo noise config loading (mostly keeps parity with old configs)

This commit is contained in:
dfsek 2021-01-29 01:52:12 -07:00
parent dddf644c34
commit 02d61d0764
28 changed files with 261 additions and 181 deletions

View File

@ -1,8 +1,8 @@
package com.dfsek.terra.api.math.noise;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.util.hash.HashMapDoubleDouble;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import parsii.eval.Expression;
import java.util.List;
@ -11,8 +11,8 @@ public class NoiseFunction2 implements NoiseFunction {
private final NoiseSampler gen;
private final Cache cache = new Cache();
public NoiseFunction2(long seed, NoiseBuilder builder) {
this.gen = builder.build((int) seed);
public NoiseFunction2(long seed, NoiseSeeded builder) {
this.gen = builder.apply(seed);
}
@Override

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.api.math.noise;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import parsii.eval.Expression;
import java.util.List;
@ -9,8 +9,8 @@ import java.util.List;
public class NoiseFunction3 implements NoiseFunction {
private final NoiseSampler gen;
public NoiseFunction3(long seed, NoiseBuilder builder) {
this.gen = builder.build((int) seed);
public NoiseFunction3(long seed, NoiseSeeded builder) {
this.gen = builder.apply(seed);
}
@Override

View File

@ -32,6 +32,6 @@ public abstract class Normalizer implements NoiseSampler {
}
public enum NormalType {
LINEAR, NONE, NORMAL
LINEAR, NORMAL
}
}

View File

@ -3,7 +3,7 @@ package com.dfsek.terra.api.math.noise.samplers;
import com.dfsek.terra.api.math.noise.NoiseFunction2;
import com.dfsek.terra.api.math.noise.NoiseFunction3;
import com.dfsek.terra.api.math.parsii.RandomFunction;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import parsii.eval.Expression;
import parsii.eval.Parser;
import parsii.eval.Scope;
@ -21,7 +21,7 @@ public class ExpressionSampler implements NoiseSampler {
private final Variable y;
private final Variable z;
public ExpressionSampler(String equation, Scope parent, long seed, Map<String, NoiseBuilder> functions) throws ParseException {
public ExpressionSampler(String equation, Scope parent, long seed, Map<String, NoiseSeeded> functions) throws ParseException {
Parser parser = new Parser();
Scope scope = new Scope().withParent(parent);

View File

@ -9,14 +9,14 @@ public interface NoiseSampler {
* <p>
* Noise output bounded between -1...1
*/
double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y);
double getNoise(double x, double y);
/**
* 3D noise at given position using current settings
* <p>
* Noise output bounded between -1...1
*/
double getNoise(/*FNLdouble*/ double x, /*FNLdouble*/ double y, /*FNLdouble*/ double z);
double getNoise(double x, double y, double z);
default double getNoise(Vector3 vector3) {
return getNoise(vector3.getX(), vector3.getY(), vector3.getZ());

View File

@ -0,0 +1,10 @@
package com.dfsek.terra.api.util.seeded;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
public interface NoiseSeeded extends SeededBuilder<NoiseSampler> {
@Override
NoiseSampler apply(Long seed);
int getDimensions();
}

View File

@ -0,0 +1,7 @@
package com.dfsek.terra.api.util.seeded;
import java.util.function.Function;
public interface SeededBuilder<T> extends Function<Long, T> {
}

View File

@ -2,8 +2,8 @@ package com.dfsek.terra.biome.pipeline;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.stages.SeededBuilder;
import com.dfsek.terra.biome.pipeline.stages.Stage;
import java.util.List;
@ -51,7 +51,7 @@ public class BiomePipeline {
}
public BiomePipeline build(BiomeSource source, long seed) {
List<Stage> stagesBuilt = stages.stream().map(stageBuilder -> stageBuilder.build(seed)).collect(Collectors.toList());
List<Stage> stagesBuilt = stages.stream().map(stageBuilder -> stageBuilder.apply(seed)).collect(Collectors.toList());
for(Stage stage : stagesBuilt) {
if(stage.isExpansion()) expand = expand * 2 - 1;

View File

@ -1,15 +0,0 @@
package com.dfsek.terra.biome.pipeline.stages;
import java.util.function.Function;
public class SeededBuilder<T> {
private final Function<Long, T> builder;
public SeededBuilder(Function<Long, T> builder) {
this.builder = builder;
}
public T build(long seed) {
return builder.apply(seed);
}
}

View File

@ -4,10 +4,10 @@ import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomeHolder;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
@ -65,7 +65,7 @@ public class StandardBiomeProvider implements BiomeProvider {
private final TerraPlugin main;
private int resolution = 1;
private int noiseAmp = 2;
private NoiseBuilder builder = new NoiseBuilder();
private NoiseSeeded builder;
public StandardBiomeProviderBuilder(ExceptionalFunction<Long, BiomePipeline> pipelineBuilder, TerraPlugin main) {
this.pipelineBuilder = pipelineBuilder;
@ -76,7 +76,7 @@ public class StandardBiomeProvider implements BiomeProvider {
this.resolution = resolution;
}
public void setBlender(NoiseBuilder builder) {
public void setBlender(NoiseSeeded builder) {
this.builder = builder;
}
@ -87,7 +87,7 @@ public class StandardBiomeProvider implements BiomeProvider {
@Override
public StandardBiomeProvider build(long seed) {
try {
StandardBiomeProvider provider = new StandardBiomeProvider(pipelineBuilder.apply(seed), main, builder.build((int) seed), builder.build((int) (seed + 1)), noiseAmp);
StandardBiomeProvider provider = new StandardBiomeProvider(pipelineBuilder.apply(seed), main, builder.apply(seed), builder.apply((seed + 1)), noiseAmp);
provider.setResolution(resolution);
return provider;
} catch(ConfigException e) {

View File

@ -7,6 +7,8 @@ import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.loaders.MaterialSetLoader;
@ -14,14 +16,13 @@ import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.RangeLoader;
import com.dfsek.terra.config.loaders.config.FloraLayerLoader;
import com.dfsek.terra.config.loaders.config.GridSpawnLoader;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.config.loaders.config.OreConfigLoader;
import com.dfsek.terra.config.loaders.config.OreHolderLoader;
import com.dfsek.terra.config.loaders.config.TreeLayerLoader;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
import com.dfsek.terra.util.MaterialSet;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import com.dfsek.terra.world.population.items.flora.FloraLayer;
import com.dfsek.terra.world.population.items.flora.TerraFlora;
import com.dfsek.terra.world.population.items.ores.Ore;
@ -46,11 +47,18 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(FloraLayer.class, new FloraLayerLoader())
.registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf(o.toString()))
.registerLoader(OreConfig.class, new OreConfigLoader())
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
.registerLoader(TreeLayer.class, new TreeLayerLoader())
.registerLoader(MaterialSet.class, new MaterialSetLoader())
.registerLoader(OreHolder.class, new OreHolderLoader())
.registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object))
.registerLoader(FastNoiseLite.FractalType.class, (t, object, cf) -> FastNoiseLite.FractalType.valueOf((String) object))
.registerLoader(FastNoiseLite.DomainWarpType.class, (t, object, cf) -> FastNoiseLite.DomainWarpType.valueOf((String) object))
.registerLoader(FastNoiseLite.RotationType3D.class, (t, object, cf) -> FastNoiseLite.RotationType3D.valueOf((String) object))
.registerLoader(FastNoiseLite.CellularReturnType.class, (t, object, cf) -> FastNoiseLite.CellularReturnType.valueOf((String) object))
.registerLoader(FastNoiseLite.CellularDistanceFunction.class, (t, object, cf) -> FastNoiseLite.CellularDistanceFunction.valueOf((String) object))
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()))
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString()))
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()));
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()))
.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader());
}
}

View File

@ -3,9 +3,9 @@ package com.dfsek.terra.config.builder;
import com.dfsek.terra.api.math.noise.samplers.ConstantSampler;
import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.world.generation.WorldGenerator;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import parsii.eval.Scope;
import parsii.tokenizer.ParseException;
@ -24,7 +24,7 @@ public class GeneratorBuilder {
private Scope varScope;
private Map<String, NoiseBuilder> noiseBuilderMap;
private Map<String, NoiseSeeded> noiseBuilderMap;
private PaletteHolder palettes;
@ -34,7 +34,7 @@ public class GeneratorBuilder {
private boolean interpolateElevation;
private NoiseBuilder biomeNoise;
private NoiseSeeded biomeNoise;
private double elevationWeight;
@ -57,7 +57,7 @@ public class GeneratorBuilder {
} catch(ParseException e) {
throw new RuntimeException(e);
}
return new WorldGenerator(palettes, slantPalettes, noise, elevation, carving, biomeNoise.build((int) seed), elevationWeight, blendDistance, blendStep, blendWeight);
return new WorldGenerator(palettes, slantPalettes, noise, elevation, carving, biomeNoise.apply(seed), elevationWeight, blendDistance, blendStep, blendWeight);
});
}
}
@ -74,7 +74,7 @@ public class GeneratorBuilder {
this.blendDistance = blendDistance;
}
public void setBiomeNoise(NoiseBuilder biomeNoise) {
public void setBiomeNoise(NoiseSeeded biomeNoise) {
this.biomeNoise = biomeNoise;
}
@ -102,11 +102,7 @@ public class GeneratorBuilder {
this.varScope = varScope;
}
public Map<String, NoiseBuilder> getNoiseBuilderMap() {
return noiseBuilderMap;
}
public void setNoiseBuilderMap(Map<String, NoiseBuilder> noiseBuilderMap) {
public void setNoiseBuilderMap(Map<String, NoiseSeeded> noiseBuilderMap) {
this.noiseBuilderMap = noiseBuilderMap;
}

View File

@ -10,7 +10,7 @@ import com.dfsek.terra.config.templates.PaletteTemplate;
public class PaletteFactory implements TerraFactory<PaletteTemplate, Palette<BlockData>> {
@Override
public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) {
NoisePalette<BlockData> palette = new NoisePalette<>(config.getNoise().build(2403), config.getNoise().getDimensions() == 2);
NoisePalette<BlockData> palette = new NoisePalette<>(config.getNoise().apply(2403L), config.getNoise().getDimensions() == 2);
for(PaletteLayerHolder layer : config.getPalette()) {
palette.add(layer.getLayer(), layer.getSize(), layer.getSampler());
}

View File

@ -7,6 +7,7 @@ import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
@ -25,19 +26,19 @@ public class FloraLayerLoader implements TypeLoader<FloraLayer> {
if(range == null) throw new LoadException("Flora range unspecified");
ProbabilityCollection<Flora> items = (ProbabilityCollection<Flora>) configLoader.loadType(Types.FLORA_PROBABILITY_COLLECTION_TYPE, map.get("items"));
NoiseBuilder sampler;
NoiseSeeded sampler;
if(map.containsKey("distribution")) {
try {
sampler = new NoiseBuilderLoader().load(NoiseBuilder.class, map.get("distribution"), configLoader);
sampler = (NoiseSeeded) configLoader.loadType(NoiseSeeded.class, map.get("distribution"));
} catch(ConfigException e) {
throw new LoadException("Unable to load noise", e);
}
return new FloraLayer(density, range, items, sampler.build(2403));
return new FloraLayer(density, range, items, sampler.apply(2403L));
}
sampler = new NoiseBuilder();
sampler.setType(FastNoiseLite.NoiseType.WhiteNoise);
sampler.setDimensions(3);
NoiseBuilder def = new NoiseBuilder();
def.setType(FastNoiseLite.NoiseType.WhiteNoise);
def.setDimensions(3);
return new FloraLayer(density, range, items, sampler.build(2403));
return new FloraLayer(density, range, items, def.build(2403));
}
}

View File

@ -1,40 +0,0 @@
package com.dfsek.terra.config.loaders.config;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class NoiseBuilderLoader implements TypeLoader<NoiseBuilder> {
private static final ConfigLoader LOADER = new ConfigLoader();
static {
LOADER.registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object))
.registerLoader(FastNoiseLite.FractalType.class, (t, object, cf) -> FastNoiseLite.FractalType.valueOf((String) object))
.registerLoader(FastNoiseLite.DomainWarpType.class, (t, object, cf) -> FastNoiseLite.DomainWarpType.valueOf((String) object))
.registerLoader(FastNoiseLite.RotationType3D.class, (t, object, cf) -> FastNoiseLite.RotationType3D.valueOf((String) object))
.registerLoader(FastNoiseLite.CellularReturnType.class, (t, object, cf) -> FastNoiseLite.CellularReturnType.valueOf((String) object))
.registerLoader(FastNoiseLite.CellularDistanceFunction.class, (t, object, cf) -> FastNoiseLite.CellularDistanceFunction.valueOf((String) object))
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()));
}
@Override
public NoiseBuilder load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
NoiseBuilder builder = new NoiseBuilder();
try {
LOADER.load(builder, new Configuration((Map<String, Object>) o));
} catch(ConfigException e) {
throw new LoadException("Could not load noise", e);
}
return builder;
}
}

View File

@ -4,18 +4,17 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.stages.SeededBuilder;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.biome.provider.StandardBiomeProvider;
import com.dfsek.terra.config.fileloaders.Loader;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.registry.TerraRegistry;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
@ -65,7 +64,7 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
if(!pipeline.containsKey("source")) throw new LoadException("Biome Source not defined!");
SeededBuilder<BiomeSource> source = new SourceBuilderLoader().load(BiomeSource.class, pipeline.get("source"), loader);
BiomePipeline biomePipeline = pipelineBuilder.build(source.build(seed), seed);
BiomePipeline biomePipeline = pipelineBuilder.build(source.apply(seed), seed);
main.getDebugLogger().info("Biome Pipeline scale factor: " + biomePipeline.getSize());
return biomePipeline;
}, main);
@ -75,7 +74,7 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
Map<String, Object> blend = (Map<String, Object>) map.get("blend");
if(blend.containsKey("amplitude")) builder.setNoiseAmp(Integer.parseInt(blend.get("amplitude").toString()));
if(blend.containsKey("noise"))
builder.setBlender(new NoiseBuilderLoader().load(NoiseBuilder.class, blend.get("noise"), loader));
builder.setBlender((NoiseSeeded) loader.loadType(NoiseSeeded.class, blend.get("noise")));
}
return builder;
} else if(map.get("type").equals("IMAGE")) {

View File

@ -4,13 +4,12 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.source.RandomSource;
import com.dfsek.terra.biome.pipeline.stages.SeededBuilder;
import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import java.lang.reflect.Type;
import java.util.Map;
@ -25,8 +24,8 @@ public class SourceBuilderLoader implements TypeLoader<SeededBuilder<BiomeSource
if("NOISE".equals(type)) {
ProbabilityCollection<TerraBiome> sourceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, source.get("biomes"));
NoiseBuilder sourceNoise = new NoiseBuilderLoader().load(NoiseBuilder.class, source.get("noise"), loader);
return new SeededBuilder<>(seed -> new RandomSource(sourceBiomes, sourceNoise.build((int) seed.longValue())));
NoiseSeeded sourceNoise = (NoiseSeeded) loader.loadType(NoiseSeeded.class, source.get("noise"));
return seed -> new RandomSource(sourceBiomes, sourceNoise.apply(seed));
}
throw new LoadException("No such loader type: " + type);
}

View File

@ -4,6 +4,8 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.expand.FractalExpander;
import com.dfsek.terra.biome.pipeline.mutator.BorderListMutator;
@ -13,12 +15,9 @@ import com.dfsek.terra.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.biome.pipeline.stages.SeededBuilder;
import com.dfsek.terra.biome.pipeline.stages.Stage;
import com.dfsek.terra.config.loaders.SelfProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import java.lang.reflect.Type;
import java.util.HashMap;
@ -31,23 +30,23 @@ public class StageBuilderLoader implements TypeLoader<SeededBuilder<Stage>> {
Map.Entry<String, Object> entry = (Map.Entry<String, Object>) c;
Map<String, Object> mutator = (Map<String, Object>) entry.getValue();
NoiseBuilder mutatorNoise = new NoiseBuilderLoader().load(NoiseBuilder.class, mutator.get("noise"), loader);
NoiseSeeded mutatorNoise = (NoiseSeeded) loader.loadType(NoiseSeeded.class, mutator.get("noise"));
if(entry.getKey().equals("expand")) {
if(mutator.get("type").equals("FRACTAL"))
return new SeededBuilder<>(seed -> new ExpanderStage(new FractalExpander(mutatorNoise.build((int) seed.longValue()))));
return seed -> new ExpanderStage(new FractalExpander(mutatorNoise.apply(seed)));
else throw new LoadException("No such expander \"" + mutator.get("type"));
} else if(entry.getKey().equals("mutate")) {
switch(mutator.get("type").toString()) {
case "SMOOTH": {
return new SeededBuilder<>(seed -> new MutatorStage(new SmoothMutator(mutatorNoise.build((int) seed.longValue()))));
return seed -> new MutatorStage(new SmoothMutator(mutatorNoise.apply(new Long(seed))));
}
case "REPLACE": {
String fromTag = mutator.get("from").toString();
ProbabilityCollection<TerraBiome> replaceBiomes = new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("to"), loader);
return new SeededBuilder<>(seed -> new MutatorStage(new ReplaceMutator(fromTag, replaceBiomes, mutatorNoise.build((int) seed.longValue()))));
return seed -> new MutatorStage(new ReplaceMutator(fromTag, replaceBiomes, mutatorNoise.apply(seed)));
}
case "REPLACE_LIST": {
String fromTag = mutator.get("default-from").toString();
@ -58,14 +57,14 @@ public class StageBuilderLoader implements TypeLoader<SeededBuilder<Stage>> {
replace.put((TerraBiome) loader.loadType(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader));
}
return new SeededBuilder<>(seed -> new MutatorStage(new ReplaceListMutator(replace, fromTag, replaceBiomes, mutatorNoise.build((int) seed.longValue()))));
return seed -> new MutatorStage(new ReplaceListMutator(replace, fromTag, replaceBiomes, mutatorNoise.apply(seed)));
}
case "BORDER": {
String fromTag = mutator.get("from").toString();
String replaceTag = mutator.get("replace").toString();
ProbabilityCollection<TerraBiome> replaceBiomes = new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("to"), loader);
return new SeededBuilder<>(seed -> new MutatorStage(new BorderMutator(fromTag, replaceTag, mutatorNoise.build((int) seed.longValue()), replaceBiomes)));
return seed -> new MutatorStage(new BorderMutator(fromTag, replaceTag, mutatorNoise.apply(seed), replaceBiomes));
}
case "BORDER_LIST": {
String fromTag = mutator.get("from").toString();
@ -77,7 +76,7 @@ public class StageBuilderLoader implements TypeLoader<SeededBuilder<Stage>> {
replace.put((TerraBiome) loader.loadType(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader));
}
return new SeededBuilder<>(seed -> new MutatorStage(new BorderListMutator(replace, fromTag, replaceTag, mutatorNoise.build((int) seed.longValue()), replaceBiomes)));
return seed -> new MutatorStage(new BorderListMutator(replace, fromTag, replaceTag, mutatorNoise.apply(seed), replaceBiomes));
}
default:
throw new LoadException("No such mutator type \"" + mutator.get("type"));

View File

@ -0,0 +1,107 @@
package com.dfsek.terra.config.loaders.config.sampler;
import com.dfsek.tectonic.config.Configuration;
import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class NoiseSamplerBuilderLoader implements TypeLoader<NoiseSeeded> {
@Override
public NoiseSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException {
Map<String, Object> map = (Map<String, Object>) c;
String samplerType = "NOISE";
int dimensions = map.containsKey("dimensions")
? Integer.parseInt(map.get("dimensions").toString())
: 2;
if(map.containsKey("sampler-type")) {
samplerType = map.get("sampler-type").toString();
}
if(samplerType.equals("NOISE")) {
NoiseBuilder builder = new NoiseBuilder();
try {
loader.load(builder, new Configuration(map));
} catch(ConfigException e) {
throw new LoadException("Failed to load noise function", e);
}
return new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return builder.build(seed);
}
@Override
public int getDimensions() {
return dimensions;
}
};
} else if(samplerType.equals("NORMALIZER")) {
Normalizer.NormalType normalType = (Normalizer.NormalType) loader.loadType(Normalizer.NormalType.class, map.get("type"));
NoiseBuilder builder = new NoiseBuilder();
try {
loader.load(builder, new Configuration((Map<String, Object>) map.get("function")));
} catch(ConfigException e) {
throw new LoadException("Failed to load noise function", e);
}
switch(normalType) {
case LINEAR: {
if(!map.containsKey("max")) throw new LoadException("Max unspecified.");
if(!map.containsKey("min")) throw new LoadException("Min unspecified.");
int min = Integer.parseInt(map.get("min").toString());
int max = Integer.parseInt(map.get("max").toString());
return new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return new LinearNormalizer(builder.build(seed), min, max);
}
@Override
public int getDimensions() {
return dimensions;
}
};
}
case NORMAL: {
if(!map.containsKey("mean")) throw new LoadException("Mean unspecified.");
if(!map.containsKey("standard-deviation")) throw new LoadException("Standard Deviation unspecified.");
if(!map.containsKey("groups")) throw new LoadException("Groups unspecified.");
double mean = Double.parseDouble(map.get("mean").toString());
double stdDev = Double.parseDouble(map.get("standard-deviation").toString());
int groups = Integer.parseInt(map.get("groups").toString());
return new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return new NormalNormalizer(builder.build(seed), groups, mean, stdDev);
}
@Override
public int getDimensions() {
return dimensions;
}
};
}
}
}
throw new LoadException("No such noise sampler type \"" + samplerType + "\"");
}
}

View File

@ -0,0 +1,4 @@
package com.dfsek.terra.config.loaders.config.sampler;
public class NormalizerLoader {
}

View File

@ -6,10 +6,9 @@ import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.config.loaders.Types;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import java.lang.reflect.Type;
import java.util.Map;
@ -23,7 +22,7 @@ public class PaletteLayerLoader implements TypeLoader<PaletteLayerHolder> {
NoiseSampler sampler = null;
if(map.containsKey("noise")) {
sampler = new NoiseBuilderLoader().load(NoiseBuilder.class, map.get("noise"), configLoader).build(2403);
sampler = ((NoiseSeeded) configLoader.loadType(NoiseSeeded.class, map.get("noise"))).apply(2403L);
}
if(collection == null) throw new LoadException("Collection is null: " + map.get("materials"));

View File

@ -3,8 +3,8 @@ package com.dfsek.terra.config.pack;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import java.util.HashMap;
import java.util.Map;
@ -15,7 +15,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
private String id;
@Value("noise")
private Map<String, NoiseBuilder> noiseBuilderMap;
private Map<String, NoiseSeeded> noiseBuilderMap;
@Value("variables")
@Default
@ -112,7 +112,7 @@ public class ConfigPackTemplate implements ConfigTemplate {
return vanillaStructures;
}
public Map<String, NoiseBuilder> getNoiseBuilderMap() {
public Map<String, NoiseSeeded> getNoiseBuilderMap() {
return noiseBuilderMap;
}

View File

@ -8,11 +8,13 @@ import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.math.parsii.BlankFunction;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.world.Biome;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.SinglePalette;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
@ -69,7 +71,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Value("biome-noise")
@Default
@Abstractable
private NoiseBuilder biomeNoise = new NoiseBuilder();
private NoiseSeeded biomeNoise;
@Value("blend.distance")
@Abstractable
@ -224,11 +226,23 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
public BiomeTemplate(ConfigPack pack, TerraPlugin main) {
this.pack = pack;
biomeNoise.setType(FastNoiseLite.NoiseType.WhiteNoise);
NoiseBuilder builder = new NoiseBuilder();
builder.setType(FastNoiseLite.NoiseType.Constant);
biomeNoise = new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return builder.build(seed);
}
@Override
public int getDimensions() {
return 2;
}
};
oceanPalette = new SinglePalette<>(main.getWorldHandle().createBlockData("minecraft:water"));
}
public NoiseBuilder getBiomeNoise() {
public NoiseSeeded getBiomeNoise() {
return biomeNoise;
}

View File

@ -4,6 +4,8 @@ import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
@ -14,7 +16,7 @@ public class PaletteTemplate extends AbstractableTemplate {
@Value("noise")
@Abstractable
@Default
private NoiseBuilder noise = new NoiseBuilder();
private NoiseSeeded noise;
@Value("id")
private String id;
@ -24,8 +26,20 @@ public class PaletteTemplate extends AbstractableTemplate {
private List<PaletteLayerHolder> palette;
public PaletteTemplate() {
noise.setType(FastNoiseLite.NoiseType.WhiteNoise);
noise.setDimensions(3);
NoiseBuilder builder = new NoiseBuilder();
builder.setType(FastNoiseLite.NoiseType.WhiteNoise);
builder.setDimensions(3);
this.noise = new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return builder.build(seed);
}
@Override
public int getDimensions() {
return 3;
}
};
}
public String getID() {
@ -36,7 +50,7 @@ public class PaletteTemplate extends AbstractableTemplate {
return palette;
}
public NoiseBuilder getNoise() {
public NoiseSeeded getNoise() {
return noise;
}
}

View File

@ -3,11 +3,9 @@ package com.dfsek.terra.world.generation.config;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.NormalNormalizer;
import com.dfsek.terra.api.math.noise.normalizer.Normalizer;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings("FieldMayBeFinal")
public class NoiseBuilder implements ConfigTemplate {
@ -69,7 +67,7 @@ public class NoiseBuilder implements ConfigTemplate {
@Value("domain-warp.function")
@Default
private NoiseBuilder domainWarp;
private NoiseSeeded domainWarp;
@Value("rotation-type")
@Default
@ -81,31 +79,11 @@ public class NoiseBuilder implements ConfigTemplate {
@Value("cellular.lookup")
@Default
private NoiseBuilder lookup;
@Value("normalize.type")
@Default
private Normalizer.NormalType normalType = Normalizer.NormalType.NONE;
@Value("normalize.linear.min")
@Default
private double linearMin = -1D;
@Value("normalize.linear.max")
@Default
private double linearMax = 1D;
@Value("normalize.normal.mean")
@Default
private double mean = 0D;
@Value("normalize.normal.standard-deviation")
@Default
private double stdDev = 0.75D;
private NoiseSeeded lookup;
public NoiseSampler build(int seed) {
FastNoiseLite noise = new FastNoiseLite(seed + seedOffset);
public NoiseSampler build(long seed) {
FastNoiseLite noise = new FastNoiseLite((int) (seed + seedOffset));
if(!fractalType.equals(FastNoiseLite.FractalType.None)) {
noise.setFractalType(fractalType);
noise.setFractalOctaves(octaves);
@ -118,20 +96,18 @@ public class NoiseBuilder implements ConfigTemplate {
noise.setCellularDistanceFunction(cellularDistanceFunction);
noise.setCellularReturnType(cellularReturnType);
noise.setCellularJitter(cellularJitter);
if(lookup != null) noise.setCellularNoiseLookup(lookup.build(seed));
if(lookup != null) noise.setCellularNoiseLookup(lookup.apply(seed));
}
noise.setNoiseType(type);
noise.setDomainWarpType(domainWarpType);
noise.setDomainWarpAmp(domainWarpAmp);
if(domainWarp != null) noise.setDomainWarpFunction(domainWarp.build(seed));
if(domainWarp != null) noise.setDomainWarpFunction(domainWarp.apply(seed));
noise.setRotationType3D(rotationType3D);
noise.setFrequency(frequency);
if(normalType.equals(Normalizer.NormalType.LINEAR)) return new LinearNormalizer(noise, linearMin, linearMax);
else if(normalType.equals(Normalizer.NormalType.NORMAL)) return new NormalNormalizer(noise, 16384, mean, stdDev);
return noise;
}

View File

@ -16,7 +16,6 @@ import com.dfsek.terra.biome.pipeline.source.BiomeSource;
import com.dfsek.terra.biome.pipeline.source.RandomSource;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.biome.pipeline.stages.SeededBuilder;
import com.dfsek.terra.biome.provider.BiomeProvider;
import com.dfsek.terra.biome.provider.StandardBiomeProvider;
import org.junit.jupiter.api.Test;
@ -64,20 +63,20 @@ public class BiomeTest {
BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> new BiomePipeline.BiomePipelineBuilder(2)
.addStage(new SeededBuilder<>(s -> new MutatorStage(new ReplaceMutator("LAND_TEMP", landBiomes, whiteNoise(243)))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(2)))))
.addStage(new SeededBuilder<>(s -> new MutatorStage(new ReplaceMutator("OCEAN_TEMP", oceanBiomes, whiteNoise(243)))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(2)))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(2)))))
.addStage(new SeededBuilder<>(s -> new MutatorStage(new SmoothMutator(whiteNoise(3)))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(4)))))
.addStage(new SeededBuilder<>(s -> new MutatorStage(new SmoothMutator(whiteNoise(6)))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(4)))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(4)))))
.addStage(new SeededBuilder<>(s -> new MutatorStage(new BorderMutator("OCEAN", "LAND", whiteNoise(1234), beachBiomes))))
.addStage(new SeededBuilder<>(s -> new ExpanderStage(new FractalExpander(whiteNoise(4)))))
.addStage(new SeededBuilder<>(s -> new MutatorStage(new SmoothMutator(whiteNoise(6)))))
.addStage(new SeededBuilder<>(s -> new MutatorStage(new SmoothMutator(whiteNoise(6)))))
.addStage(s -> new MutatorStage(new ReplaceMutator("LAND_TEMP", landBiomes, whiteNoise(243))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(2))))
.addStage(s -> new MutatorStage(new ReplaceMutator("OCEAN_TEMP", oceanBiomes, whiteNoise(243))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(2))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(2))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(3))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(6))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new MutatorStage(new BorderMutator("OCEAN", "LAND", whiteNoise(1234), beachBiomes)))
.addStage(s -> new ExpanderStage(new FractalExpander(whiteNoise(4))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(6))))
.addStage(s -> new MutatorStage(new SmoothMutator(whiteNoise(6))))
.build(source, seed), null).build(0);

View File

@ -2,15 +2,15 @@ package noise;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
@SuppressWarnings("unused")
public class NoiseConfigTemplate implements ConfigTemplate {
@Value(".")
private NoiseBuilder builder;
private NoiseSeeded builder;
public NoiseBuilder getBuilder() {
public NoiseSeeded getBuilder() {
return builder;
}
}

View File

@ -4,9 +4,10 @@ import com.dfsek.tectonic.exception.ConfigException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.config.GenericLoaders;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.config.NoiseBuilderLoader;
import com.dfsek.terra.world.generation.config.NoiseBuilder;
import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader;
import org.apache.commons.io.FileUtils;
import javax.swing.*;
@ -90,8 +91,10 @@ public class NoiseTool {
long s = System.nanoTime();
ConfigLoader loader = new ConfigLoader();
loader.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader())
.registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader());
new GenericLoaders(null).register(loader);
NoiseConfigTemplate template = new NoiseConfigTemplate();
File file = new File("./config.yml");
@ -117,7 +120,7 @@ public class NoiseTool {
ProbabilityCollection<Integer> colorCollection = color.getColors();
loader.load(template, new FileInputStream(file));
NoiseSampler noise = template.getBuilder().build(seed);
NoiseSampler noise = template.getBuilder().apply((long) seed);
int size = 1024;
@ -132,7 +135,7 @@ public class NoiseTool {
for(int x = 0; x < noiseVals.length; x++) {
for(int z = 0; z < noiseVals[x].length; z++) {
double n = template.getBuilder().getDimensions() == 2 ? noise.getNoise(x, z) : noise.getNoise(x, 0, z);
double n = noise.getNoise(x, z);
noiseVals[x][z] = n;
max = Math.max(n, max);
min = Math.min(n, min);