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 94d1acd2a..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, CLAMP - } } 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 11a7da859..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 @@ -30,10 +30,10 @@ public class ExpressionSampler implements NoiseSampler { 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; } }); 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 cec8e52ed..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,7 +1,6 @@ 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; @@ -10,8 +9,8 @@ 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 @@ -33,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; 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 c8d38bdc7..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,13 +1,12 @@ package com.dfsek.terra.api.math.parsii.noise; import com.dfsek.terra.api.math.noise.NoiseSampler; -import com.dfsek.terra.api.util.seeded.NoiseSeeded; 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 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 2260bd15e..9e48e4caf 100644 --- a/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java +++ b/common/src/main/java/com/dfsek/terra/carving/UserDefinedCarver.java @@ -61,10 +61,10 @@ 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; } }); 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 4764b2790..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,10 +6,8 @@ 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; @@ -38,7 +36,6 @@ 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; @@ -84,7 +81,6 @@ public class GenericLoaders implements LoaderRegistrar { .registerLoader(LinearNormalizerTemplate.class, LinearNormalizerTemplate::new) .registerLoader(NormalNormalizerTemplate.class, NormalNormalizerTemplate::new) .registerLoader(ClampNormalizerTemplate.class, ClampNormalizerTemplate::new) - .registerLoader(NoiseSeeded.class, new NoiseSamplerBuilderLoader()) .registerLoader(ReplaceMutatorTemplate.class, ReplaceMutatorTemplate::new) .registerLoader(ExpanderStageTemplate.class, ExpanderStageTemplate::new) .registerLoader(SmoothMutatorTemplate.class, SmoothMutatorTemplate::new) @@ -108,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/loaders/config/sampler/NoiseSamplerBuilderLoader.java b/common/src/main/java/com/dfsek/terra/config/loaders/config/sampler/NoiseSamplerBuilderLoader.java index 19a8653d4..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,22 +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.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.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 { @@ -32,14 +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); - case NORMAL: - return loader.loadClass(NormalNormalizerTemplate.class, map); - case CLAMP: - return loader.loadClass(ClampNormalizerTemplate.class, map); + 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/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index 90b067690..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 @@ -10,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; @@ -33,6 +34,7 @@ import com.dfsek.terra.config.loaders.config.BufferedImageLoader; 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; @@ -47,6 +49,7 @@ 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; @@ -91,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(); @@ -270,6 +275,7 @@ public class ConfigPack implements LoaderRegistrar { .registerLoader(LootTable.class, lootRegistry) .registerLoader(UserDefinedCarver.class, carverRegistry) .registerLoader(BufferedImage.class, new BufferedImageLoader(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)); 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/test/java/biome/DistributionTest.java b/common/src/test/java/biome/DistributionTest.java index f31ce6c91..f54a59fef 100644 --- a/common/src/test/java/biome/DistributionTest.java +++ b/common/src/test/java/biome/DistributionTest.java @@ -35,6 +35,7 @@ import com.dfsek.terra.config.templates.AbstractableTemplate; import com.dfsek.terra.debug.DebugLogger; 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.*; @@ -154,7 +155,7 @@ public class DistributionTest { .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/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());