reduce pipeline boilerplate

This commit is contained in:
dfsek
2021-01-21 20:00:51 -07:00
parent 8b501ddcde
commit 708ef16a1c
18 changed files with 234 additions and 90 deletions

View File

@@ -65,7 +65,7 @@ public class Vector2 implements Cloneable {
/**
* Add this vector to another.
*
* @param other Vector to add
* @param other Vector to increment
* @return Mutated vector, for chaining.
*/
public Vector2 add(Vector2 other) {

View File

@@ -1,51 +1,39 @@
package com.dfsek.terra.api.util.mutable;
public class MutableInteger extends Number implements MutablePrimitive<Integer> {
private int value;
public MutableInteger() {
public class MutableInteger extends MutableNumber<Integer> {
public MutableInteger(Integer value) {
super(value);
}
public MutableInteger(int init) {
this.value = init;
}
@Override
public int intValue() {
return value;
}
@Override
public long longValue() {
return value;
}
@Override
public float floatValue() {
return value;
}
@Override
public double doubleValue() {
return value;
}
@Override
public Integer get() {
return value;
}
@Override
public void set(Integer value) {
this.value = value;
}
public void add() {
public void increment() {
add(1);
}
public void decrement() {
add(-1);
}
@Override
public void add(Integer add) {
value += add;
}
@Override
public void multiply(Integer mul) {
value *= mul;
}
@Override
public void subtract(Integer sub) {
value -= sub;
}
@Override
public void divide(Integer divide) {
value /= divide;
}
public void add(int add) {
this.value += add;
value += add;
}
}

View File

@@ -0,0 +1,51 @@
package com.dfsek.terra.api.util.mutable;
public abstract class MutableNumber<T extends Number> extends Number implements MutablePrimitive<T> {
protected T value;
public MutableNumber(T value) {
this.value = value;
}
public abstract void increment();
public abstract void decrement();
public abstract void add(T add);
public abstract void multiply(T mul);
public abstract void subtract(T sub);
public abstract void divide(T divide);
@Override
public T get() {
return value;
}
@Override
public void set(T value) {
this.value = value;
}
@Override
public int intValue() {
return value.intValue();
}
@Override
public long longValue() {
return value.longValue();
}
@Override
public float floatValue() {
return value.floatValue();
}
@Override
public double doubleValue() {
return value.doubleValue();
}
}

View File

@@ -35,4 +35,6 @@ public interface Generator {
NoiseSampler getBiomeNoise();
double getElevationWeight();
int getBlendStep();
}

View File

@@ -76,7 +76,7 @@ public class StandardBiomeProvider implements BiomeProvider {
this.resolution = resolution;
}
public void setBuilder(NoiseBuilder builder) {
public void setBlender(NoiseBuilder builder) {
this.builder = builder;
}

View File

@@ -0,0 +1,46 @@
package com.dfsek.terra.biome.pipeline.mutator;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.Map;
public class BorderListMutator implements BiomeMutator {
private final String border;
private final NoiseSampler noiseSampler;
private final ProbabilityCollection<TerraBiome> replaceDefault;
private final String defaultReplace;
private final Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
public BorderListMutator(Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace, String border, String defaultReplace, NoiseSampler noiseSampler, ProbabilityCollection<TerraBiome> replaceDefault) {
this.border = border;
this.noiseSampler = noiseSampler;
this.replaceDefault = replaceDefault;
this.defaultReplace = defaultReplace;
this.replace = replace;
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
TerraBiome origin = viewPoint.getBiome(0, 0);
if(origin.getTags().contains(defaultReplace)) {
for(int xi = -1; xi <= 1; xi++) {
for(int zi = -1; zi <= 1; zi++) {
if(xi == 0 && zi == 0) continue;
TerraBiome current = viewPoint.getBiome(xi, zi);
if(current == null) continue;
if(current.getTags().contains(border)) {
if(replace.containsKey(origin)) {
TerraBiome biome = replace.get(origin).get(noiseSampler, x, z);
return biome == null ? origin : biome;
}
TerraBiome biome = replaceDefault.get(noiseSampler, x, z);
return biome == null ? origin : biome;
}
}
}
}
return origin;
}
}

View File

@@ -26,7 +26,10 @@ public class BorderMutator implements BiomeMutator {
if(xi == 0 && zi == 0) continue;
TerraBiome current = viewPoint.getBiome(xi, zi);
if(current == null) continue;
if(current.getTags().contains(border)) return replace.get(noiseSampler, x, z);
if(current.getTags().contains(border)) {
TerraBiome biome = replace.get(noiseSampler, x, z);
return biome == null ? origin : biome;
}
}
}
}

View File

@@ -0,0 +1,35 @@
package com.dfsek.terra.biome.pipeline.mutator;
import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.Map;
public class ReplaceListMutator implements BiomeMutator {
private final Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace;
private final NoiseSampler sampler;
private final ProbabilityCollection<TerraBiome> replaceDefault;
private final String defaultTag;
public ReplaceListMutator(Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace, String defaultTag, ProbabilityCollection<TerraBiome> replaceDefault, NoiseSampler sampler) {
this.replace = replace;
this.sampler = sampler;
this.defaultTag = defaultTag;
this.replaceDefault = replaceDefault;
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
TerraBiome center = viewPoint.getBiome(0, 0);
if(replace.containsKey(center)) {
TerraBiome biome = replace.get(center).get(sampler, x, z);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
if(viewPoint.getBiome(0, 0).getTags().contains(defaultTag)) {
TerraBiome biome = replaceDefault.get(sampler, x, z);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
return center;
}
}

View File

@@ -21,18 +21,6 @@ public class ConfigPackTemplate implements ConfigTemplate {
@Default
private Map<String, Double> variables = new HashMap<>();
@Value("blend.enable")
@Default
private boolean blend = false;
@Value("blend.frequency")
@Default
private double blendFreq = 0.1;
@Value("blend.amplitude")
@Default
private double blendAmp = 4.0D;
@Value("structures.locatable")
@Default
private Map<String, String> locatable = new HashMap<>();
@@ -132,18 +120,6 @@ public class ConfigPackTemplate implements ConfigTemplate {
return variables;
}
public boolean isBlend() {
return blend;
}
public double getBlendFreq() {
return blendFreq;
}
public double getBlendAmp() {
return blendAmp;
}
public boolean isErode() {
return erode;
}
@@ -160,7 +136,6 @@ public class ConfigPackTemplate implements ConfigTemplate {
return erodeOctaves;
}
public int getElevationBlend() {
return elevationBlend;
}

View File

@@ -38,13 +38,18 @@ public class GeneratorBuilder {
private int blendDistance;
private int blendStep;
public WorldGenerator build(long seed) {
synchronized(gens) {
return gens.computeIfAbsent(seed, k -> new WorldGenerator(seed, noiseEquation, elevationEquation, varScope, noiseBuilderMap, palettes, slantPalettes, noise2d, base, biomeNoise.build((int) seed), elevationWeight, blendDistance));
return gens.computeIfAbsent(seed, k -> new WorldGenerator(seed, noiseEquation, elevationEquation, varScope, noiseBuilderMap, palettes, slantPalettes, noise2d, base, biomeNoise.build((int) seed), elevationWeight, blendDistance, blendStep));
}
}
public void setBlendStep(int blendStep) {
this.blendStep = blendStep;
}
public void setBlendDistance(int blendDistance) {
this.blendDistance = blendDistance;
}

View File

@@ -29,6 +29,7 @@ public class BiomeFactory implements TerraFactory<BiomeTemplate, TerraBiome> {
generatorBuilder.setElevationWeight(template.getElevationWeight());
generatorBuilder.setBiomeNoise(template.getBiomeNoise());
generatorBuilder.setBlendDistance(template.getBlendDistance());
generatorBuilder.setBlendStep(template.getBlendStep());
return new UserDefinedBiome(template.getVanilla(), generatorBuilder, template);

View File

@@ -9,6 +9,7 @@ import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Set;
/**
@@ -23,6 +24,7 @@ public final class Types {
public static final Type FLORA_PROBABILITY_COLLECTION_TYPE;
public static final Type TREE_PROBABILITY_COLLECTION_TYPE;
public static final Type TERRA_BIOME_PROBABILITY_COLLECTION_TYPE;
public static final Type TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP;
static {
MATERIAL_SET_TYPE = getType("materialSet");
@@ -32,6 +34,7 @@ public final class Types {
FLORA_PROBABILITY_COLLECTION_TYPE = getType("floraProbabilityCollection");
TREE_PROBABILITY_COLLECTION_TYPE = getType("treeProbabilityCollection");
TERRA_BIOME_PROBABILITY_COLLECTION_TYPE = getType("terraBiomeProbabilityCollection");
TERRA_BIOME_TERRA_BIOME_PROBABILITY_COLLECTION_MAP = getType("terraBiomeProbabilityCollectionMap");
}
private Set<MaterialData> materialSet;
@@ -41,6 +44,7 @@ public final class Types {
private ProbabilityCollection<Flora> floraProbabilityCollection;
private ProbabilityCollection<Tree> treeProbabilityCollection;
private ProbabilityCollection<TerraBiome> terraBiomeProbabilityCollection;
private Map<TerraBiome, ProbabilityCollection<TerraBiome>> terraBiomeProbabilityCollectionMap;
private static Type getType(String dummyFieldName) {
try {

View File

@@ -12,7 +12,9 @@ import com.dfsek.terra.biome.ImageBiomeProvider;
import com.dfsek.terra.biome.StandardBiomeProvider;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.pipeline.expand.FractalExpander;
import com.dfsek.terra.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.biome.pipeline.source.RandomSource;
@@ -30,6 +32,7 @@ import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -46,7 +49,7 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
}
@Override
public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException {
public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) throws LoadException { // TODO: clean this up
Map<String, Object> map = (Map<String, Object>) c;
int resolution = 1;
@@ -79,17 +82,40 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
pipelineBuilder.addStage(new ExpanderStage(new FractalExpander(mutatorNoise)));
else throw new LoadException("No such expander \"" + mutator.get("type"));
} else if(entry.getKey().equals("mutate")) {
if(mutator.get("type").equals("SMOOTH"))
if(mutator.get("type").equals("SMOOTH")) {
pipelineBuilder.addStage(new MutatorStage(new SmoothMutator(mutatorNoise)));
else if(mutator.get("type").equals("REPLACE")) {
} else if(mutator.get("type").equals("REPLACE")) {
String fromTag = mutator.get("from").toString();
ProbabilityCollection<TerraBiome> replaceBiomes = new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("to"), loader);
pipelineBuilder.addStage(new MutatorStage(new ReplaceMutator(fromTag, replaceBiomes, mutatorNoise)));
} else if(mutator.get("type").equals("REPLACE_LIST")) {
String fromTag = mutator.get("default-from").toString();
ProbabilityCollection<TerraBiome> replaceBiomes = new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("default-to"), loader);
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace = new HashMap<>();
for(Map.Entry<String, Object> e : ((Map<String, Object>) mutator.get("to")).entrySet()) {
replace.put((TerraBiome) loader.loadType(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader));
}
pipelineBuilder.addStage(new MutatorStage(new ReplaceListMutator(replace, fromTag, replaceBiomes, mutatorNoise)));
} else if(mutator.get("type").equals("BORDER")) {
String fromTag = mutator.get("from").toString();
String replaceTag = mutator.get("replace").toString();
ProbabilityCollection<TerraBiome> replaceBiomes = (ProbabilityCollection<TerraBiome>) loader.loadType(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("to"));
ProbabilityCollection<TerraBiome> replaceBiomes = new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("to"), loader);
pipelineBuilder.addStage(new MutatorStage(new BorderMutator(fromTag, replaceTag, mutatorNoise, replaceBiomes)));
} else if(mutator.get("type").equals("BORDER_LIST")) {
String fromTag = mutator.get("from").toString();
String replaceTag = mutator.get("default-replace").toString();
ProbabilityCollection<TerraBiome> replaceBiomes = new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, mutator.get("default-to"), loader);
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replace = new HashMap<>();
for(Map.Entry<String, Object> e : ((Map<String, Object>) mutator.get("replace")).entrySet()) {
replace.put((TerraBiome) loader.loadType(TerraBiome.class, e.getKey()), new SelfProbabilityCollectionLoader<TerraBiome>().load(Types.TERRA_BIOME_PROBABILITY_COLLECTION_TYPE, e.getValue(), loader));
}
pipelineBuilder.addStage(new MutatorStage(new BorderListMutator(replace, fromTag, replaceTag, mutatorNoise, replaceBiomes)));
} else throw new LoadException("No such mutator type \"" + mutator.get("type"));
} else throw new LoadException("No such mutator \"" + entry.getKey() + "\"");
}
@@ -103,7 +129,7 @@ public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.Biom
Map<String, Object> blend = (Map<String, Object>) map.get("blend");
if(blend.containsKey("amplitude")) builder.setNoiseAmp(Integer.parseInt(blend.get("amplitude").toString()));
if(blend.containsKey("noise"))
builder.setBuilder(new NoiseBuilderLoader().load(NoiseBuilder.class, blend.get("noise"), loader));
builder.setBlender(new NoiseBuilderLoader().load(NoiseBuilder.class, blend.get("noise"), loader));
}
return builder;
} else if(map.get("type").equals("IMAGE")) {

View File

@@ -75,6 +75,10 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
@Default
private int blendDistance = 3;
@Value("blend.step")
@Default
private int blendStep = 4;
@Value("erode")
@Abstractable
@Default
@@ -284,6 +288,10 @@ public class BiomeTemplate extends AbstractableTemplate implements ValidatedConf
return elevationWeight;
}
public int getBlendStep() {
return blendStep;
}
@Override
public boolean validate() throws ValidationException {
color |= 0x1fe00000; // Alpha adjustment

View File

@@ -34,8 +34,9 @@ public class WorldGenerator implements Generator {
private final NoiseSampler biomeNoise;
private final double elevationWeight;
private final int blendDistance;
private final int blendStep;
public WorldGenerator(long seed, String equation, String elevateEquation, Scope vScope, Map<String, NoiseBuilder> noiseBuilders, PaletteHolder palettes, PaletteHolder slantPalettes, boolean noise2d, double base, NoiseSampler biomeNoise, double elevationWeight, int blendDistance) {
public WorldGenerator(long seed, String equation, String elevateEquation, Scope vScope, Map<String, NoiseBuilder> noiseBuilders, PaletteHolder palettes, PaletteHolder slantPalettes, boolean noise2d, double base, NoiseSampler biomeNoise, double elevationWeight, int blendDistance, int blendStep) {
this.palettes = palettes;
this.slantPalettes = slantPalettes;
@@ -44,6 +45,7 @@ public class WorldGenerator implements Generator {
this.biomeNoise = biomeNoise;
this.elevationWeight = elevationWeight;
this.blendDistance = blendDistance;
this.blendStep = blendStep;
Parser p = new Parser();
p.registerFunction("rand", new RandomFunction());
@@ -143,6 +145,11 @@ public class WorldGenerator implements Generator {
return elevationWeight;
}
@Override
public int getBlendStep() {
return blendStep;
}
public Palette<BlockData> getSlantPalette(int y) {
return slantPalettes.getPalette(y);
}

View File

@@ -10,7 +10,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* Class to abstract away the 16 Interpolators needed to generate a chunk.<br>
* Class to abstract away the Interpolators needed to generate a chunk.<br>
* Contains method to get interpolated noise at a coordinate within the chunk.
*/
public class ChunkInterpolator {
@@ -21,30 +21,25 @@ public class ChunkInterpolator {
*
* @param chunkX X coordinate of the chunk.
* @param chunkZ Z coordinate of the chunk.
* @param provider BiomeGrid to use for noise fetching.
* @param provider Biome Provider to use for biome fetching.
*/
public ChunkInterpolator(World w, int chunkX, int chunkZ, BiomeProvider provider) {
Generator[][] gens = new Generator[5][5];
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
gens[x][z] = provider.getBiome(xOrigin + (x * 4), zOrigin + (z * 4)).getGenerator(w);
}
}
double[][][] noiseStorage = new double[5][5][65];
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
Generator generator = gens[x][z];
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
Map<Generator, MutableInteger> genMap = new HashMap<>();
int step = generator.getBlendStep();
int blend = generator.getBlendDistance();
for(int xi = -blend; xi <= blend; xi++) {
for(int zi = -blend; zi <= blend; zi++) {
genMap.computeIfAbsent(provider.getBiome(xOrigin + ((x + xi) << 2), zOrigin + ((z + zi) << 2)).getGenerator(w), g -> new MutableInteger(0)).add(); // Increment by 1
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
}
}

View File

@@ -26,7 +26,7 @@ public abstract class TerraRegistry<T> implements TypeLoader<T> {
* Add an object to the registry with a name.
*
* @param name Name of the tree.
* @param value Object to add
* @param value Object to increment
* @return True if tree was overwritten.
*/
public boolean add(String name, T value) {

View File

@@ -22,7 +22,6 @@ import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.debug.Debug;
import com.dfsek.terra.registry.BiomeRegistry;
import org.junit.jupiter.api.Test;
import javax.swing.*;
import java.awt.*;
@@ -62,7 +61,6 @@ public class DistributionTest {
return template.getBiomeProviderBuilder().build(seed);
}
@Test
public static void main(String... args) throws ConfigException, IOException {
Debug.setLogger(Logger.getLogger("Terra"));
Debug.setDebug(true);