diff --git a/build.gradle.kts b/build.gradle.kts index bd43d96b8..8ae1e205f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,6 @@ import com.dfsek.terra.getGitHash -val versionObj = Version("4", "0", "1", true) +val versionObj = Version("4", "1", "0", true) allprojects { version = versionObj diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 94fec69e3..38d982bca 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -13,10 +13,11 @@ dependencies { "shadedApi"("org.apache.commons:commons-rng-core:1.3") "shadedApi"("commons-io:commons-io:2.4") - "shadedApi"("com.scireum:parsii:1.2.1") + "shadedApi"("com.dfsek:Paralithic:0.3.2") "shadedApi"("com.dfsek:Tectonic:1.2.3") "shadedApi"("net.jafama:jafama:2.3.2") "shadedApi"("org.yaml:snakeyaml:1.27") + "shadedApi"("org.ow2.asm:asm:9.0") "compileOnly"("com.googlecode.json-simple:json-simple:1.1") diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ClampNormalizer.java b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ClampNormalizer.java new file mode 100644 index 000000000..dee3ddfd8 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ClampNormalizer.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.api.math.noise.normalizer; + +import com.dfsek.terra.api.math.noise.NoiseSampler; +import net.jafama.FastMath; + +public class ClampNormalizer extends Normalizer { + private final double min; + private final double max; + + public ClampNormalizer(NoiseSampler sampler, double min, double max) { + super(sampler); + this.min = min; + this.max = max; + } + + @Override + public double normalize(double in) { + return FastMath.max(FastMath.min(in, max), min); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ExpressionNormalizer.java b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ExpressionNormalizer.java new file mode 100644 index 000000000..a5d603abf --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/ExpressionNormalizer.java @@ -0,0 +1,33 @@ +package com.dfsek.terra.api.math.noise.normalizer; + +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.parsii.noise.NoiseFunction2; +import com.dfsek.terra.api.math.parsii.noise.NoiseFunction3; + +import java.util.Map; + +public class ExpressionNormalizer extends Normalizer { + private final Expression expression; + + public ExpressionNormalizer(NoiseSampler sampler, String eq, Map vars) throws ParseException { + super(sampler); + Parser p = new Parser(); + Scope scope = new Scope(); + scope.addInvocationVariable("in"); + + vars.forEach(scope::create); + + p.registerFunction("super2", new NoiseFunction2(sampler)); + p.registerFunction("super3", new NoiseFunction3(sampler)); + expression = p.parse(eq); + } + + @Override + public double normalize(double in) { + return expression.evaluate(in); + } +} diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java index 1ac1d6067..19967130c 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/normalizer/Normalizer.java @@ -30,8 +30,4 @@ public abstract class Normalizer implements NoiseSampler { public double getNoiseSeeded(int seed, double x, double y, double z) { return normalize(sampler.getNoiseSeeded(seed, x, y, z)); } - - public enum NormalType { - LINEAR, NORMAL - } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java index 003f692dd..b400caa72 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java +++ b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java @@ -1,73 +1,58 @@ package com.dfsek.terra.api.math.noise.samplers; +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.parsii.defined.UserDefinedFunction; import com.dfsek.terra.api.math.parsii.noise.NoiseFunction2; import com.dfsek.terra.api.math.parsii.noise.NoiseFunction3; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import parsii.eval.Expression; -import parsii.eval.Parser; -import parsii.eval.Scope; -import parsii.eval.Variable; -import parsii.tokenizer.ParseException; -import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * Sampler implementation using parsii expression */ public class ExpressionSampler implements NoiseSampler { private final Expression expression; - private final Variable x; - private final Variable y; - private final Variable z; public ExpressionSampler(String equation, Scope parent, long seed, Map functions, Map definedFunctions) throws ParseException { Parser parser = new Parser(); Scope scope = new Scope().withParent(parent); - this.x = scope.create("x"); - this.y = scope.create("y"); - this.z = scope.create("z"); + scope.addInvocationVariable("x"); + scope.addInvocationVariable("y"); + scope.addInvocationVariable("z"); functions.forEach((id, noise) -> { switch(noise.getDimensions()) { case 2: - parser.registerFunction(id, new NoiseFunction2(seed, noise)); + parser.registerFunction(id, new NoiseFunction2(noise.apply(seed))); break; case 3: - parser.registerFunction(id, new NoiseFunction3(seed, noise)); + parser.registerFunction(id, new NoiseFunction3(noise.apply(seed))); break; } }); for(Map.Entry entry : definedFunctions.entrySet()) { - String id = entry.getKey(); - FunctionTemplate fun = entry.getValue(); - - Scope functionScope = new Scope().withParent(parent); - List variables = fun.getArgs().stream().map(functionScope::create).collect(Collectors.toList()); - - parser.registerFunction(id, new UserDefinedFunction(parser.parse(fun.getFunction(), functionScope), variables)); + parser.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), parser, parent)); } this.expression = parser.parse(equation, scope); } @Override - public synchronized double getNoise(double x, double y) { + public double getNoise(double x, double y) { return getNoise(x, 0, y); } @Override - public synchronized double getNoise(double x, double y, double z) { - this.x.setValue(x); - this.y.setValue(y); - this.z.setValue(z); - return expression.evaluate(); + public double getNoise(double x, double y, double z) { + return expression.evaluate(x, y, z); } @Override diff --git a/common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java index a95ebc971..b506b8323 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/BlankFunction.java @@ -1,11 +1,9 @@ package com.dfsek.terra.api.math.parsii; -import parsii.eval.Expression; -import parsii.eval.Function; -import java.util.List; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; -public class BlankFunction implements Function { +public class BlankFunction implements DynamicFunction { private final int args; public BlankFunction(int args) { @@ -13,17 +11,17 @@ public class BlankFunction implements Function { } @Override - public int getNumberOfArguments() { + public int getArgNumber() { return args; } @Override - public double eval(List list) { + public double eval(double... d) { return 0; } @Override - public boolean isNaturalFunction() { + public boolean isStateless() { return true; } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/parsii/defined/UserDefinedFunction.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/defined/UserDefinedFunction.java index d9e670683..020f5c8ef 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/parsii/defined/UserDefinedFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/defined/UserDefinedFunction.java @@ -1,35 +1,44 @@ package com.dfsek.terra.api.math.parsii.defined; -import parsii.eval.Expression; -import parsii.eval.Function; -import parsii.eval.Variable; +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; +import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import java.util.List; -public class UserDefinedFunction implements Function { +public class UserDefinedFunction implements DynamicFunction { private final Expression expression; - private final List variables; + private final int args; - public UserDefinedFunction(Expression expression, List variables) { + protected UserDefinedFunction(Expression expression, int args) { this.expression = expression; - this.variables = variables; + this.args = args; + } + + + @Override + public double eval(double... args) { + return expression.evaluate(args); } @Override - public int getNumberOfArguments() { - return variables.size(); - } - - @Override - public synchronized double eval(List args) { - for(int i = 0; i < variables.size(); i++) { - variables.get(i).setValue(args.get(i).evaluate()); - } - return expression.evaluate(); - } - - @Override - public boolean isNaturalFunction() { + public boolean isStateless() { return true; } + + @Override + public int getArgNumber() { + return args; + } + + public static UserDefinedFunction newInstance(FunctionTemplate template, Parser parser, Scope parent) throws ParseException { + + Scope functionScope = new Scope().withParent(parent); + + template.getArgs().forEach(functionScope::addInvocationVariable); + + return new UserDefinedFunction(parser.parse(template.getFunction(), functionScope), template.getArgs().size()); + } } diff --git a/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction.java index 107a86536..6da1dd45b 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction.java @@ -1,6 +1,7 @@ package com.dfsek.terra.api.math.parsii.noise; -import parsii.eval.Function; -public interface NoiseFunction extends Function { +import com.dfsek.paralithic.functions.dynamic.DynamicFunction; + +public interface NoiseFunction extends DynamicFunction { } diff --git a/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction2.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction2.java index 3a97fb256..37a623d91 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction2.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction2.java @@ -1,42 +1,30 @@ package com.dfsek.terra.api.math.parsii.noise; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.util.hash.HashMapDoubleDouble; -import parsii.eval.Expression; -import java.util.List; + public class NoiseFunction2 implements NoiseFunction { private final NoiseSampler gen; private final Cache cache = new Cache(); - public NoiseFunction2(long seed, NoiseSeeded builder) { - this.gen = builder.apply(seed); + public NoiseFunction2(NoiseSampler gen) { + this.gen = gen; } @Override - public int getNumberOfArguments() { + public int getArgNumber() { return 2; } @Override - public double eval(List list) { - return cache.get(gen, list.get(0).evaluate(), list.get(1).evaluate()); - } - - /** - * Evaluate without cache. For testing. - * - * @param list Parameters. - * @return Result. - */ - public double evalNoCache(List list) { - return gen.getNoise(list.get(0).evaluate(), list.get(1).evaluate()); + public double eval(double... args) { + return cache.get(gen, args[0], args[1]); } @Override - public boolean isNaturalFunction() { + public boolean isStateless() { return true; } @@ -44,6 +32,10 @@ public class NoiseFunction2 implements NoiseFunction { private static final long serialVersionUID = 8915092734723467010L; private static final int cacheSize = 384; + public Cache() { + super(cacheSize); + } + public double get(NoiseSampler noise, double x, double z) { double xx = x >= 0 ? x * 2 : x * -2 - 1; double zz = z >= 0 ? z * 2 : z * -2 - 1; @@ -55,7 +47,7 @@ public class NoiseFunction2 implements NoiseFunction { return (value == 4.9E-324D ? addAndReturn(noise.getNoise(x, z), key) : value); } - private double addAndReturn(double value, double key) { + private synchronized double addAndReturn(double value, double key) { this.put(key, value); return value; } diff --git a/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction3.java b/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction3.java index 0f0e85edc..83c86aa29 100644 --- a/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction3.java +++ b/common/src/main/java/com/dfsek/terra/api/math/parsii/noise/NoiseFunction3.java @@ -1,30 +1,26 @@ package com.dfsek.terra.api.math.parsii.noise; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; -import parsii.eval.Expression; - -import java.util.List; public class NoiseFunction3 implements NoiseFunction { private final NoiseSampler gen; - public NoiseFunction3(long seed, NoiseSeeded builder) { - this.gen = builder.apply(seed); + public NoiseFunction3(NoiseSampler gen) { + this.gen = gen; } @Override - public int getNumberOfArguments() { + public int getArgNumber() { return 3; } @Override - public double eval(List list) { - return gen.getNoise(list.get(0).evaluate(), list.get(1).evaluate(), list.get(2).evaluate()); + public double eval(double... args) { + return gen.getNoise(args[0], args[1], args[2]); } @Override - public boolean isNaturalFunction() { + public boolean isStateless() { return true; } } diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java index e8a316fdc..ad1512ce3 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/StructureScript.java @@ -28,8 +28,8 @@ import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.structures.structure.buffer.Buffer; import com.dfsek.terra.api.structures.structure.buffer.DirectBuffer; import com.dfsek.terra.api.structures.structure.buffer.StructureBuffer; -import com.dfsek.terra.registry.LootRegistry; -import com.dfsek.terra.registry.ScriptRegistry; +import com.dfsek.terra.registry.config.LootRegistry; +import com.dfsek.terra.registry.config.ScriptRegistry; import com.dfsek.terra.world.generation.math.SamplerCache; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java index 140401a20..b2a39c92a 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/LootFunctionBuilder.java @@ -5,7 +5,7 @@ import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.script.functions.LootFunction; import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.LootRegistry; +import com.dfsek.terra.registry.config.LootRegistry; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java index b54004816..311cb4d1b 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/builders/StructureFunctionBuilder.java @@ -6,7 +6,7 @@ import com.dfsek.terra.api.structures.parser.lang.Returnable; import com.dfsek.terra.api.structures.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.api.structures.script.functions.StructureFunction; import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.ScriptRegistry; +import com.dfsek.terra.registry.config.ScriptRegistry; import java.util.List; import java.util.stream.Collectors; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java index e6363427f..5218f86a7 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/LootFunction.java @@ -12,7 +12,7 @@ import com.dfsek.terra.api.structures.script.TerraImplementationArguments; import com.dfsek.terra.api.structures.structure.RotationUtil; import com.dfsek.terra.api.structures.structure.buffer.items.BufferedLootApplication; import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.LootRegistry; +import com.dfsek.terra.registry.config.LootRegistry; import net.jafama.FastMath; import java.util.Map; diff --git a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java index 93c628e91..cd61d0ae0 100644 --- a/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java +++ b/common/src/main/java/com/dfsek/terra/api/structures/script/functions/StructureFunction.java @@ -13,7 +13,7 @@ import com.dfsek.terra.api.structures.structure.Rotation; import com.dfsek.terra.api.structures.structure.RotationUtil; import com.dfsek.terra.api.structures.structure.buffer.IntermediateBuffer; import com.dfsek.terra.api.structures.tokenizer.Position; -import com.dfsek.terra.registry.ScriptRegistry; +import com.dfsek.terra.registry.config.ScriptRegistry; import net.jafama.FastMath; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java new file mode 100644 index 000000000..e2a9e0e3c --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/seeded/SourceSeeded.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.util.seeded; + +import com.dfsek.terra.biome.pipeline.source.BiomeSource; + +public interface SourceSeeded extends SeededBuilder { +} diff --git a/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java b/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java new file mode 100644 index 000000000..c9754c22f --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/api/util/seeded/StageSeeded.java @@ -0,0 +1,6 @@ +package com.dfsek.terra.api.util.seeded; + +import com.dfsek.terra.biome.pipeline.stages.Stage; + +public interface StageSeeded extends SeededBuilder { +} diff --git a/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java b/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java index 988cbda77..a2bcb5df5 100644 --- a/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java +++ b/common/src/main/java/com/dfsek/terra/biome/pipeline/BiomePipeline.java @@ -2,7 +2,7 @@ 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.api.util.seeded.StageSeeded; import com.dfsek.terra.biome.pipeline.source.BiomeSource; import com.dfsek.terra.biome.pipeline.stages.Stage; @@ -42,7 +42,7 @@ public class BiomePipeline { public static final class BiomePipelineBuilder { private final int init; - List> stages = new GlueList<>(); + List stages = new GlueList<>(); private int expand; public BiomePipelineBuilder(int init) { @@ -60,7 +60,7 @@ public class BiomePipeline { return new BiomePipeline(source, stagesBuilt, expand, init); } - public BiomePipelineBuilder addStage(SeededBuilder stage) { + public BiomePipelineBuilder addStage(StageSeeded stage) { stages.add(stage); return this; } diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java b/common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java index 3369a931a..9041edd85 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/biome/provider/BiomeProvider.java @@ -23,4 +23,8 @@ public interface BiomeProvider { interface BiomeProviderBuilder { BiomeProvider build(long seed); } + + enum Type { + IMAGE, PIPELINE, SINGLE + } } diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java b/common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java index 50cbd137c..2f2a6467e 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/biome/provider/ImageBiomeProvider.java @@ -9,14 +9,16 @@ import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Map; -public class ImageBiomeProvider implements BiomeProvider { +public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder. private final Map colorBiomeMap = new HashMap<>(); private final BufferedImage image; private final int resolution; + private final Align align; - public ImageBiomeProvider(TerraRegistry registry, BufferedImage image, int resolution) { + public ImageBiomeProvider(TerraRegistry registry, BufferedImage image, int resolution, Align align) { this.image = image; this.resolution = resolution; + this.align = align; registry.forEach(biome -> colorBiomeMap.put(new Color(biome.getColor()), biome)); } @@ -26,7 +28,9 @@ public class ImageBiomeProvider implements BiomeProvider { @Override public TerraBiome getBiome(int x, int z) { - Color color = new Color(image.getRGB(FastMath.floorMod(x / resolution, image.getWidth()), FastMath.floorMod(z / resolution, image.getHeight()))); + x /= resolution; + z /= resolution; + Color color = align.getColor(image, x, z); return colorBiomeMap.get(colorBiomeMap.keySet().stream().reduce(colorBiomeMap.keySet().stream().findAny().orElseThrow(IllegalStateException::new), (running, element) -> { int d1 = distance(color, running); int d2 = distance(color, element); @@ -34,20 +38,24 @@ public class ImageBiomeProvider implements BiomeProvider { })); } - public static class ImageBiomeProviderBuilder implements BiomeProviderBuilder { - private final BufferedImage image; - private final int resolution; - private final TerraRegistry registry; + @Override + public BiomeProvider build(long seed) { + return this; + } - public ImageBiomeProviderBuilder(BufferedImage image, int resolution, TerraRegistry registry) { - this.image = image; - this.resolution = resolution; - this.registry = registry; - } + public enum Align { + CENTER { + @Override + public Color getColor(BufferedImage image, int x, int z) { + return new Color(image.getRGB(FastMath.floorMod(x - image.getWidth() / 2, image.getWidth()), FastMath.floorMod(z - image.getHeight() / 2, image.getHeight()))); + } + }, NONE { + @Override + public Color getColor(BufferedImage image, int x, int z) { + return new Color(image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(z, image.getHeight()))); + } + }; - @Override - public BiomeProvider build(long seed) { - return new ImageBiomeProvider(registry, image, resolution); - } + public abstract Color getColor(BufferedImage image, int x, int z); } } diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java b/common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java index 8ede312a1..1119788f6 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/biome/provider/SingleBiomeProvider.java @@ -2,7 +2,7 @@ package com.dfsek.terra.biome.provider; import com.dfsek.terra.biome.TerraBiome; -public class SingleBiomeProvider implements BiomeProvider { +public class SingleBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { private final TerraBiome biome; public SingleBiomeProvider(TerraBiome biome) { @@ -14,5 +14,8 @@ public class SingleBiomeProvider implements BiomeProvider { return biome; } - + @Override + public BiomeProvider build(long seed) { + return this; + } } diff --git a/common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java b/common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java index 8501ac094..f54c3c287 100644 --- a/common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java +++ b/common/src/main/java/com/dfsek/terra/biome/provider/StandardBiomeProvider.java @@ -1,10 +1,8 @@ package com.dfsek.terra.biome.provider; -import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.math.noise.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; @@ -17,12 +15,13 @@ import org.jetbrains.annotations.NotNull; public class StandardBiomeProvider implements BiomeProvider { private final LoadingCache holderCache; private final BiomePipeline pipeline; - private int resolution = 1; + private final int resolution; private final NoiseSampler mutator; private final double noiseAmp; private final int seed; - protected StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main, NoiseSampler mutator, double noiseAmp, int seed) { + public StandardBiomeProvider(BiomePipeline pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp, int seed) { + this.resolution = resolution; this.mutator = mutator; this.noiseAmp = noiseAmp; this.seed = seed; @@ -53,52 +52,4 @@ public class StandardBiomeProvider implements BiomeProvider { int fdZ = FastMath.floorDiv(z, pipeline.getSize()); return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize()); } - - public int getResolution() { - return resolution; - } - - public void setResolution(int resolution) { - this.resolution = resolution; - } - - public interface ExceptionalFunction { - O apply(I in) throws ConfigException; - } - - public static final class StandardBiomeProviderBuilder implements BiomeProviderBuilder { - private final ExceptionalFunction pipelineBuilder; - private final TerraPlugin main; - private int resolution = 1; - private double noiseAmp = 2; - private NoiseSeeded builder; - - public StandardBiomeProviderBuilder(ExceptionalFunction pipelineBuilder, TerraPlugin main) { - this.pipelineBuilder = pipelineBuilder; - this.main = main; - } - - public void setResolution(int resolution) { - this.resolution = resolution; - } - - public void setBlender(NoiseSeeded builder) { - this.builder = builder; - } - - public void setNoiseAmp(double noiseAmp) { - this.noiseAmp = noiseAmp; - } - - @Override - public StandardBiomeProvider build(long seed) { - try { - StandardBiomeProvider provider = new StandardBiomeProvider(pipelineBuilder.apply(seed), main, builder.apply(seed), noiseAmp, (int) seed); - provider.setResolution(resolution); - return provider; - } catch(ConfigException e) { - throw new RuntimeException(e); - } - } - } } diff --git a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java index d175ff4f2..75a645aa0 100644 --- a/common/src/main/java/com/dfsek/terra/carving/CarverCache.java +++ b/common/src/main/java/com/dfsek/terra/carving/CarverCache.java @@ -34,7 +34,6 @@ public class CarverCache { BiomeProvider provider = main.getWorld(w).getBiomeProvider(); if(CarverCache.this.carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + CarverCache.this.carver.hashCode())))) { long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed()); - CarverCache.this.carver.getSeedVar().setValue(seed); Random r = new FastRandom(seed); Worm carving = CarverCache.this.carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), CarverCache.this.carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16))); List points = new GlueList<>(); diff --git a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java index 5b550ec1d..9e48e4caf 100644 --- a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -1,5 +1,9 @@ package com.dfsek.terra.carving; +import com.dfsek.paralithic.Expression; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.math.Range; import com.dfsek.terra.api.math.parsii.defined.UserDefinedFunction; @@ -16,18 +20,12 @@ import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.CarverTemplate; import net.jafama.FastMath; -import parsii.eval.Expression; -import parsii.eval.Parser; -import parsii.eval.Scope; -import parsii.eval.Variable; -import parsii.tokenizer.ParseException; import java.util.List; import java.util.Map; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; -import java.util.stream.Collectors; public class UserDefinedCarver extends Carver { private final double[] start; // 0, 1, 2 = x, y, z. @@ -40,13 +38,6 @@ public class UserDefinedCarver extends Carver { private final Expression xRad; private final Expression yRad; private final Expression zRad; - private final Variable lengthVar; - private final Variable position; - private final Variable seedVar; - - private final Variable xOrigin; - private final Variable yOrigin; - private final Variable zOrigin; private final Map cacheMap = new ConcurrentHashMap<>(); private final TerraPlugin main; @@ -70,33 +61,28 @@ public class UserDefinedCarver extends Carver { functions.forEach((id, noise) -> { switch(noise.getDimensions()) { case 2: - p.registerFunction(id, new NoiseFunction2(hash, noise)); + p.registerFunction(id, new NoiseFunction2(noise.apply(hash))); break; case 3: - p.registerFunction(id, new NoiseFunction3(hash, noise)); + p.registerFunction(id, new NoiseFunction3(noise.apply(hash))); break; } }); for(Map.Entry entry : definedFunctions.entrySet()) { - String id = entry.getKey(); - FunctionTemplate fun = entry.getValue(); - - Scope functionScope = new Scope().withParent(parent); - List variables = fun.getArgs().stream().map(functionScope::create).collect(Collectors.toList()); - - p.registerFunction(id, new UserDefinedFunction(p.parse(fun.getFunction(), functionScope), variables)); + p.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), p, parent)); } Scope s = new Scope().withParent(parent); - lengthVar = s.create("length"); - position = s.create("position"); - seedVar = s.create("seed"); - xOrigin = s.create("x"); - yOrigin = s.create("y"); - zOrigin = s.create("z"); + s.addInvocationVariable("x"); + s.addInvocationVariable("y"); + s.addInvocationVariable("z"); + + s.addInvocationVariable("length"); + s.addInvocationVariable("position"); + s.addInvocationVariable("seed"); xRad = p.parse(radii.get(0), s); @@ -108,19 +94,7 @@ public class UserDefinedCarver extends Carver { @Override public Worm getWorm(long l, Vector3 vector) { Random r = new FastRandom(l + hash); - return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut); - } - - protected Variable getSeedVar() { - return seedVar; - } - - protected Variable getLengthVar() { - return lengthVar; - } - - protected Variable getPosition() { - return position; + return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut, l); } public void setStep(double step) { @@ -168,21 +142,21 @@ public class UserDefinedCarver extends Carver { private class UserDefinedWorm extends Worm { private final Vector3 direction; + private final Vector3 origin; private int steps; private int nextDirection = 0; private double[] currentRotation = new double[3]; + private final long seed; - public UserDefinedWorm(int length, Random r, Vector3 origin, int topCut, int bottomCut) { + public UserDefinedWorm(int length, Random r, Vector3 origin, int topCut, int bottomCut, long seed) { super(length, r, origin); + this.origin = origin; + this.seed = seed; super.setTopCut(topCut); super.setBottomCut(bottomCut); direction = new Vector3((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step); - position.setValue(0); - lengthVar.setValue(length); - xOrigin.setValue(origin.getX()); - yOrigin.setValue(origin.getY()); - zOrigin.setValue(origin.getZ()); - setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())}); + double[] args = {origin.getX(), origin.getY(), origin.getZ(), length, 0, seed}; + setRadius(new int[] {(int) (xRad.evaluate(args)), (int) (yRad.evaluate(args)), (int) (zRad.evaluate(args))}); } @Override @@ -191,7 +165,7 @@ public class UserDefinedCarver extends Carver { } @Override - public synchronized void step() { + public void step() { if(steps == nextDirection) { direction.rotateAroundX(FastMath.toRadians((getRandom().nextGaussian()) * mutate[0] * recalcMagnitude)); direction.rotateAroundY(FastMath.toRadians((getRandom().nextGaussian()) * mutate[1] * recalcMagnitude)); @@ -202,8 +176,8 @@ public class UserDefinedCarver extends Carver { nextDirection += recalc.get(getRandom()); } steps++; - position.setValue(steps); - setRadius(new int[] {(int) (xRad.evaluate()), (int) (yRad.evaluate()), (int) (zRad.evaluate())}); + double[] args = {origin.getX(), origin.getY(), origin.getZ(), getLength(), steps, seed}; + setRadius(new int[] {(int) (xRad.evaluate(args)), (int) (yRad.evaluate(args)), (int) (zRad.evaluate(args))}); direction.rotateAroundX(FastMath.toRadians(currentRotation[0] * mutate[0])); direction.rotateAroundY(FastMath.toRadians(currentRotation[1] * mutate[1])); direction.rotateAroundZ(FastMath.toRadians(currentRotation[2] * mutate[2])); diff --git a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java index 1b5c88e24..7d966680e 100644 --- a/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java +++ b/common/src/main/java/com/dfsek/terra/config/GenericLoaders.java @@ -6,14 +6,16 @@ import com.dfsek.terra.api.core.TerraPlugin; 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.math.noise.samplers.ImageSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.api.util.seeded.SourceSeeded; +import com.dfsek.terra.api.util.seeded.StageSeeded; import com.dfsek.terra.api.world.palette.holder.PaletteHolder; import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder; import com.dfsek.terra.biome.pipeline.stages.ExpanderStage; import com.dfsek.terra.biome.pipeline.stages.MutatorStage; +import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.biome.provider.ImageBiomeProvider; import com.dfsek.terra.carving.CarverPalette; import com.dfsek.terra.config.loaders.LinkedHashMapLoader; import com.dfsek.terra.config.loaders.MaterialSetLoader; @@ -24,6 +26,9 @@ import com.dfsek.terra.config.loaders.config.GridSpawnLoader; 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.biome.BiomeProviderBuilderLoader; +import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader; +import com.dfsek.terra.config.loaders.config.biome.StageBuilderLoader; import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; @@ -31,10 +36,10 @@ import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.Repla import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceMutatorTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.SmoothMutatorTemplate; import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; -import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; import com.dfsek.terra.config.loaders.config.sampler.templates.DomainWarpTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.ClampNormalizerTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate; import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader; @@ -75,8 +80,7 @@ public class GenericLoaders implements LoaderRegistrar { .registerLoader(DomainWarpTemplate.class, DomainWarpTemplate::new) .registerLoader(LinearNormalizerTemplate.class, LinearNormalizerTemplate::new) .registerLoader(NormalNormalizerTemplate.class, NormalNormalizerTemplate::new) - .registerLoader(FastNoiseTemplate.class, FastNoiseTemplate::new) - .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()) + .registerLoader(ClampNormalizerTemplate.class, ClampNormalizerTemplate::new) .registerLoader(ReplaceMutatorTemplate.class, ReplaceMutatorTemplate::new) .registerLoader(ExpanderStageTemplate.class, ExpanderStageTemplate::new) .registerLoader(SmoothMutatorTemplate.class, SmoothMutatorTemplate::new) @@ -86,7 +90,12 @@ public class GenericLoaders implements LoaderRegistrar { .registerLoader(FunctionTemplate.class, FunctionTemplate::new) .registerLoader(LinkedHashMap.class, new LinkedHashMapLoader()) .registerLoader(CarverPalette.class, new CarverPaletteLoader()) + .registerLoader(SourceSeeded.class, new SourceBuilderLoader()) + .registerLoader(StageSeeded.class, new StageBuilderLoader()) + .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) .registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object)) + .registerLoader(BiomeProvider.Type.class, (t, object, cf) -> BiomeProvider.Type.valueOf((String) object)) + .registerLoader(ImageBiomeProvider.Align.class, (t, object, cf) -> ImageBiomeProvider.Align.valueOf((String) object)) .registerLoader(ExpanderStage.Type.class, (t, object, cf) -> ExpanderStage.Type.valueOf((String) object)) .registerLoader(MutatorStage.Type.class, (t, object, cf) -> MutatorStage.Type.valueOf((String) object)) .registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object)) @@ -95,8 +104,6 @@ public class GenericLoaders implements LoaderRegistrar { .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(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString())); } } diff --git a/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java b/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java index 8ec4a5a5b..d64e9ef0c 100644 --- a/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java +++ b/common/src/main/java/com/dfsek/terra/config/builder/GeneratorBuilder.java @@ -1,5 +1,7 @@ package com.dfsek.terra.config.builder; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.terra.api.math.noise.NoiseSampler; import com.dfsek.terra.api.math.noise.samplers.ConstantSampler; import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler; @@ -7,8 +9,6 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.palette.holder.PaletteHolder; import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import com.dfsek.terra.world.generation.WorldGenerator; -import parsii.eval.Scope; -import parsii.tokenizer.ParseException; import java.util.Collections; import java.util.HashMap; diff --git a/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java index 4273d5fec..b4f09aa8c 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/BiomeFactory.java @@ -1,5 +1,6 @@ package com.dfsek.terra.config.factories; +import com.dfsek.paralithic.eval.parser.Scope; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.biome.TerraBiome; import com.dfsek.terra.biome.UserDefinedBiome; @@ -7,7 +8,6 @@ import com.dfsek.terra.config.builder.GeneratorBuilder; import com.dfsek.terra.config.loaders.config.function.FunctionTemplate; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.BiomeTemplate; -import parsii.eval.Scope; import java.util.LinkedHashMap; import java.util.Map; @@ -35,7 +35,7 @@ public class BiomeFactory implements TerraFactory { generatorBuilder.setSlantPalettes(template.getSlantPalette()); Scope vars = new Scope().withParent(pack.getVarScope()); - template.getVariables().forEach((id, val) -> vars.create(id).setValue(val)); + template.getVariables().forEach(vars::create); generatorBuilder.setVarScope(vars); generatorBuilder.setInterpolateElevation(template.interpolateElevation()); diff --git a/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java index dc38d1c05..19c16e47e 100644 --- a/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java +++ b/common/src/main/java/com/dfsek/terra/config/factories/CarverFactory.java @@ -1,12 +1,12 @@ package com.dfsek.terra.config.factories; +import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.math.MathUtil; import com.dfsek.terra.carving.UserDefinedCarver; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.CarverTemplate; -import parsii.tokenizer.ParseException; import java.util.Arrays; import java.util.List; diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java index ca585de34..d7f4d045f 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/BiomeProviderBuilderLoader.java @@ -3,94 +3,31 @@ package com.dfsek.terra.config.loaders.config.biome; 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.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.registry.TerraRegistry; +import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.IOException; import java.lang.reflect.Type; -import java.util.List; import java.util.Map; @SuppressWarnings("unchecked") public class BiomeProviderBuilderLoader implements TypeLoader { - private final TerraPlugin main; - private final TerraRegistry biomeRegistry; - private final Loader fileLoader; - public BiomeProviderBuilderLoader(TerraPlugin main, TerraRegistry biomeRegistry, Loader fileLoader) { - this.main = main; - this.biomeRegistry = biomeRegistry; - this.fileLoader = fileLoader; + public BiomeProviderBuilderLoader() { } @Override public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException { // TODO: clean this up Map map = (Map) c; - int resolution = (Integer) map.getOrDefault("resolution", 1); - if(map.get("type").equals("PIPELINE")) { - Map pipeline = (Map) map.get("pipeline"); - - List> stages = (List>) pipeline.get("stages"); - - if(stages == null) throw new LoadException("No pipeline stages defined!"); - - int init = (Integer) pipeline.getOrDefault("initial-size", 2); - - StandardBiomeProvider.StandardBiomeProviderBuilder builder = new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> { - BiomePipeline.BiomePipelineBuilder pipelineBuilder = new BiomePipeline.BiomePipelineBuilder(init); - - for(Map stage : stages) { - for(Map.Entry entry : stage.entrySet()) { - pipelineBuilder.addStage(new StageBuilderLoader().load(SeededBuilder.class, entry, loader)); - } - } - - if(!pipeline.containsKey("source")) throw new LoadException("Biome Source not defined!"); - SeededBuilder source = new SourceBuilderLoader().load(BiomeSource.class, pipeline.get("source"), loader); - - BiomePipeline biomePipeline = pipelineBuilder.build(source.apply(seed), seed); - main.getDebugLogger().info("Biome Pipeline scale factor: " + biomePipeline.getSize()); - return biomePipeline; - }, main); - - builder.setResolution(resolution); - if(map.containsKey("blend")) { - Map blend = (Map) map.get("blend"); - if(blend.containsKey("amplitude")) builder.setNoiseAmp(Double.parseDouble(blend.get("amplitude").toString())); - if(blend.containsKey("noise")) - builder.setBlender(loader.loadClass(NoiseSeeded.class, blend.get("noise"))); - } - return builder; - } else if(map.get("type").equals("IMAGE")) { - Map imageMap = (Map) map.get("image"); - try { - main.getLogger().info("Using image " + imageMap.get("name") + " for biome distribution."); - BufferedImage image = ImageIO.read(fileLoader.get(imageMap.get("name").toString())); - return new ImageBiomeProvider.ImageBiomeProviderBuilder(image, resolution, biomeRegistry); - } catch(IOException e) { - throw new LoadException("Failed to load image", e); - } - } else if(map.get("type").equals("SINGLE")) { - return seed -> { - try { - return new SingleBiomeProvider(loader.loadClass(TerraBiome.class, map.get("biome"))); - } catch(LoadException e) { - throw new RuntimeException(e); - } - }; + switch(loader.loadClass(BiomeProvider.Type.class, map.get("type"))) { + case IMAGE: + return loader.loadClass(ImageProviderTemplate.class, map); + case PIPELINE: + return loader.loadClass(BiomePipelineTemplate.class, map); + case SINGLE: + return loader.loadClass(SingleBiomeProviderTemplate.class, map); } throw new LoadException("No such biome provider type: " + map.get("type")); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java index 871cbb9f1..03a8d5527 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/SourceBuilderLoader.java @@ -5,9 +5,8 @@ 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.api.util.seeded.SourceSeeded; 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.config.loaders.Types; @@ -15,9 +14,9 @@ import java.lang.reflect.Type; import java.util.Map; @SuppressWarnings("unchecked") -public class SourceBuilderLoader implements TypeLoader> { +public class SourceBuilderLoader implements TypeLoader { @Override - public SeededBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException { + public SourceSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { Map source = (Map) c; String type = source.get("type").toString(); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java index 6cfd489ac..f173c1364 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/StageBuilderLoader.java @@ -3,10 +3,9 @@ package com.dfsek.terra.config.loaders.config.biome; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.tectonic.loading.TypeLoader; -import com.dfsek.terra.api.util.seeded.SeededBuilder; +import com.dfsek.terra.api.util.seeded.StageSeeded; import com.dfsek.terra.biome.pipeline.stages.ExpanderStage; import com.dfsek.terra.biome.pipeline.stages.MutatorStage; -import com.dfsek.terra.biome.pipeline.stages.Stage; import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate; import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate; @@ -18,33 +17,40 @@ import java.lang.reflect.Type; import java.util.Map; @SuppressWarnings("unchecked") -public class StageBuilderLoader implements TypeLoader> { +public class StageBuilderLoader implements TypeLoader { @Override - public SeededBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException { - Map.Entry entry = (Map.Entry) c; + public StageSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { + Map raw = (Map) c; + + if(raw.size() != 1) throw new LoadException("Illegal stage map size: " + raw.size()); + + Map.Entry entry = null; + + for(Map.Entry e : raw.entrySet()) { + entry = e; + } Map mutator = (Map) entry.getValue(); if(entry.getKey().equals("expand")) { ExpanderStage.Type stageType = loader.loadClass(ExpanderStage.Type.class, mutator.get("type")); if(stageType.equals(ExpanderStage.Type.FRACTAL)) { - return loader.loadClass(ExpanderStageTemplate.class, mutator).get(); + return loader.loadClass(ExpanderStageTemplate.class, mutator); } else throw new LoadException("No such expander \"" + stageType + "\""); } else if(entry.getKey().equals("mutate")) { switch(loader.loadClass(MutatorStage.Type.class, mutator.get("type"))) { case SMOOTH: - return loader.loadClass(SmoothMutatorTemplate.class, mutator).get(); + return loader.loadClass(SmoothMutatorTemplate.class, mutator); case REPLACE: - return loader.loadClass(ReplaceMutatorTemplate.class, mutator).get(); + return loader.loadClass(ReplaceMutatorTemplate.class, mutator); case REPLACE_LIST: - return loader.loadClass(ReplaceListMutatorTemplate.class, mutator).get(); + return loader.loadClass(ReplaceListMutatorTemplate.class, mutator); case BORDER: - return loader.loadClass(BorderMutatorTemplate.class, mutator).get(); + return loader.loadClass(BorderMutatorTemplate.class, mutator); case BORDER_LIST: - return loader.loadClass(BorderListMutatorTemplate.class, mutator).get(); + return loader.loadClass(BorderListMutatorTemplate.class, mutator); default: throw new LoadException("No such mutator type \"" + mutator.get("type")); - } } throw new LoadException("No such mutator \"" + entry.getKey() + "\""); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomePipelineTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomePipelineTemplate.java new file mode 100644 index 000000000..46d810866 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomePipelineTemplate.java @@ -0,0 +1,40 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.source; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.core.TerraPlugin; +import com.dfsek.terra.api.util.seeded.SourceSeeded; +import com.dfsek.terra.api.util.seeded.StageSeeded; +import com.dfsek.terra.biome.pipeline.BiomePipeline; +import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.biome.provider.StandardBiomeProvider; +import com.dfsek.terra.registry.config.BiomeRegistry; + +import java.util.List; + +@SuppressWarnings({"FieldMayBeFinal", "unused"}) +public class BiomePipelineTemplate extends BiomeProviderTemplate { + private final TerraPlugin main; + @Value("pipeline.initial-size") + @Default + private int initialSize = 2; + + @Value("pipeline.stages") + private List stages; + + @Value("pipeline.source") + private SourceSeeded source; + + public BiomePipelineTemplate(BiomeRegistry registry, TerraPlugin main) { + super(registry); + this.main = main; + } + + @Override + public BiomeProvider build(long seed) { + BiomePipeline.BiomePipelineBuilder biomePipelineBuilder = new BiomePipeline.BiomePipelineBuilder(initialSize); + stages.forEach(biomePipelineBuilder::addStage); + BiomePipeline pipeline = biomePipelineBuilder.build(source.apply(seed), seed); + return new StandardBiomeProvider(pipeline, main, resolution, blend.apply(seed), blendAmp, (int) seed); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomeProviderTemplate.java new file mode 100644 index 000000000..9e2d11d88 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/BiomeProviderTemplate.java @@ -0,0 +1,44 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.source; + +import com.dfsek.tectonic.annotations.Default; +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.loading.object.ObjectTemplate; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.noise.samplers.ConstantSampler; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; +import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.registry.config.BiomeRegistry; + +public abstract class BiomeProviderTemplate implements ObjectTemplate, BiomeProvider.BiomeProviderBuilder { + protected final BiomeRegistry registry; + @Value("resolution") + @Default + protected int resolution = 1; + @Value("blend.noise") + @Default + protected NoiseSeeded blend = new NoiseSeeded() { + @Override + public NoiseSampler apply(Long seed) { + return new ConstantSampler(0); + } + + @Override + public int getDimensions() { + return 2; + } + }; + @Value("blend.amplitude") + @Default + protected double blendAmp = 0d; + @Value("type") + BiomeProvider.Type type; + + protected BiomeProviderTemplate(BiomeRegistry registry) { + this.registry = registry; + } + + @Override + public BiomeProvider.BiomeProviderBuilder get() { + return this; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/ImageProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/ImageProviderTemplate.java new file mode 100644 index 000000000..e92379d7e --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/ImageProviderTemplate.java @@ -0,0 +1,25 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.source; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.biome.provider.ImageBiomeProvider; +import com.dfsek.terra.registry.config.BiomeRegistry; + +import java.awt.image.BufferedImage; + +public class ImageProviderTemplate extends BiomeProviderTemplate { + @Value("image.name") + private BufferedImage image; + + @Value("image.align") + private ImageBiomeProvider.Align align; + + public ImageProviderTemplate(BiomeRegistry registry) { + super(registry); + } + + @Override + public BiomeProvider build(long seed) { + return new ImageBiomeProvider(registry, image, resolution, align); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SingleBiomeProviderTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SingleBiomeProviderTemplate.java new file mode 100644 index 000000000..811656cd4 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/source/SingleBiomeProviderTemplate.java @@ -0,0 +1,21 @@ +package com.dfsek.terra.config.loaders.config.biome.templates.source; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.biome.provider.BiomeProvider; +import com.dfsek.terra.biome.provider.SingleBiomeProvider; +import com.dfsek.terra.registry.config.BiomeRegistry; + +public class SingleBiomeProviderTemplate extends BiomeProviderTemplate { + @Value("biome") + private TerraBiome biome; + + public SingleBiomeProviderTemplate(BiomeRegistry registry) { + super(registry); + } + + @Override + public BiomeProvider build(long seed) { + return new SingleBiomeProvider(biome); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java index 24103b9d0..041185648 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/biome/templates/stage/StageTemplate.java @@ -4,14 +4,15 @@ import com.dfsek.tectonic.annotations.Value; import com.dfsek.tectonic.loading.object.ObjectTemplate; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.util.seeded.SeededBuilder; +import com.dfsek.terra.api.util.seeded.StageSeeded; import com.dfsek.terra.biome.pipeline.stages.Stage; -public abstract class StageTemplate implements ObjectTemplate>, SeededBuilder { +public abstract class StageTemplate implements ObjectTemplate>, StageSeeded { @Value("noise") protected NoiseSeeded noise; @Override - public SeededBuilder get() { + public StageSeeded get() { return this; } } diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java index 20a01061d..a44d3135e 100644 --- a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java @@ -1,21 +1,27 @@ 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.Normalizer; import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.config.loaders.config.sampler.templates.DomainWarpTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate; import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate; -import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalizerTemplate; +import com.dfsek.terra.registry.config.NormalizerRegistry; import java.lang.reflect.Type; import java.util.Map; @SuppressWarnings("unchecked") public class NoiseSamplerBuilderLoader implements TypeLoader { + private final NormalizerRegistry normalizerRegistry; + + public NoiseSamplerBuilderLoader(NormalizerRegistry normalizerRegistry) { + this.normalizerRegistry = normalizerRegistry; + } @Override public NoiseSeeded load(Type t, Object c, ConfigLoader loader) throws LoadException { @@ -31,12 +37,12 @@ public class NoiseSamplerBuilderLoader implements TypeLoader { case "NOISE": return loader.loadClass(FastNoiseTemplate.class, map).get(); case "NORMALIZER": - Normalizer.NormalType normalType = loader.loadClass(Normalizer.NormalType.class, map.get("type")); - switch(normalType) { - case LINEAR: - return loader.loadClass(LinearNormalizerTemplate.class, map).get(); - case NORMAL: - return loader.loadClass(NormalNormalizerTemplate.class, map).get(); + try { + NormalizerTemplate normalizerTemplate = normalizerRegistry.get((String) map.get("type")).get(); + loader.load(normalizerTemplate, new Configuration(map)); + return normalizerTemplate; + } catch(ConfigException e) { + throw new LoadException("Unable to load normalizer: ", e); } case "IMAGE": { return loader.loadClass(ImageSamplerTemplate.class, map).get(); diff --git a/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/ClampNormalizerTemplate.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/ClampNormalizerTemplate.java new file mode 100644 index 000000000..1701e8223 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/templates/normalizer/ClampNormalizerTemplate.java @@ -0,0 +1,20 @@ +package com.dfsek.terra.config.loaders.config.sampler.templates.normalizer; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.terra.api.math.noise.NoiseSampler; +import com.dfsek.terra.api.math.noise.normalizer.ClampNormalizer; +import com.dfsek.terra.api.math.noise.normalizer.LinearNormalizer; + +@SuppressWarnings({"unused", "FieldMayBeFinal"}) +public class ClampNormalizerTemplate extends NormalizerTemplate { + @Value("max") + private double max; + + @Value("min") + private double min; + + @Override + public NoiseSampler apply(Long seed) { + return new ClampNormalizer(function.apply(seed), min, max); + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index d65d4aee9..91a83f3fe 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java @@ -1,5 +1,6 @@ package com.dfsek.terra.config.pack; +import com.dfsek.paralithic.eval.parser.Scope; import com.dfsek.tectonic.abstraction.AbstractConfigLoader; import com.dfsek.tectonic.exception.ConfigException; import com.dfsek.tectonic.exception.LoadException; @@ -9,6 +10,7 @@ import com.dfsek.terra.api.LoaderRegistrar; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.structures.loot.LootTable; import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.api.util.seeded.NoiseSeeded; import com.dfsek.terra.api.world.flora.Flora; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.tree.Tree; @@ -29,7 +31,11 @@ import com.dfsek.terra.config.fileloaders.Loader; import com.dfsek.terra.config.fileloaders.ZIPLoader; import com.dfsek.terra.config.lang.LangUtil; import com.dfsek.terra.config.loaders.config.BufferedImageLoader; -import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; +import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; +import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; +import com.dfsek.terra.config.loaders.config.sampler.templates.ImageSamplerTemplate; import com.dfsek.terra.config.templates.AbstractableTemplate; import com.dfsek.terra.config.templates.BiomeTemplate; import com.dfsek.terra.config.templates.CarverTemplate; @@ -38,22 +44,22 @@ import com.dfsek.terra.config.templates.OreTemplate; import com.dfsek.terra.config.templates.PaletteTemplate; import com.dfsek.terra.config.templates.StructureTemplate; import com.dfsek.terra.config.templates.TreeTemplate; -import com.dfsek.terra.registry.BiomeRegistry; -import com.dfsek.terra.registry.CarverRegistry; -import com.dfsek.terra.registry.FloraRegistry; -import com.dfsek.terra.registry.LootRegistry; -import com.dfsek.terra.registry.OreRegistry; -import com.dfsek.terra.registry.PaletteRegistry; -import com.dfsek.terra.registry.ScriptRegistry; -import com.dfsek.terra.registry.StructureRegistry; import com.dfsek.terra.registry.TerraRegistry; -import com.dfsek.terra.registry.TreeRegistry; +import com.dfsek.terra.registry.config.BiomeRegistry; +import com.dfsek.terra.registry.config.CarverRegistry; +import com.dfsek.terra.registry.config.FloraRegistry; +import com.dfsek.terra.registry.config.LootRegistry; +import com.dfsek.terra.registry.config.NormalizerRegistry; +import com.dfsek.terra.registry.config.OreRegistry; +import com.dfsek.terra.registry.config.PaletteRegistry; +import com.dfsek.terra.registry.config.ScriptRegistry; +import com.dfsek.terra.registry.config.StructureRegistry; +import com.dfsek.terra.registry.config.TreeRegistry; import com.dfsek.terra.world.generation.math.SamplerCache; import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.ores.Ore; import org.apache.commons.io.IOUtils; import org.json.simple.parser.ParseException; -import parsii.eval.Scope; import java.awt.image.BufferedImage; import java.io.File; @@ -88,6 +94,8 @@ public class ConfigPack implements LoaderRegistrar { private final CarverRegistry carverRegistry = new CarverRegistry(); + private final NormalizerRegistry normalizerRegistry = new NormalizerRegistry(); + private final AbstractConfigLoader abstractConfigLoader = new AbstractConfigLoader(); private final ConfigLoader selfLoader = new ConfigLoader(); private final Scope varScope = new Scope(); @@ -97,74 +105,98 @@ public class ConfigPack implements LoaderRegistrar { private final TerraPlugin main; private final Loader loader; + private final BiomeProvider.BiomeProviderBuilder biomeProviderBuilder; + public ConfigPack(File folder, TerraPlugin main) throws ConfigException { - this.loader = new FolderLoader(folder.toPath()); - this.main = main; - long l = System.nanoTime(); - this.samplerCache = new SamplerCache(main); - floraRegistry = new FloraRegistry(main); - paletteRegistry = new PaletteRegistry(main); - treeRegistry = new TreeRegistry(main); - register(abstractConfigLoader); - register(selfLoader); - - main.register(selfLoader); - main.register(abstractConfigLoader); - - File pack = new File(folder, "pack.yml"); - try { - selfLoader.load(template, new FileInputStream(pack)); - } catch(FileNotFoundException e) { - throw new FileMissingException("No pack.yml file found in " + folder.getAbsolutePath(), e); + this.loader = new FolderLoader(folder.toPath()); + this.main = main; + long l = System.nanoTime(); + this.samplerCache = new SamplerCache(main); + floraRegistry = new FloraRegistry(main); + paletteRegistry = new PaletteRegistry(main); + treeRegistry = new TreeRegistry(main); + register(abstractConfigLoader); + register(selfLoader); + + main.register(selfLoader); + main.register(abstractConfigLoader); + + File pack = new File(folder, "pack.yml"); + + try { + selfLoader.load(template, new FileInputStream(pack)); + + main.getLogger().info("Loading config pack \"" + template.getID() + "\""); + + load(l, main); + ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); + selfLoader.load(packPostTemplate, new FileInputStream(pack)); + biomeProviderBuilder = packPostTemplate.getProviderBuilder(); + biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. + } catch(FileNotFoundException e) { + throw new FileMissingException("No pack.yml file found in " + folder.getAbsolutePath(), e); + } + } catch(Exception e) { + main.getLogger().severe("Failed to load config pack from folder \"" + folder.getAbsolutePath() + "\""); + throw e; } - load(l, main); } public ConfigPack(ZipFile file, TerraPlugin main) throws ConfigException { - this.loader = new ZIPLoader(file); - this.main = main; - long l = System.nanoTime(); - this.samplerCache = new SamplerCache(main); - floraRegistry = new FloraRegistry(main); - paletteRegistry = new PaletteRegistry(main); - treeRegistry = new TreeRegistry(main); - register(abstractConfigLoader); - register(selfLoader); - - main.register(selfLoader); - main.register(abstractConfigLoader); - - InputStream stream = null; - try { - Enumeration entries = file.entries(); - while(entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - if(entry.getName().equals("pack.yml")) stream = file.getInputStream(entry); + this.loader = new ZIPLoader(file); + this.main = main; + long l = System.nanoTime(); + this.samplerCache = new SamplerCache(main); + floraRegistry = new FloraRegistry(main); + paletteRegistry = new PaletteRegistry(main); + treeRegistry = new TreeRegistry(main); + register(abstractConfigLoader); + register(selfLoader); + + main.register(selfLoader); + main.register(abstractConfigLoader); + + try { + ZipEntry pack = null; + Enumeration entries = file.entries(); + while(entries.hasMoreElements()) { + ZipEntry entry = entries.nextElement(); + if(entry.getName().equals("pack.yml")) pack = entry; + } + + if(pack == null) throw new FileMissingException("No pack.yml file found in " + file.getName()); + + selfLoader.load(template, file.getInputStream(pack)); + main.getLogger().info("Loading config pack \"" + template.getID() + "\""); + + load(l, main); + + ConfigPackPostTemplate packPostTemplate = new ConfigPackPostTemplate(); + + selfLoader.load(packPostTemplate, file.getInputStream(pack)); + biomeProviderBuilder = packPostTemplate.getProviderBuilder(); + biomeProviderBuilder.build(0); // Build dummy provider to catch errors at load time. + } catch(IOException e) { + throw new LoadException("Unable to load pack.yml from ZIP file", e); } - } catch(IOException e) { - throw new LoadException("Unable to load pack.yml from ZIP file", e); + } catch(Exception e) { + main.getLogger().severe("Failed to load config pack from ZIP archive \"" + file.getName() + "\""); + throw e; } - if(stream == null) throw new FileMissingException("No pack.yml file found in " + file.getName()); + } - selfLoader.load(template, stream); - - - load(l, main); - - template.getProviderBuilder().build(0); // Build dummy provider to catch errors at load time. + public static void buildAll(TerraFactory factory, TerraRegistry registry, List configTemplates, TerraPlugin main) throws LoadException { + for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main)); } private void load(long start, TerraPlugin main) throws ConfigException { main.packPreLoadCallback(this); for(Map.Entry var : template.getVariables().entrySet()) { - varScope.create(var.getKey()).setValue(var.getValue()); + varScope.create(var.getKey(), var.getValue()); } - loader.open("structures/data", ".tstructure") - .thenNames(ids -> ids.forEach(id -> main.getLogger().severe("Found .tstructure file \"" + id + "\". This file must be updated to the newer .tesf format to work properly. See version 3.0 release notes for instructions."))) - .close(); loader.open("structures/data", ".tesf").thenEntries(entries -> { for(Map.Entry entry : entries) { @@ -197,10 +229,6 @@ public class ConfigPack implements LoaderRegistrar { LangUtil.log("config-pack.loaded", Level.INFO, template.getID(), String.valueOf((System.nanoTime() - start) / 1000000D), template.getAuthor(), template.getVersion()); } - public static void buildAll(TerraFactory factory, TerraRegistry registry, List configTemplates, TerraPlugin main) throws LoadException { - for(C template : configTemplates) registry.add(template.getID(), factory.build(template, main)); - } - public TerraBiome getBiome(String id) { return biomeRegistry.get(id); } @@ -247,7 +275,10 @@ public class ConfigPack implements LoaderRegistrar { .registerLoader(LootTable.class, lootRegistry) .registerLoader(UserDefinedCarver.class, carverRegistry) .registerLoader(BufferedImage.class, new BufferedImageLoader(loader)) - .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(main, biomeRegistry, loader)); + .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(normalizerRegistry)) + .registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry)) + .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, main)) + .registerLoader(ImageSamplerTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); } public ScriptRegistry getScriptRegistry() { @@ -265,4 +296,8 @@ public class ConfigPack implements LoaderRegistrar { public Set getCarvers() { return carverRegistry.entries(); } + + public BiomeProvider.BiomeProviderBuilder getBiomeProviderBuilder() { + return biomeProviderBuilder; + } } diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java new file mode 100644 index 000000000..985740a1a --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackPostTemplate.java @@ -0,0 +1,14 @@ +package com.dfsek.terra.config.pack; + +import com.dfsek.tectonic.annotations.Value; +import com.dfsek.tectonic.config.ConfigTemplate; +import com.dfsek.terra.biome.provider.BiomeProvider; + +public class ConfigPackPostTemplate implements ConfigTemplate { + @Value("biomes") + private BiomeProvider.BiomeProviderBuilder providerBuilder; + + public BiomeProvider.BiomeProviderBuilder getProviderBuilder() { + return providerBuilder; + } +} diff --git a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java index 051bf659d..638a6f4e9 100644 --- a/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPackTemplate.java @@ -4,7 +4,6 @@ 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.config.loaders.config.function.FunctionTemplate; import java.util.HashMap; @@ -67,13 +66,6 @@ public class ConfigPackTemplate implements ConfigTemplate { @Default private String version = "0.1.0"; - @Value("biomes") - private BiomeProvider.BiomeProviderBuilder providerBuilder; - - public BiomeProvider.BiomeProviderBuilder getProviderBuilder() { - return providerBuilder; - } - public Map getFunctions() { return functions; } diff --git a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java index d72f796de..6afdeb128 100644 --- a/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java +++ b/common/src/main/java/com/dfsek/terra/config/templates/BiomeTemplate.java @@ -1,5 +1,8 @@ package com.dfsek.terra.config.templates; +import com.dfsek.paralithic.eval.parser.Parser; +import com.dfsek.paralithic.eval.parser.Scope; +import com.dfsek.paralithic.eval.tokenizer.ParseException; import com.dfsek.tectonic.annotations.Abstractable; import com.dfsek.tectonic.annotations.Default; import com.dfsek.tectonic.annotations.Value; @@ -27,17 +30,12 @@ import com.dfsek.terra.world.population.items.TerraStructure; import com.dfsek.terra.world.population.items.flora.FloraLayer; import com.dfsek.terra.world.population.items.ores.OreHolder; import com.dfsek.terra.world.population.items.tree.TreeLayer; -import parsii.eval.Parser; -import parsii.eval.Scope; -import parsii.eval.Variable; -import parsii.tokenizer.ParseException; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; @SuppressWarnings({"FieldMayBeFinal", "unused"}) public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate { @@ -344,26 +342,20 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf Parser tester = new Parser(); Scope testScope = new Scope().withParent(pack.getVarScope()); - variables.forEach((id, val) -> testScope.create(id).setValue(val)); + variables.forEach(testScope::create); + + testScope.addInvocationVariable("x"); + testScope.addInvocationVariable("y"); + testScope.addInvocationVariable("z"); - testScope.create("x"); - testScope.create("y"); - testScope.create("z"); - testScope.create("seed"); pack.getTemplate().getNoiseBuilderMap().forEach((id, builder) -> tester.registerFunction(id, new BlankFunction(builder.getDimensions()))); // Register dummy functions Map testFunctions = new LinkedHashMap<>(pack.getTemplate().getFunctions()); testFunctions.putAll(functions); for(Map.Entry entry : testFunctions.entrySet()) { - String id = entry.getKey(); - FunctionTemplate fun = entry.getValue(); - - Scope functionScope = new Scope().withParent(testScope); - List variables = fun.getArgs().stream().map(functionScope::create).collect(Collectors.toList()); - try { - tester.registerFunction(id, new UserDefinedFunction(tester.parse(fun.getFunction(), functionScope), variables)); + tester.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), tester, testScope)); } catch(ParseException e) { throw new ValidationException("Invalid function: ", e); } diff --git a/common/src/main/java/com/dfsek/terra/registry/BiomeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java similarity index 87% rename from common/src/main/java/com/dfsek/terra/registry/BiomeRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java index 235f379ec..06aad4412 100644 --- a/common/src/main/java/com/dfsek/terra/registry/BiomeRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/BiomeRegistry.java @@ -1,8 +1,9 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.tectonic.exception.LoadException; import com.dfsek.tectonic.loading.ConfigLoader; import com.dfsek.terra.biome.TerraBiome; +import com.dfsek.terra.registry.TerraRegistry; import java.lang.reflect.Type; diff --git a/common/src/main/java/com/dfsek/terra/registry/CarverRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java similarity index 58% rename from common/src/main/java/com/dfsek/terra/registry/CarverRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java index 8de7fa2da..46fe3d725 100644 --- a/common/src/main/java/com/dfsek/terra/registry/CarverRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/CarverRegistry.java @@ -1,6 +1,7 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.terra.carving.UserDefinedCarver; +import com.dfsek.terra.registry.TerraRegistry; public class CarverRegistry extends TerraRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/FloraRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java similarity index 96% rename from common/src/main/java/com/dfsek/terra/registry/FloraRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java index 0645a1dd3..e62f88b08 100644 --- a/common/src/main/java/com/dfsek/terra/registry/FloraRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/FloraRegistry.java @@ -1,9 +1,10 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.platform.block.MaterialData; import com.dfsek.terra.api.world.flora.Flora; +import com.dfsek.terra.registry.TerraRegistry; import com.dfsek.terra.util.MaterialSet; import com.dfsek.terra.world.population.items.flora.ConstantFlora; @@ -37,7 +38,7 @@ public class FloraRegistry extends TerraRegistry { create("minecraft:light_gray_terracotta"), create("minecraft:lime_terracotta"), create("minecraft:magenta_terracotta"), create("minecraft:orange_terracotta"), create("minecraft:pink_terracotta"), create("minecraft:purple_terracotta"), create("minecraft:red_terracotta"), create("minecraft:white_terracotta"), create("minecraft:yellow_terracotta"), - create("minecraft:red_sand"), create("minecraft:sand")), Collections.singletonList(data("minecraft:dead_bush")))); + create("minecraft:red_sand"), create("minecraft:sand"), create("minecraft:coarse_dirt")), Collections.singletonList(data("minecraft:dead_bush")))); addItem("RED_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:red_tulip")))); addItem("ORANGE_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:orange_tulip")))); addItem("WHITE_TULIP", () -> new ConstantFlora(grassy, Collections.singletonList(data("minecraft:white_tulip")))); diff --git a/common/src/main/java/com/dfsek/terra/registry/LootRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java similarity index 57% rename from common/src/main/java/com/dfsek/terra/registry/LootRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java index 0104bb66c..21358ea41 100644 --- a/common/src/main/java/com/dfsek/terra/registry/LootRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/LootRegistry.java @@ -1,6 +1,7 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.terra.api.structures.loot.LootTable; +import com.dfsek.terra.registry.TerraRegistry; public class LootRegistry extends TerraRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/config/NormalizerRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/NormalizerRegistry.java new file mode 100644 index 000000000..900a99fc2 --- /dev/null +++ b/common/src/main/java/com/dfsek/terra/registry/config/NormalizerRegistry.java @@ -0,0 +1,17 @@ +package com.dfsek.terra.registry.config; + +import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.ClampNormalizerTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.LinearNormalizerTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalNormalizerTemplate; +import com.dfsek.terra.config.loaders.config.sampler.templates.normalizer.NormalizerTemplate; +import com.dfsek.terra.registry.TerraRegistry; + +import java.util.function.Supplier; + +public class NormalizerRegistry extends TerraRegistry>> { + public NormalizerRegistry() { + add("LINEAR", LinearNormalizerTemplate::new); + add("NORMAL", NormalNormalizerTemplate::new); + add("CLAMP", ClampNormalizerTemplate::new); + } +} diff --git a/common/src/main/java/com/dfsek/terra/registry/OreRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java similarity index 56% rename from common/src/main/java/com/dfsek/terra/registry/OreRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java index 4290497bc..3f8e285df 100644 --- a/common/src/main/java/com/dfsek/terra/registry/OreRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/OreRegistry.java @@ -1,5 +1,6 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; +import com.dfsek.terra.registry.TerraRegistry; import com.dfsek.terra.world.population.items.ores.Ore; public class OreRegistry extends TerraRegistry { diff --git a/common/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java similarity index 88% rename from common/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java index eb0a2ec10..2a8cb5704 100644 --- a/common/src/main/java/com/dfsek/terra/registry/PaletteRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/PaletteRegistry.java @@ -1,9 +1,10 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.platform.block.BlockData; import com.dfsek.terra.api.world.palette.Palette; import com.dfsek.terra.api.world.palette.SinglePalette; +import com.dfsek.terra.registry.TerraRegistry; public class PaletteRegistry extends TerraRegistry> { private final TerraPlugin main; diff --git a/common/src/main/java/com/dfsek/terra/registry/ScriptRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java similarity index 60% rename from common/src/main/java/com/dfsek/terra/registry/ScriptRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java index 703f971b6..d4320f854 100644 --- a/common/src/main/java/com/dfsek/terra/registry/ScriptRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/ScriptRegistry.java @@ -1,6 +1,7 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.terra.api.structures.script.StructureScript; +import com.dfsek.terra.registry.TerraRegistry; public class ScriptRegistry extends TerraRegistry { } diff --git a/common/src/main/java/com/dfsek/terra/registry/StructureRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java similarity index 60% rename from common/src/main/java/com/dfsek/terra/registry/StructureRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java index 092241a43..523395fa7 100644 --- a/common/src/main/java/com/dfsek/terra/registry/StructureRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/StructureRegistry.java @@ -1,5 +1,6 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; +import com.dfsek.terra.registry.TerraRegistry; import com.dfsek.terra.world.population.items.TerraStructure; public class StructureRegistry extends TerraRegistry { diff --git a/common/src/main/java/com/dfsek/terra/registry/TreeRegistry.java b/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java similarity index 97% rename from common/src/main/java/com/dfsek/terra/registry/TreeRegistry.java rename to common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java index fd63d50b8..82ac69fc6 100644 --- a/common/src/main/java/com/dfsek/terra/registry/TreeRegistry.java +++ b/common/src/main/java/com/dfsek/terra/registry/config/TreeRegistry.java @@ -1,4 +1,4 @@ -package com.dfsek.terra.registry; +package com.dfsek.terra.registry.config; import com.dfsek.terra.api.core.TerraPlugin; import com.dfsek.terra.api.math.vector.Location; @@ -14,6 +14,7 @@ import com.dfsek.terra.api.world.tree.fractal.trees.ShatteredTree; import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredPillar; import com.dfsek.terra.api.world.tree.fractal.trees.SmallShatteredTree; import com.dfsek.terra.api.world.tree.fractal.trees.SpruceTree; +import com.dfsek.terra.registry.TerraRegistry; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; diff --git a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java index 79c25cdeb..936582d38 100644 --- a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java +++ b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java @@ -24,9 +24,10 @@ public class TerraWorld { public TerraWorld(World w, ConfigPack c, TerraPlugin main) { + c.getBiomeRegistry().forEach(biome -> biome.getGenerator(w)); // Load all gens to cache config = c; profiler = new WorldProfiler(w); - this.provider = config.getTemplate().getProviderBuilder().build(w.getSeed()); + this.provider = config.getBiomeProviderBuilder().build(w.getSeed()); this.world = w; air = main.getWorldHandle().createBlockData("minecraft:air"); safe = true; diff --git a/common/src/test/java/biome/BiomeTest.java b/common/src/test/java/biome/BiomeTest.java deleted file mode 100644 index 8dafb17d5..000000000 --- a/common/src/test/java/biome/BiomeTest.java +++ /dev/null @@ -1,160 +0,0 @@ -package biome; - -import com.dfsek.terra.api.math.ProbabilityCollection; -import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite; -import com.dfsek.terra.api.platform.world.Biome; -import com.dfsek.terra.api.platform.world.World; -import com.dfsek.terra.api.world.biome.Generator; -import com.dfsek.terra.biome.TerraBiome; -import com.dfsek.terra.biome.pipeline.BiomePipeline; -import com.dfsek.terra.biome.pipeline.expand.FractalExpander; -import com.dfsek.terra.biome.pipeline.mutator.BorderMutator; -import com.dfsek.terra.biome.pipeline.mutator.ReplaceMutator; -import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator; -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.provider.BiomeProvider; -import com.dfsek.terra.biome.provider.StandardBiomeProvider; -import org.junit.jupiter.api.Test; - -import javax.swing.*; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -public class BiomeTest { - @Test - public static void main(String... args) { - ProbabilityCollection oceanBiomes = new ProbabilityCollection<>(); - ProbabilityCollection landBiomes = new ProbabilityCollection<>(); - - - ProbabilityCollection beachBiomes = new ProbabilityCollection<>(); - - TestBiome ocean = new TestBiome(Color.BLUE, "OCEAN_TEMP"); - TestBiome land = new TestBiome(Color.GREEN, "LAND_TEMP"); - - TestBiome beach = new TestBiome(Color.YELLOW, "BEACH"); - beachBiomes.add(beach, 1); - - - ProbabilityCollection climate = new ProbabilityCollection<>(); - climate.add(ocean, 1); - climate.add(land, 2); - - - oceanBiomes.add(new TestBiome(Color.BLUE, "OCEAN"), 10); - oceanBiomes.add(new TestBiome(Color.CYAN, "OCEAN"), 1); - - landBiomes.add(new TestBiome(Color.GREEN, "LAND"), 8); - landBiomes.add(new TestBiome(Color.ORANGE, "LAND"), 5); - landBiomes.add(new TestBiome(Color.RED, "LAND"), 1); - landBiomes.add(new TestBiome(Color.GRAY, "LAND"), 1); - - FastNoiseLite sourceSampler = new FastNoiseLite(123); - sourceSampler.setNoiseType(FastNoiseLite.NoiseType.WhiteNoise); - - BiomeSource source = new RandomSource(climate, sourceSampler); - - - BiomeProvider provider = new StandardBiomeProvider.StandardBiomeProviderBuilder((seed) -> new BiomePipeline.BiomePipelineBuilder(2) - .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); - - - int size = 1000; - - - BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); - - - System.out.println(size); - - long s = System.nanoTime(); - for(int x = 0; x < size; x++) { - for(int z = 0; z < size; z++) { - image.setRGB(x, z, provider.getBiome(x, z).getColor()); - } - } - long e = System.nanoTime(); - - double time = e - s; - time /= 1000000; - System.out.println(time + "ms for " + size + "x" + size); - - JFrame frame = new JFrame("TerraBiome Viewer"); - - - frame.setResizable(false); - frame.add(new JLabel(new ImageIcon(image))); - frame.pack(); - - - System.out.println("Done"); - - frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - - frame.setVisible(true); - - } - - private static NoiseSampler whiteNoise(int seed) { - FastNoiseLite noiseLite = new FastNoiseLite(seed); - noiseLite.setNoiseType(FastNoiseLite.NoiseType.WhiteNoise); - return noiseLite; - } - - private final static class TestBiome implements TerraBiome { - private final Color color; - private final Set tags; - - - private TestBiome(Color color, String... tags) { - this.color = color; - this.tags = Arrays.stream(tags).collect(Collectors.toSet()); - } - - @Override - public ProbabilityCollection getVanillaBiomes() { - return null; - } - - @Override - public Generator getGenerator(World w) { - return null; - } - - @Override - public int getColor() { - return color.getRGB(); - } - - @Override - public Set getTags() { - return tags; - } - - @Override - public String getID() { - return null; - } - } -} diff --git a/common/src/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java index 2694289c7..f54a59fef 100644 --- a/common/src/test/java/biome/DistributionTest.java +++ b/common/src/test/java/biome/DistributionTest.java @@ -24,13 +24,18 @@ import com.dfsek.terra.config.PluginConfig; import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.lang.Language; import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; +import com.dfsek.terra.config.loaders.config.BufferedImageLoader; import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader; +import com.dfsek.terra.config.loaders.config.biome.templates.source.BiomePipelineTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.source.ImageProviderTemplate; +import com.dfsek.terra.config.loaders.config.biome.templates.source.SingleBiomeProviderTemplate; import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; import com.dfsek.terra.config.pack.ConfigPack; import com.dfsek.terra.config.templates.AbstractableTemplate; import com.dfsek.terra.debug.DebugLogger; -import com.dfsek.terra.registry.BiomeRegistry; import com.dfsek.terra.registry.ConfigRegistry; +import com.dfsek.terra.registry.config.BiomeRegistry; +import com.dfsek.terra.registry.config.NormalizerRegistry; import com.dfsek.terra.world.TerraWorld; import javax.swing.*; @@ -141,12 +146,16 @@ public class DistributionTest { BiomeProviderTemplate template = new BiomeProviderTemplate(); ConfigLoader pipeLoader = new ConfigLoader() - .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(MAIN, biomeRegistry, folderLoader)) + .registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader()) .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()) - .registerLoader(TerraBiome.class, biomeRegistry); + .registerLoader(TerraBiome.class, biomeRegistry) + .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) + .registerLoader(SingleBiomeProviderTemplate.class, () -> new SingleBiomeProviderTemplate(biomeRegistry)) + .registerLoader(BiomePipelineTemplate.class, () -> new BiomePipelineTemplate(biomeRegistry, MAIN)) + .registerLoader(ImageProviderTemplate.class, () -> new ImageProviderTemplate(biomeRegistry)); new GenericLoaders(null).register(pipeLoader); - pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()); + pipeLoader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NormalizerRegistry())); pipeLoader.load(template, folderLoader.get("pack.yml")); return template.getBiomeProviderBuilder().build(seed); diff --git a/common/src/test/java/biome/ImageTest.java b/common/src/test/java/biome/ImageTest.java index c93348b58..916a68c00 100644 --- a/common/src/test/java/biome/ImageTest.java +++ b/common/src/test/java/biome/ImageTest.java @@ -48,7 +48,7 @@ public class ImageTest { }; folderLoader.open("biomes", ".yml").then(inputStreams -> ConfigPack.buildAll((template, main) -> template, biomeRegistry, loader.load(inputStreams, TestBiome::new), null)); - return new ImageBiomeProvider(biomeRegistry, ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1); + return new ImageBiomeProvider(biomeRegistry, ImageIO.read(ImageTest.class.getResourceAsStream("/map.jpg")), 1, ImageBiomeProvider.Align.CENTER); } @Test diff --git a/common/src/test/java/noise/NoiseTool.java b/common/src/test/java/noise/NoiseTool.java index 07c9e2c0e..977673db9 100644 --- a/common/src/test/java/noise/NoiseTool.java +++ b/common/src/test/java/noise/NoiseTool.java @@ -10,6 +10,7 @@ import com.dfsek.terra.config.fileloaders.FolderLoader; import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader; import com.dfsek.terra.config.loaders.config.BufferedImageLoader; import com.dfsek.terra.config.loaders.config.sampler.NoiseSamplerBuilderLoader; +import com.dfsek.terra.registry.config.NormalizerRegistry; import org.apache.commons.io.FileUtils; import javax.swing.*; @@ -96,7 +97,7 @@ public class NoiseTool { FolderLoader folderLoader = new FolderLoader(Paths.get("./")); ConfigLoader loader = new ConfigLoader(); - loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()) + loader.registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader(new NormalizerRegistry())) .registerLoader(BufferedImage.class, new BufferedImageLoader(folderLoader)) .registerLoader(ProbabilityCollection.class, new ProbabilityCollectionLoader()); diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java index 2882736a5..6a1948cf9 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/command/command/TerraCommand.java @@ -33,7 +33,7 @@ public class TerraCommand extends Command { @Override public String getName() { - return "com/dfsek/terra"; + return "terra"; } @Override diff --git a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java index b3407e3fa..b4ef72b18 100644 --- a/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java +++ b/platforms/bukkit/src/main/java/com/dfsek/terra/bukkit/listeners/CommonListener.java @@ -9,13 +9,14 @@ import com.dfsek.terra.api.util.FastRandom; import com.dfsek.terra.api.world.tree.Tree; import com.dfsek.terra.bukkit.world.BukkitAdapter; import com.dfsek.terra.config.pack.ConfigPack; -import com.dfsek.terra.registry.TreeRegistry; +import com.dfsek.terra.registry.config.TreeRegistry; import com.dfsek.terra.world.TerraWorld; import org.bukkit.Material; import org.bukkit.TreeType; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.world.StructureGrowEvent; @@ -40,7 +41,7 @@ public class CommonListener implements Listener { .add(TreeType.SWAMP, "SWAMP_OAK")) .addTransform(TreeType::toString).build(); - @EventHandler + @EventHandler(priority = EventPriority.HIGHEST) public void onSaplingGrow(StructureGrowEvent e) { if(e.isCancelled()) return; World bukkit = BukkitAdapter.adapt(e.getWorld()); diff --git a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java index 452fd222b..8cc0dee3d 100644 --- a/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java +++ b/platforms/fabric/src/main/java/com/dfsek/terra/fabric/world/TerraBiomeSource.java @@ -34,7 +34,7 @@ public class TerraBiomeSource extends BiomeSource { super(biomes.stream().collect(Collectors.toList())); this.biomeRegistry = biomes; this.seed = seed; - this.grid = pack.getTemplate().getProviderBuilder().build(seed); + this.grid = pack.getBiomeProviderBuilder().build(seed); this.pack = pack; }