From 565266992f05394b15523a2b7d82326ca8158bd4 Mon Sep 17 00:00:00 2001 From: dfsek Date: Wed, 3 Feb 2021 23:15:36 -0700 Subject: [PATCH] paralithic implementation --- common/build.gradle.kts | 3 +- .../noise/samplers/ExpressionSampler.java | 32 +++++---------- .../terra/api/math/parsii/BlankFunction.java | 13 +++--- .../parsii/defined/UserDefinedFunction.java | 40 +++++++++---------- .../api/math/parsii/noise/NoiseFunction.java | 4 +- .../api/math/parsii/noise/NoiseFunction2.java | 23 +++-------- .../api/math/parsii/noise/NoiseFunction3.java | 11 ++--- .../config/builder/GeneratorBuilder.java | 4 +- .../terra/config/factories/BiomeFactory.java | 4 +- .../dfsek/terra/config/pack/ConfigPack.java | 4 +- .../terra/config/templates/BiomeTemplate.java | 23 +++++------ .../com/dfsek/terra/world/TerraWorld.java | 1 + .../bukkit/command/command/TerraCommand.java | 2 +- 13 files changed, 67 insertions(+), 97 deletions(-) diff --git a/common/build.gradle.kts b/common/build.gradle.kts index 94fec69e3..9a48211c6 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.1.0+21c6ff6") "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/samplers/ExpressionSampler.java b/common/src/main/java/com/dfsek/terra/api/math/noise/samplers/ExpressionSampler.java index 003f692dd..0564b0f56 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,37 +1,31 @@ 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()) { @@ -49,25 +43,21 @@ public class ExpressionSampler implements NoiseSampler { 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(id, new UserDefinedFunction(parser.parse(fun.getFunction(), functionScope), fun.getArgs().size())); } 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..206dc83ea 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,8 @@ package com.dfsek.terra.api.math.parsii; -import parsii.eval.Expression; -import parsii.eval.Function; +import com.dfsek.paralithic.function.dynamic.DynamicFunction; -import java.util.List; - -public class BlankFunction implements Function { +public class BlankFunction implements DynamicFunction { private final int args; public BlankFunction(int args) { @@ -13,17 +10,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..6a28021d6 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,31 @@ 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.function.dynamic.DynamicFunction; -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) { + public 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; + } } 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..4b9e90dbf 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,6 @@ package com.dfsek.terra.api.math.parsii.noise; -import parsii.eval.Function; +import com.dfsek.paralithic.function.dynamic.DynamicFunction; -public interface NoiseFunction extends Function { +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..cec8e52ed 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 @@ -3,9 +3,8 @@ 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; @@ -16,27 +15,17 @@ public class NoiseFunction2 implements NoiseFunction { } @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; } @@ -55,7 +44,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..c8d38bdc7 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 @@ -2,9 +2,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 parsii.eval.Expression; - -import java.util.List; public class NoiseFunction3 implements NoiseFunction { private final NoiseSampler gen; @@ -14,17 +11,17 @@ public class NoiseFunction3 implements NoiseFunction { } @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/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 61460c2f4..6297b018c 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.HashMap; 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/pack/ConfigPack.java b/common/src/main/java/com/dfsek/terra/config/pack/ConfigPack.java index 6b587e8bc..2bfe47540 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; @@ -49,7 +50,6 @@ 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; @@ -154,7 +154,7 @@ public class ConfigPack implements LoaderRegistrar { 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."))) 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 29cbfb193..47914948c 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; @@ -26,16 +29,11 @@ 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.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; @SuppressWarnings({"FieldMayBeFinal", "unused"}) public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate { @@ -333,12 +331,12 @@ 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 @@ -349,16 +347,17 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf FunctionTemplate fun = entry.getValue(); Scope functionScope = new Scope().withParent(testScope); - List variables = fun.getArgs().stream().map(functionScope::create).collect(Collectors.toList()); + fun.getArgs().forEach(functionScope::addInvocationVariable); try { - tester.registerFunction(id, new UserDefinedFunction(tester.parse(fun.getFunction(), functionScope), variables)); + tester.registerFunction(id, new UserDefinedFunction(tester.parse(fun.getFunction(), functionScope), fun.getArgs().size())); } catch(ParseException e) { throw new ValidationException("Invalid function: ", e); } } try { + System.out.println("Testing " + id); tester.parse(noiseEquation, testScope); } catch(ParseException e) { throw new ValidationException("Invalid noise equation: ", e); 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..c361fce2e 100644 --- a/common/src/main/java/com/dfsek/terra/world/TerraWorld.java +++ b/common/src/main/java/com/dfsek/terra/world/TerraWorld.java @@ -24,6 +24,7 @@ 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()); 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