implement UserDefinedFunction

This commit is contained in:
dfsek
2021-01-31 01:41:05 -07:00
parent e600b50a11
commit 1863ba29fc
10 changed files with 148 additions and 38 deletions
@@ -28,6 +28,7 @@ import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.Borde
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceListMutatorTemplate;
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;
@@ -77,6 +78,7 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(ReplaceListMutatorTemplate.class, ReplaceListMutatorTemplate::new)
.registerLoader(BorderMutatorTemplate.class, BorderMutatorTemplate::new)
.registerLoader(BorderListMutatorTemplate.class, BorderListMutatorTemplate::new)
.registerLoader(FunctionTemplate.class, FunctionTemplate::new)
.registerLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.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))
@@ -5,6 +5,7 @@ import com.dfsek.terra.api.math.noise.samplers.ConstantSampler;
import com.dfsek.terra.api.math.noise.samplers.ExpressionSampler;
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;
@@ -26,6 +27,8 @@ public class GeneratorBuilder {
private Map<String, NoiseSeeded> noiseBuilderMap;
private Map<String, FunctionTemplate> functionTemplateMap;
private PaletteHolder palettes;
private PaletteHolder slantPalettes;
@@ -51,9 +54,9 @@ public class GeneratorBuilder {
NoiseSampler elevation;
NoiseSampler carving;
try {
noise = new ExpressionSampler(noiseEquation, varScope, seed, noiseBuilderMap);
elevation = elevationEquation == null ? new ConstantSampler(0) : new ExpressionSampler(elevationEquation, varScope, seed, noiseBuilderMap);
carving = new ExpressionSampler(carvingEquation, varScope, seed, noiseBuilderMap);
noise = new ExpressionSampler(noiseEquation, varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = elevationEquation == null ? new ConstantSampler(0) : new ExpressionSampler(elevationEquation, varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(carvingEquation, varScope, seed, noiseBuilderMap, functionTemplateMap);
} catch(ParseException e) {
throw new RuntimeException(e);
}
@@ -66,6 +69,10 @@ public class GeneratorBuilder {
this.blendWeight = blendWeight;
}
public void setFunctionTemplateMap(Map<String, FunctionTemplate> functionTemplateMap) {
this.functionTemplateMap = functionTemplateMap;
}
public void setBlendStep(int blendStep) {
this.blendStep = blendStep;
}
@@ -4,10 +4,14 @@ import com.dfsek.terra.api.core.TerraPlugin;
import com.dfsek.terra.biome.TerraBiome;
import com.dfsek.terra.biome.UserDefinedBiome;
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;
public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
private final ConfigPack pack;
@@ -21,7 +25,12 @@ public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
generatorBuilder.setElevationEquation(template.getElevationEquation());
generatorBuilder.setNoiseEquation(template.getNoiseEquation());
generatorBuilder.setCarvingEquation(template.getCarvingEquation());
generatorBuilder.setNoiseBuilderMap(template.getPack().getTemplate().getNoiseBuilderMap());
generatorBuilder.setNoiseBuilderMap(pack.getTemplate().getNoiseBuilderMap());
Map<String, FunctionTemplate> functions = new HashMap<>(pack.getTemplate().getFunctions());
functions.putAll(template.getFunctions());
generatorBuilder.setFunctionTemplateMap(functions);
generatorBuilder.setPalettes(template.getPalette());
generatorBuilder.setSlantPalettes(template.getSlantPalette());
@@ -0,0 +1,28 @@
package com.dfsek.terra.config.loaders.config.function;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import java.util.List;
@SuppressWarnings("unused")
public class FunctionTemplate implements ObjectTemplate<FunctionTemplate> {
@Value("arguments")
private List<String> args;
@Value("function")
private String function;
public List<String> getArgs() {
return args;
}
public String getFunction() {
return function;
}
@Override
public FunctionTemplate get() {
return this;
}
}
@@ -5,6 +5,7 @@ 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;
import java.util.Map;
@@ -21,6 +22,10 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Default
private Map<String, Double> variables = new HashMap<>();
@Value("functions")
@Default
private Map<String, FunctionTemplate> functions = new HashMap<>();
@Value("structures.locatable")
@Default
private Map<String, String> locatable = new HashMap<>();
@@ -80,6 +85,10 @@ public class ConfigPackTemplate implements ConfigTemplate {
return providerBuilder;
}
public Map<String, FunctionTemplate> getFunctions() {
return functions;
}
public String getVersion() {
return version;
}
@@ -10,6 +10,7 @@ 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.math.parsii.BlankFunction;
import com.dfsek.terra.api.math.parsii.defined.UserDefinedFunction;
import com.dfsek.terra.api.platform.block.BlockData;
import com.dfsek.terra.api.platform.block.MaterialData;
import com.dfsek.terra.api.platform.world.Biome;
@@ -18,6 +19,7 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.palette.SinglePalette;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.loaders.config.sampler.templates.FastNoiseTemplate;
import com.dfsek.terra.config.pack.ConfigPack;
import com.dfsek.terra.world.population.items.TerraStructure;
@@ -26,12 +28,14 @@ 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 {
@@ -50,6 +54,11 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Default
private Map<String, Double> variables = new HashMap<>();
@Value("functions")
@Default
@Abstractable
private Map<String, FunctionTemplate> functions = new HashMap<>();
@Value("carving.equation")
@Abstractable
@Default
@@ -180,6 +189,10 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
return tags;
}
public Map<String, FunctionTemplate> getFunctions() {
return functions;
}
public double getBlendWeight() {
return blendWeight;
}
@@ -316,7 +329,7 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Override
public boolean validate() throws ValidationException {
color |= 0x1fe00000; // Alpha adjustment
color |= 0xff000000; // Alpha adjustment
Parser tester = new Parser();
Scope testScope = new Scope().withParent(pack.getVarScope());
@@ -329,6 +342,22 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
pack.getTemplate().getNoiseBuilderMap().forEach((id, builder) -> tester.registerFunction(id, new BlankFunction(builder.getDimensions()))); // Register dummy functions
Map<String, FunctionTemplate> testFunctions = new HashMap<>(pack.getTemplate().getFunctions());
testFunctions.putAll(functions);
for(Map.Entry<String, FunctionTemplate> entry : testFunctions.entrySet()) {
String id = entry.getKey();
FunctionTemplate fun = entry.getValue();
Scope functionScope = new Scope().withParent(testScope);
List<Variable> variables = fun.getArgs().stream().map(functionScope::create).collect(Collectors.toList());
try {
tester.registerFunction(id, new UserDefinedFunction(tester.parse(fun.getFunction(), functionScope), variables));
} catch(ParseException e) {
throw new ValidationException("Invalid function: ", e);
}
}
try {
tester.parse(noiseEquation, testScope);
} catch(ParseException e) {