build biome config addon

This commit is contained in:
dfsek
2021-07-04 23:11:08 -07:00
parent 19d482f249
commit 3364a75cec
16 changed files with 63 additions and 156 deletions

View File

@@ -2,7 +2,6 @@ package com.dfsek.terra.addons.biome;
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;
@@ -14,18 +13,11 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.math.paralithic.BlankFunction;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.generator.Palette;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.world.population.items.TerraStructure;
import com.dfsek.terra.addons.flora.flora.FloraLayer;
import com.dfsek.terra.addons.ore.ores.OreHolder;
import com.dfsek.terra.addons.tree.tree.TreeLayer;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,7 +46,7 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Value("beta.carving.equation")
@Abstractable
@Default
private NoiseSeeded carvingEquation = NoiseSeeded.zero(2);
private NoiseSeeded carvingEquation = NoiseSeeded.zero(3);
@Value("palette")
@Abstractable
@@ -98,10 +90,10 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Abstractable
private NoiseSeeded noiseEquation;
@Value("ores")
/*@Value("ores")
@Abstractable
@Default
private OreHolder oreHolder = new OreHolder();
private OreHolder oreHolder = new OreHolder();*/
@Value("ocean.level")
@Abstractable
@@ -115,22 +107,22 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Value("elevation.equation")
@Default
@Abstractable
private String elevationEquation = null;
private NoiseSeeded elevationEquation = NoiseSeeded.zero(2);
@Value("elevation.weight")
@Default
@Abstractable
private double elevationWeight = 1;
@Value("flora")
/*@Value("flora")
@Abstractable
@Default
private List<FloraLayer> flora = new GlueList<>();
private List<FloraLayer> flora = new ArrayList<>();
@Value("trees")
@Abstractable
@Default
private List<TreeLayer> trees = new GlueList<>();
private List<TreeLayer> trees = new ArrayList<>();*/
@Value("slabs.enable")
@Abstractable
@@ -166,10 +158,10 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
@Abstractable
private Set<String> tags = new HashSet<>();
@Value("carving")
/*@Value("carving")
@Abstractable
@Default
private Map<UserDefinedCarver, Integer> carvers = new HashMap<>();
private Map<UserDefinedCarver, Integer> carvers = new HashMap<>();*/
@Value("colors")
@Abstractable
@@ -188,10 +180,6 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return colors;
}
public Map<UserDefinedCarver, Integer> getCarvers() {
return carvers;
}
public double getBlendWeight() {
return blendWeight;
}
@@ -216,10 +204,6 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return slabThreshold;
}
public List<FloraLayer> getFlora() {
return flora;
}
public boolean doSlabs() {
return doSlabs;
}
@@ -240,11 +224,11 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return biomeNoise;
}
public String getElevationEquation() {
public NoiseSeeded getElevationEquation() {
return elevationEquation;
}
public String getCarvingEquation() {
public NoiseSeeded getCarvingEquation() {
return carvingEquation;
}
@@ -268,10 +252,6 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return palette;
}
public List<TreeLayer> getTrees() {
return trees;
}
public ProbabilityCollection<Biome> getVanilla() {
return vanilla;
}
@@ -284,10 +264,6 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
return noiseEquation;
}
public OreHolder getOreHolder() {
return oreHolder;
}
public double getElevationWeight() {
return elevationWeight;
}
@@ -304,7 +280,7 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
public boolean validate() throws ValidationException {
color |= 0xff000000; // Alpha adjustment
Parser tester = new Parser();
Scope testScope = new Scope().withParent(pack.getVarScope());
Scope testScope = new Scope();
variables.forEach(testScope::create);
@@ -313,24 +289,24 @@ public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTempl
testScope.addInvocationVariable("z");
pack.getTemplate().getNoiseBuilderMap().forEach((id, builder) -> tester.registerFunction(id, new BlankFunction(builder.getDimensions()))); // Register dummy functions
//pack.getTemplate().getNoiseBuilderMap().forEach((id, builder) -> tester.registerFunction(id, new BlankFunction(builder.getDimensions()))); // Register dummy functions
try {
tester.parse(noiseEquation, testScope);
} catch(ParseException e) {
throw new ValidationException("Invalid noise equation: ", e);
noiseEquation.apply(0L);
} catch(Exception e) {
throw new ValidationException("Invalid noise sampler: ", e);
}
try {
tester.parse(carvingEquation, testScope);
} catch(ParseException e) {
throw new ValidationException("Invalid carving equation: ", e);
carvingEquation.apply(0L);
} catch(Exception e) {
throw new ValidationException("Invalid carving sampler: ", e);
}
try {
if(elevationEquation != null) tester.parse(elevationEquation, testScope);
} catch(ParseException e) {
throw new ValidationException("Invalid elevation equation: ", e);
elevationEquation.apply(0L);
} catch(Exception e) {
throw new ValidationException("Invalid elevation sampler: ", e);
}
return true;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.addons.noise.paralithic;
package com.dfsek.terra.addons.biome;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;

View File

@@ -1,21 +0,0 @@
package com.dfsek.terra.addons.biome;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.range.ConstantRange;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.addons.ore.ores.OreConfig;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class OreConfigLoader implements TypeLoader<OreConfig> {
@Override
public OreConfig load(Type type, Object o, ConfigLoader configLoader) {
Map<String, Integer> map = (Map<String, Integer>) o;
Range amount = new ConstantRange(map.get("min"), map.get("max"));
Range height = new ConstantRange(map.get("min-height"), map.get("max-height"));
return new OreConfig(amount, height);
}
}

View File

@@ -1,26 +0,0 @@
package com.dfsek.terra.addons.biome;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.addons.ore.ores.Ore;
import com.dfsek.terra.addons.ore.ores.OreConfig;
import com.dfsek.terra.addons.ore.ores.OreHolder;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class OreHolderLoader implements TypeLoader<OreHolder> {
@Override
public OreHolder load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
OreHolder holder = new OreHolder();
Map<String, Object> map = (Map<String, Object>) o;
for(Map.Entry<String, Object> entry : map.entrySet()) {
holder.add(configLoader.loadClass(Ore.class, entry.getKey()), configLoader.loadClass(OreConfig.class, entry.getValue()), entry.getKey());
}
return holder;
}
}

View File

@@ -0,0 +1,18 @@
package com.dfsek.terra.addons.biome;
import com.dfsek.terra.addons.biome.holder.PaletteHolder;
import com.dfsek.terra.api.world.biome.PaletteSettings;
import com.dfsek.terra.api.world.generator.Palette;
public class PaletteSettingsImpl implements PaletteSettings {
private final PaletteHolder palette;
public PaletteSettingsImpl(PaletteHolder palette) {
this.palette = palette;
}
@Override
public Palette getPalette(int y) {
return palette.getPalette(y);
}
}

View File

@@ -5,8 +5,6 @@ import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.Set;

View File

@@ -1,21 +1,10 @@
package com.dfsek.terra.addons.biome;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.pack.ConfigPackImpl;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.noise.samplers.ExpressionSampler;
import com.dfsek.terra.world.generation.WorldGenerator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -35,25 +24,7 @@ public class UserDefinedBiomeBuilder implements BiomeBuilder {
synchronized(biomeMap) {
return biomeMap.computeIfAbsent(seed,
s -> {
NoiseSampler noise;
NoiseSampler elevation;
NoiseSampler carving;
Scope varScope = new Scope().withParent(pack.getVarScope());
template.getVariables().forEach(varScope::create);
Map<String, NoiseSeeded> noiseBuilderMap = pack.getTemplate().getNoiseBuilderMap();
try {
noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap);
elevation = template.getElevationEquation() == null ? NoiseSampler.zero() : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap);
carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap);
} catch(ParseException e) {
throw new RuntimeException(e);
}
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlant(), noise, elevation, carving, template.getBiomeNoise().apply(seed), template.getElevationWeight(),
WorldGenerator generator = new WorldGenerator(template.getPalette(), template.getSlant(), template.getNoiseEquation().apply(seed), template.getElevationEquation().apply(seed), template.getCarvingEquation().apply(seed), template.getBiomeNoise().apply(seed), template.getElevationWeight(),
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
return new UserDefinedBiome(template.getVanilla(), generator, template);
}

View File

@@ -4,12 +4,10 @@ import com.dfsek.terra.addons.biome.holder.PaletteHolder;
import com.dfsek.terra.addons.biome.slant.SlantHolder;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.api.world.generator.Palette;
import com.dfsek.terra.api.world.biome.PaletteSettings;
public class WorldGenerator implements Generator {
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
private final PaletteHolder palettes;
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
private final PaletteSettings paletteSettings;
private final SlantHolder slantPalettes;
private final NoiseSampler noise;
@@ -23,7 +21,7 @@ public class WorldGenerator implements Generator {
private final double blendWeight;
public WorldGenerator(PaletteHolder palettes, SlantHolder slantPalettes, NoiseSampler noise, NoiseSampler elevation, NoiseSampler carving, NoiseSampler biomeNoise, double elevationWeight, int blendDistance, int blendStep, double blendWeight) {
this.palettes = palettes;
this.paletteSettings = new PaletteSettingsImpl(palettes);
this.slantPalettes = slantPalettes;
this.noise = noise;
this.elevation = elevation;
@@ -61,14 +59,9 @@ public class WorldGenerator implements Generator {
return blendWeight;
}
/**
* Gets the BlockPalette to generate the biome with.
*
* @return BlockPalette - The biome's palette.
*/
@Override
public Palette getPalette(int y) {
return palettes.getPalette(y);
public PaletteSettings getPaletteSettings() {
return paletteSettings;
}
@Override

View File

@@ -0,0 +1,38 @@
package com.dfsek.terra.addons.biome.command.biome;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
/**
* Runnable that locates a biome asynchronously
*/
public class AsyncBiomeFinder extends AsyncFeatureFinder<TerraBiome> {
public AsyncBiomeFinder(BiomeProvider provider, TerraBiome target, @NotNull Vector3 origin, World world, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
super(provider, target, origin, world, startRadius, maxRadius, callback, main);
}
/**
* Helper method to get biome at location
*
* @param x X coordinate
* @param z Z coordinate
* @return TerraBiome at coordinates
*/
@Override
public boolean isValid(int x, int z, TerraBiome target) {
int res = main.getTerraConfig().getBiomeSearchResolution();
return getProvider().getBiome(x * res, z * res).equals(target);
}
@Override
public Vector3 finalizeVector(Vector3 orig) {
return orig.multiply(main.getTerraConfig().getBiomeSearchResolution());
}
}

View File

@@ -0,0 +1,96 @@
package com.dfsek.terra.addons.biome.command.biome;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public abstract class AsyncFeatureFinder<T> implements Runnable {
protected final BiomeProvider provider;
protected final T target;
protected final int startRadius;
protected final int maxRadius;
protected final int centerX;
protected final int centerZ;
protected final World world;
private final Consumer<Vector3> callback;
protected int searchSize = 1;
protected final TerraPlugin main;
public AsyncFeatureFinder(BiomeProvider provider, T target, @NotNull Vector3 origin, World world, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
this.provider = provider;
this.target = target;
this.main = main;
this.startRadius = startRadius;
this.maxRadius = maxRadius;
this.centerX = origin.getBlockX();
this.centerZ = origin.getBlockZ();
this.world = world;
this.callback = callback;
}
@Override
public void run() {
int x = centerX;
int z = centerZ;
x /= searchSize;
z /= searchSize;
int run = 1;
boolean toggle = true;
boolean found = false;
main:
for(int i = startRadius; i < maxRadius; i++) {
for(int j = 0; j < run; j++) {
if(isValid(x, z, target)) {
found = true;
break main;
}
if(toggle) x += 1;
else x -= 1;
}
for(int j = 0; j < run; j++) {
if(isValid(x, z, target)) {
found = true;
break main;
}
if(toggle) z += 1;
else z -= 1;
}
run++;
toggle = !toggle;
}
Vector3 finalSpawn = found ? finalizeVector(new Vector3(x, 0, z)) : null;
callback.accept(finalSpawn);
}
public abstract Vector3 finalizeVector(Vector3 orig);
public abstract boolean isValid(int x, int z, T target);
public T getTarget() {
return target;
}
public World getWorld() {
return world;
}
public BiomeProvider getProvider() {
return provider;
}
public int getSearchSize() {
return searchSize;
}
public void setSearchSize(int searchSize) {
this.searchSize = searchSize;
}
}

View File

@@ -1,5 +1,6 @@
package com.dfsek.terra.addons.biome.command.biome;
import com.dfsek.terra.addons.biome.UserDefinedBiome;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Command;
@@ -9,9 +10,7 @@ import com.dfsek.terra.api.command.annotation.type.WorldCommand;
import com.dfsek.terra.api.entity.CommandSender;
import com.dfsek.terra.api.entity.Player;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.config.lang.LangUtil;
@Command(
subcommands = {
@@ -40,6 +39,6 @@ public class BiomeCommand implements CommandTemplate {
BiomeProvider provider = main.getWorld(player.world()).getBiomeProvider();
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.position());
LangUtil.send("command.biome.in", sender, biome.getID());
sender.sendMessage("You are standing in " + biome.getID());
}
}

View File

@@ -1,5 +1,9 @@
package com.dfsek.terra.addons.biome.command.biome;
import com.dfsek.terra.addons.biome.BiomeTemplate;
import com.dfsek.terra.addons.biome.UserDefinedBiome;
import com.dfsek.terra.addons.biome.command.biome.arg.BiomeArgumentParser;
import com.dfsek.terra.addons.biome.command.biome.tab.BiomeTabCompleter;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Argument;
import com.dfsek.terra.api.command.annotation.Command;
@@ -7,9 +11,6 @@ import com.dfsek.terra.api.command.annotation.inject.ArgumentTarget;
import com.dfsek.terra.api.entity.CommandSender;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.world.population.items.TerraStructure;
import java.util.List;
@@ -47,8 +48,8 @@ public class BiomeInfoCommand implements CommandTemplate {
sender.sendMessage("No Structures");
} else {
sender.sendMessage("-------Structures-------");
for(TerraStructure c : structureConfigs) {
sender.sendMessage(" - " + c.getTemplate().getID());
for(ConfiguredStructure c : structureConfigs) {
sender.sendMessage(" - " + c);
}
}
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.addons.biome.command.biome;
import com.dfsek.terra.addons.biome.command.biome.arg.BiomeArgumentParser;
import com.dfsek.terra.addons.biome.command.biome.tab.BiomeTabCompleter;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.command.CommandTemplate;
import com.dfsek.terra.api.command.annotation.Argument;
@@ -16,9 +17,6 @@ import com.dfsek.terra.api.entity.Player;
import com.dfsek.terra.api.injection.annotations.Inject;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.locate.AsyncBiomeFinder;
import com.dfsek.terra.addons.biome.command.biome.tab.BiomeTabCompleter;
import com.dfsek.terra.config.lang.LangUtil;
import java.util.Locale;
@@ -70,7 +68,7 @@ public class BiomeLocateCommand implements CommandTemplate {
if(teleport) {
main.runPossiblyUnsafeTask(() -> player.position(new Vector3(location.getX(), player.position().getY(), location.getZ())));
}
} else LangUtil.send("command.biome.unable-to-locate", sender);
} else sender.sendMessage("Unable to locate biome \"" + biome.getID() + "\"");
}, main), "Biome Location Thread").start();
}

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.addons.biome;
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.ProbabilityCollection;

View File

@@ -1,4 +1,4 @@
package com.dfsek.terra.addons.biome;
package com.dfsek.terra.addons.biome.pipeline.config;
import com.dfsek.tectonic.loading.object.ObjectTemplate;
import com.dfsek.terra.api.util.seeded.SourceSeeded;

View File

@@ -4,6 +4,8 @@ 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.addons.carver.carving.Carver;
import com.dfsek.terra.addons.carver.carving.Worm;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2;
@@ -15,8 +17,6 @@ import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.biome.UserDefinedBiome;
import com.dfsek.terra.api.world.carving.Carver;
import com.dfsek.terra.api.world.carving.Worm;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import net.jafama.FastMath;