mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-08-30 05:40:34 +00:00
move more things to new modules
This commit is contained in:
+19
@@ -0,0 +1,19 @@
|
||||
package com.dfsek.terra.addons.biome;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.config.ConfigFactory;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder> {
|
||||
private final ConfigPack pack;
|
||||
|
||||
public BiomeFactory(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) {
|
||||
return new UserDefinedBiomeBuilder(template, pack);
|
||||
}
|
||||
}
|
||||
+338
@@ -0,0 +1,338 @@
|
||||
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;
|
||||
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
|
||||
import com.dfsek.tectonic.exception.ValidationException;
|
||||
import com.dfsek.terra.addons.biome.holder.PaletteHolder;
|
||||
import com.dfsek.terra.addons.biome.slant.SlantHolder;
|
||||
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.world.population.items.flora.FloraLayer;
|
||||
import com.dfsek.terra.world.population.items.ores.OreHolder;
|
||||
import com.dfsek.terra.world.population.items.tree.TreeLayer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressWarnings({"FieldMayBeFinal", "unused"})
|
||||
public class BiomeTemplate implements AbstractableTemplate, ValidatedConfigTemplate {
|
||||
private final ConfigPack pack;
|
||||
|
||||
@Value("id")
|
||||
private String id;
|
||||
|
||||
@Value("extends")
|
||||
@Default
|
||||
private List<String> extended = Collections.emptyList();
|
||||
|
||||
@Value("variables")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<String, Double> variables = new HashMap<>();
|
||||
|
||||
@Value("beta.carving.equation")
|
||||
@Abstractable
|
||||
@Default
|
||||
private NoiseSeeded carvingEquation = NoiseSeeded.zero(2);
|
||||
|
||||
@Value("palette")
|
||||
@Abstractable
|
||||
private PaletteHolder palette;
|
||||
|
||||
@Value("slant")
|
||||
@Abstractable
|
||||
@Default
|
||||
private SlantHolder slant = null;
|
||||
|
||||
@Value("vanilla")
|
||||
@Abstractable
|
||||
private ProbabilityCollection<Biome> vanilla;
|
||||
|
||||
@Value("biome-noise")
|
||||
@Default
|
||||
@Abstractable
|
||||
private NoiseSeeded biomeNoise = NoiseSeeded.zero(2);
|
||||
|
||||
@Value("blend.distance")
|
||||
@Abstractable
|
||||
@Default
|
||||
private int blendDistance = 3;
|
||||
|
||||
@Value("blend.weight")
|
||||
@Abstractable
|
||||
@Default
|
||||
private double blendWeight = 1;
|
||||
|
||||
@Value("blend.step")
|
||||
@Abstractable
|
||||
@Default
|
||||
private int blendStep = 4;
|
||||
|
||||
@Value("structures")
|
||||
@Abstractable
|
||||
@Default
|
||||
private List<ConfiguredStructure> structures = new ArrayList<>();
|
||||
|
||||
@Value("noise")
|
||||
@Abstractable
|
||||
private NoiseSeeded noiseEquation;
|
||||
|
||||
@Value("ores")
|
||||
@Abstractable
|
||||
@Default
|
||||
private OreHolder oreHolder = new OreHolder();
|
||||
|
||||
@Value("ocean.level")
|
||||
@Abstractable
|
||||
@Default
|
||||
private int seaLevel = 62;
|
||||
|
||||
@Value("ocean.palette")
|
||||
@Abstractable
|
||||
private Palette oceanPalette;
|
||||
|
||||
@Value("elevation.equation")
|
||||
@Default
|
||||
@Abstractable
|
||||
private String elevationEquation = null;
|
||||
|
||||
@Value("elevation.weight")
|
||||
@Default
|
||||
@Abstractable
|
||||
private double elevationWeight = 1;
|
||||
|
||||
@Value("flora")
|
||||
@Abstractable
|
||||
@Default
|
||||
private List<FloraLayer> flora = new GlueList<>();
|
||||
|
||||
@Value("trees")
|
||||
@Abstractable
|
||||
@Default
|
||||
private List<TreeLayer> trees = new GlueList<>();
|
||||
|
||||
@Value("slabs.enable")
|
||||
@Abstractable
|
||||
@Default
|
||||
private boolean doSlabs = false;
|
||||
|
||||
@Value("slabs.threshold")
|
||||
@Abstractable
|
||||
@Default
|
||||
private double slabThreshold = 0.0075D;
|
||||
|
||||
@Value("slabs.palettes")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<BlockType, Palette> slabPalettes;
|
||||
|
||||
@Value("slabs.stair-palettes")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<BlockType, Palette> stairPalettes;
|
||||
|
||||
@Value("interpolate-elevation")
|
||||
@Abstractable
|
||||
@Default
|
||||
private boolean interpolateElevation = true;
|
||||
|
||||
@Value("color")
|
||||
@Default
|
||||
private int color = 0;
|
||||
|
||||
@Value("tags")
|
||||
@Default
|
||||
@Abstractable
|
||||
private Set<String> tags = new HashSet<>();
|
||||
|
||||
@Value("carving")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<UserDefinedCarver, Integer> carvers = new HashMap<>();
|
||||
|
||||
@Value("colors")
|
||||
@Abstractable
|
||||
@Default
|
||||
private Map<String, Integer> colors = new HashMap<>(); // Plain ol' map, so platforms can decide what to do with colors (if anything).
|
||||
|
||||
public List<String> getExtended() {
|
||||
return extended;
|
||||
}
|
||||
|
||||
public Set<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getColors() {
|
||||
return colors;
|
||||
}
|
||||
|
||||
public Map<UserDefinedCarver, Integer> getCarvers() {
|
||||
return carvers;
|
||||
}
|
||||
|
||||
public double getBlendWeight() {
|
||||
return blendWeight;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public int getBlendDistance() {
|
||||
return blendDistance;
|
||||
}
|
||||
|
||||
public boolean interpolateElevation() {
|
||||
return interpolateElevation;
|
||||
}
|
||||
|
||||
public SlantHolder getSlant() {
|
||||
return slant;
|
||||
}
|
||||
|
||||
public double getSlabThreshold() {
|
||||
return slabThreshold;
|
||||
}
|
||||
|
||||
public List<FloraLayer> getFlora() {
|
||||
return flora;
|
||||
}
|
||||
|
||||
public boolean doSlabs() {
|
||||
return doSlabs;
|
||||
}
|
||||
|
||||
public BiomeTemplate(ConfigPack pack, TerraPlugin main) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
public Map<BlockType, Palette> getSlabPalettes() {
|
||||
return slabPalettes;
|
||||
}
|
||||
|
||||
public Map<BlockType, Palette> getStairPalettes() {
|
||||
return stairPalettes;
|
||||
}
|
||||
|
||||
public NoiseSeeded getBiomeNoise() {
|
||||
return biomeNoise;
|
||||
}
|
||||
|
||||
public String getElevationEquation() {
|
||||
return elevationEquation;
|
||||
}
|
||||
|
||||
public String getCarvingEquation() {
|
||||
return carvingEquation;
|
||||
}
|
||||
|
||||
public ConfigPack getPack() {
|
||||
return pack;
|
||||
}
|
||||
|
||||
public int getSeaLevel() {
|
||||
return seaLevel;
|
||||
}
|
||||
|
||||
public Palette getOceanPalette() {
|
||||
return oceanPalette;
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public PaletteHolder getPalette() {
|
||||
return palette;
|
||||
}
|
||||
|
||||
public List<TreeLayer> getTrees() {
|
||||
return trees;
|
||||
}
|
||||
|
||||
public ProbabilityCollection<Biome> getVanilla() {
|
||||
return vanilla;
|
||||
}
|
||||
|
||||
public List<ConfiguredStructure> getStructures() {
|
||||
return structures;
|
||||
}
|
||||
|
||||
public NoiseSeeded getNoiseEquation() {
|
||||
return noiseEquation;
|
||||
}
|
||||
|
||||
public OreHolder getOreHolder() {
|
||||
return oreHolder;
|
||||
}
|
||||
|
||||
public double getElevationWeight() {
|
||||
return elevationWeight;
|
||||
}
|
||||
|
||||
public int getBlendStep() {
|
||||
return blendStep;
|
||||
}
|
||||
|
||||
public Map<String, Double> getVariables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validate() throws ValidationException {
|
||||
color |= 0xff000000; // Alpha adjustment
|
||||
Parser tester = new Parser();
|
||||
Scope testScope = new Scope().withParent(pack.getVarScope());
|
||||
|
||||
variables.forEach(testScope::create);
|
||||
|
||||
testScope.addInvocationVariable("x");
|
||||
testScope.addInvocationVariable("y");
|
||||
testScope.addInvocationVariable("z");
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
try {
|
||||
tester.parse(carvingEquation, testScope);
|
||||
} catch(ParseException e) {
|
||||
throw new ValidationException("Invalid carving equation: ", e);
|
||||
}
|
||||
|
||||
try {
|
||||
if(elevationEquation != null) tester.parse(elevationEquation, testScope);
|
||||
} catch(ParseException e) {
|
||||
throw new ValidationException("Invalid elevation equation: ", e);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.dfsek.terra.addons.biome;
|
||||
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Class representing a config-defined biome
|
||||
*/
|
||||
public class UserDefinedBiome implements TerraBiome {
|
||||
private final WorldGenerator gen;
|
||||
private final ProbabilityCollection<Biome> vanilla;
|
||||
private final String id;
|
||||
private final BiomeTemplate config;
|
||||
private final int color;
|
||||
private final Set<String> tags;
|
||||
|
||||
|
||||
public UserDefinedBiome(ProbabilityCollection<Biome> vanilla, WorldGenerator gen, BiomeTemplate config) {
|
||||
this.vanilla = vanilla;
|
||||
this.gen = gen;
|
||||
this.id = config.getID();
|
||||
this.config = config;
|
||||
this.color = config.getColor();
|
||||
this.tags = config.getTags();
|
||||
tags.add("BIOME:" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Vanilla biomes to represent the custom biome.
|
||||
*
|
||||
* @return Collection of biomes to represent the custom biome.
|
||||
*/
|
||||
@Override
|
||||
public ProbabilityCollection<Biome> getVanillaBiomes() {
|
||||
return vanilla;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public BiomeTemplate getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Generator getGenerator(World w) {
|
||||
return gen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "{BIOME:" + getID() + "}";
|
||||
}
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
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;
|
||||
|
||||
public class UserDefinedBiomeBuilder implements BiomeBuilder {
|
||||
private final BiomeTemplate template;
|
||||
private final ConfigPack pack;
|
||||
|
||||
private final Map<Long, UserDefinedBiome> biomeMap = new ConcurrentHashMap<>();
|
||||
|
||||
public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPack pack) {
|
||||
this.template = template;
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDefinedBiome apply(Long seed) {
|
||||
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(),
|
||||
template.getBlendDistance(), template.getBlendStep(), template.getBlendWeight());
|
||||
return new UserDefinedBiome(template.getVanilla(), generator, template);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProbabilityCollection<Biome> getVanillaBiomes() {
|
||||
return template.getVanilla();
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.dfsek.terra.addons.biome;
|
||||
|
||||
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;
|
||||
|
||||
public class WorldGenerator implements Generator {
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final PaletteHolder palettes;
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final SlantHolder slantPalettes;
|
||||
|
||||
private final NoiseSampler noise;
|
||||
private final NoiseSampler elevation;
|
||||
private final NoiseSampler carving;
|
||||
|
||||
private final NoiseSampler biomeNoise;
|
||||
private final double elevationWeight;
|
||||
private final int blendDistance;
|
||||
private final int blendStep;
|
||||
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.slantPalettes = slantPalettes;
|
||||
this.noise = noise;
|
||||
this.elevation = elevation;
|
||||
this.carving = carving;
|
||||
|
||||
this.biomeNoise = biomeNoise;
|
||||
this.elevationWeight = elevationWeight;
|
||||
this.blendDistance = blendDistance;
|
||||
this.blendStep = blendStep;
|
||||
this.blendWeight = blendWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler getBaseSampler() {
|
||||
return noise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler getElevationSampler() {
|
||||
return elevation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler getCarver() {
|
||||
return carving;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlendDistance() {
|
||||
return blendDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWeight() {
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoiseSampler getBiomeNoise() {
|
||||
return biomeNoise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getElevationWeight() {
|
||||
return elevationWeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlendStep() {
|
||||
return blendStep;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.dfsek.terra.addons.biome.holder;
|
||||
|
||||
import com.dfsek.terra.api.world.generator.Palette;
|
||||
|
||||
public class PaletteHolder {
|
||||
private final Palette[] palettes;
|
||||
private final int offset;
|
||||
|
||||
protected PaletteHolder(Palette[] palettes, int offset) {
|
||||
this.palettes = palettes;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public Palette getPalette(int y) {
|
||||
int index = y + offset;
|
||||
return index >= 0
|
||||
? index < palettes.length
|
||||
? palettes[index]
|
||||
: palettes[palettes.length - 1]
|
||||
: palettes[0];
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package com.dfsek.terra.addons.biome.holder;
|
||||
|
||||
import com.dfsek.terra.api.world.generator.Palette;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class PaletteHolderBuilder {
|
||||
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();
|
||||
|
||||
public PaletteHolderBuilder add(int y, Palette palette) {
|
||||
paletteMap.put(y, palette);
|
||||
return this;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
public PaletteHolder build() {
|
||||
|
||||
int min = FastMath.min(paletteMap.keySet().stream().min(Integer::compareTo).orElse(0), 0);
|
||||
int max = FastMath.max(paletteMap.keySet().stream().max(Integer::compareTo).orElse(255), 255);
|
||||
|
||||
Palette[] palettes = new Palette[paletteMap.lastKey() + 1 - min];
|
||||
for(int y = min; y <= FastMath.max(paletteMap.lastKey(), max); y++) {
|
||||
Palette d = null;
|
||||
for(Map.Entry<Integer, Palette> e : paletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
d = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(d == null) throw new IllegalArgumentException("No palette for Y=" + y);
|
||||
palettes[y - min] = d;
|
||||
}
|
||||
return new PaletteHolder(palettes, -min);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package com.dfsek.terra.addons.biome.holder;
|
||||
|
||||
import com.dfsek.terra.api.block.state.BlockState;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PaletteLayerHolder {
|
||||
private final ProbabilityCollection<BlockState> layer;
|
||||
private final NoiseSampler sampler;
|
||||
private final int size;
|
||||
|
||||
public PaletteLayerHolder(@NotNull ProbabilityCollection<BlockState> layer, NoiseSampler sampler, int size) {
|
||||
this.layer = layer;
|
||||
this.sampler = sampler;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProbabilityCollection<BlockState> getLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public NoiseSampler getSampler() {
|
||||
return sampler;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.dfsek.terra.addons.biome.slant;
|
||||
|
||||
import com.dfsek.terra.addons.biome.holder.PaletteHolder;
|
||||
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class SlantHolder {
|
||||
private final TreeMap<Double, PaletteHolder> layers;
|
||||
private final double minSlope;
|
||||
|
||||
public SlantHolder(TreeMap<Double, PaletteHolder> layers, double minSlope) {
|
||||
this.layers = layers;
|
||||
this.minSlope = minSlope;
|
||||
}
|
||||
|
||||
public PaletteHolder getPalette(double slope) {
|
||||
return layers.floorEntry(slope).getValue();
|
||||
}
|
||||
|
||||
public double getMinSlope() {
|
||||
return minSlope;
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.dfsek.terra.addons.biome.image;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class ImageBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder { // This provider does not need a seed, so it is its own builder.
|
||||
private final Map<Color, TerraBiome> colorBiomeMap = new HashMap<>();
|
||||
private final BufferedImage image;
|
||||
private final int resolution;
|
||||
private final Align align;
|
||||
|
||||
public ImageBiomeProvider(Set<TerraBiome> registry, BufferedImage image, int resolution, Align align) {
|
||||
this.image = image;
|
||||
this.resolution = resolution;
|
||||
this.align = align;
|
||||
registry.forEach(biome -> colorBiomeMap.put(new Color(biome.getColor()), biome));
|
||||
}
|
||||
|
||||
private static int distance(Color a, Color b) {
|
||||
return FastMath.abs(a.getRed() - b.getRed()) + FastMath.abs(a.getGreen() - b.getGreen()) + FastMath.abs(a.getBlue() - b.getBlue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBiome(int x, int z) {
|
||||
x /= resolution;
|
||||
z /= resolution;
|
||||
Color color = align.getColor(image, x, z);
|
||||
return colorBiomeMap.get(colorBiomeMap.keySet().stream().reduce(colorBiomeMap.keySet().stream().findAny().orElseThrow(IllegalStateException::new), (running, element) -> {
|
||||
int d1 = distance(color, running);
|
||||
int d2 = distance(color, element);
|
||||
return d1 < d2 ? running : element;
|
||||
}));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider build(long seed) {
|
||||
return this;
|
||||
}
|
||||
|
||||
public enum Align {
|
||||
CENTER {
|
||||
@Override
|
||||
public Color getColor(BufferedImage image, int x, int z) {
|
||||
return new Color(image.getRGB(FastMath.floorMod(x - image.getWidth() / 2, image.getWidth()), FastMath.floorMod(z - image.getHeight() / 2, image.getHeight())));
|
||||
}
|
||||
}, NONE {
|
||||
@Override
|
||||
public Color getColor(BufferedImage image, int x, int z) {
|
||||
return new Color(image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(z, image.getHeight())));
|
||||
}
|
||||
};
|
||||
|
||||
public abstract Color getColor(BufferedImage image, int x, int z);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.dfsek.terra.addons.biome.image;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.registry.Registry;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ImageProviderTemplate extends BiomeProviderTemplate {
|
||||
private final Registry<BiomeBuilder> biomes;
|
||||
@Value("image.name")
|
||||
private BufferedImage image;
|
||||
|
||||
@Value("image.align")
|
||||
private ImageBiomeProvider.Align align;
|
||||
|
||||
public ImageProviderTemplate(Registry<BiomeBuilder> set) {
|
||||
this.biomes = set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider build(long seed) {
|
||||
return new ImageBiomeProvider(biomes.entries().stream().map(biomeBuilder -> biomeBuilder.apply(seed)).collect(Collectors.toSet()), image, resolution, align);
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline;
|
||||
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeExpander;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
|
||||
|
||||
public class BiomeHolderImpl implements BiomeHolder {
|
||||
private final Vector2 origin;
|
||||
private final int width;
|
||||
private TerraBiome[][] biomes;
|
||||
private final int offset;
|
||||
|
||||
public BiomeHolderImpl(int width, Vector2 origin) {
|
||||
width += 4;
|
||||
this.width = width;
|
||||
biomes = new TerraBiome[width][width];
|
||||
this.origin = origin;
|
||||
this.offset = 2;
|
||||
}
|
||||
|
||||
private BiomeHolderImpl(TerraBiome[][] biomes, Vector2 origin, int width, int offset) {
|
||||
this.biomes = biomes;
|
||||
this.origin = origin;
|
||||
this.width = width;
|
||||
this.offset = 2 * offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeHolder expand(BiomeExpander expander) {
|
||||
TerraBiome[][] old = biomes;
|
||||
int newWidth = width * 2 - 1;
|
||||
|
||||
biomes = new TerraBiome[newWidth][newWidth];
|
||||
|
||||
for(int x = 0; x < width; x++) {
|
||||
for(int z = 0; z < width; z++) {
|
||||
biomes[x * 2][z * 2] = old[x][z];
|
||||
if(z != width - 1)
|
||||
biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x][z + 1]);
|
||||
if(x != width - 1)
|
||||
biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), old[x][z], old[x + 1][z]);
|
||||
if(x != width - 1 && z != width - 1)
|
||||
biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]);
|
||||
}
|
||||
}
|
||||
return new BiomeHolderImpl(biomes, origin.setX(origin.getX() * 2 - 1).setZ(origin.getZ() * 2 - 1), newWidth, offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mutate(BiomeMutator mutator) {
|
||||
for(int x = 0; x < width; x++) {
|
||||
for(int z = 0; z < width; z++) {
|
||||
BiomeMutator.ViewPoint viewPoint = new BiomeMutator.ViewPoint(this, x, z);
|
||||
biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill(BiomeSource source) {
|
||||
for(int x = 0; x < width; x++) {
|
||||
for(int z = 0; z < width; z++) {
|
||||
biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBiome(int x, int z) {
|
||||
x += offset;
|
||||
z += offset;
|
||||
return getBiomeRaw(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBiomeRaw(int x, int z) {
|
||||
if(x >= width || z >= width || x < 0 || z < 0) return null;
|
||||
return biomes[x][z];
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline;
|
||||
|
||||
import com.dfsek.terra.api.util.GlueList;
|
||||
import com.dfsek.terra.api.util.seeded.StageSeeded;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
|
||||
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BiomePipelineImpl {
|
||||
private final BiomeSource source;
|
||||
private final List<Stage> stages;
|
||||
private final int size;
|
||||
private final int init;
|
||||
|
||||
private BiomePipelineImpl(BiomeSource source, List<Stage> stages, int size, int init) {
|
||||
this.source = source;
|
||||
this.stages = stages;
|
||||
this.size = size;
|
||||
this.init = init;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get biomes in a chunk
|
||||
*
|
||||
* @param x Chunk X coord
|
||||
* @param z Chunk Z coord
|
||||
* @return BiomeHolder containing biomes.
|
||||
*/
|
||||
public BiomeHolder getBiomes(int x, int z) {
|
||||
BiomeHolder holder = new BiomeHolderImpl(init, new Vector2(x * (init - 1), z * (init - 1)));
|
||||
holder.fill(source);
|
||||
for(Stage stage : stages) holder = stage.apply(holder);
|
||||
return holder;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public static final class BiomePipelineBuilder {
|
||||
private final int init;
|
||||
List<StageSeeded> stages = new ArrayList<>();
|
||||
private int expand;
|
||||
|
||||
public BiomePipelineBuilder(int init) {
|
||||
this.init = init;
|
||||
expand = init;
|
||||
}
|
||||
|
||||
public BiomePipelineImpl build(BiomeSource source, long seed) {
|
||||
List<Stage> stagesBuilt = stages.stream().map(stageBuilder -> stageBuilder.apply(seed)).collect(Collectors.toList());
|
||||
|
||||
for(Stage stage : stagesBuilt) {
|
||||
if(stage.isExpansion()) expand = expand * 2 - 1;
|
||||
}
|
||||
|
||||
return new BiomePipelineImpl(source, stagesBuilt, expand, init);
|
||||
}
|
||||
|
||||
public BiomePipelineBuilder addStage(StageSeeded stage) {
|
||||
stages.add(stage);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline;
|
||||
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.vector.Vector2;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeHolder;
|
||||
import com.dfsek.terra.api.world.biome.pipeline.BiomePipelineImpl;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import net.jafama.FastMath;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class StandardBiomeProvider implements BiomeProvider {
|
||||
private final LoadingCache<Vector2, BiomeHolder> holderCache;
|
||||
private final BiomePipelineImpl pipeline;
|
||||
private final int resolution;
|
||||
private final NoiseSampler mutator;
|
||||
private final double noiseAmp;
|
||||
private final int seed;
|
||||
|
||||
public StandardBiomeProvider(BiomePipelineImpl pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp, int seed) {
|
||||
this.resolution = resolution;
|
||||
this.mutator = mutator;
|
||||
this.noiseAmp = noiseAmp;
|
||||
this.seed = seed;
|
||||
holderCache = CacheBuilder.newBuilder()
|
||||
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
|
||||
.build(
|
||||
new CacheLoader<Vector2, BiomeHolder>() {
|
||||
@Override
|
||||
public BiomeHolder load(@NotNull Vector2 key) {
|
||||
return pipeline.getBiomes(key.getBlockX(), key.getBlockZ());
|
||||
}
|
||||
}
|
||||
);
|
||||
this.pipeline = pipeline;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBiome(int x, int z) {
|
||||
x += mutator.getNoiseSeeded(seed, x, z) * noiseAmp;
|
||||
z += mutator.getNoiseSeeded(1 + seed, x, z) * noiseAmp;
|
||||
|
||||
|
||||
x = FastMath.floorToInt(FastMath.floorDiv(x, resolution));
|
||||
|
||||
z = FastMath.floorToInt(FastMath.floorDiv(z, resolution));
|
||||
|
||||
int fdX = FastMath.floorDiv(x, pipeline.getSize());
|
||||
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
|
||||
return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.api;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
|
||||
public interface BiomeExpander {
|
||||
TerraBiome getBetween(double x, double z, TerraBiome... others);
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.api;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
|
||||
|
||||
public interface BiomeHolder {
|
||||
BiomeHolder expand(BiomeExpander expander);
|
||||
|
||||
void mutate(BiomeMutator mutator);
|
||||
|
||||
void fill(BiomeSource source);
|
||||
|
||||
TerraBiome getBiome(int x, int z);
|
||||
|
||||
TerraBiome getBiomeRaw(int x, int z);
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.api;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
|
||||
public interface BiomeMutator {
|
||||
TerraBiome mutate(ViewPoint viewPoint, double x, double z);
|
||||
|
||||
class ViewPoint {
|
||||
private final BiomeHolder biomes;
|
||||
private final int offX;
|
||||
private final int offZ;
|
||||
|
||||
public ViewPoint(BiomeHolder biomes, int offX, int offZ) {
|
||||
this.biomes = biomes;
|
||||
this.offX = offX;
|
||||
this.offZ = offZ;
|
||||
}
|
||||
|
||||
|
||||
public TerraBiome getBiome(int x, int z) {
|
||||
return biomes.getBiomeRaw(x + offX, z + offZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.api;
|
||||
|
||||
public interface Stage {
|
||||
boolean isExpansion();
|
||||
|
||||
BiomeHolder apply(BiomeHolder in);
|
||||
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.addons.biome.pipeline.BiomePipelineImpl;
|
||||
import com.dfsek.terra.api.TerraPlugin;
|
||||
import com.dfsek.terra.api.util.seeded.SourceSeeded;
|
||||
import com.dfsek.terra.api.util.seeded.StageSeeded;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.world.biome.provider.StandardBiomeProvider;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"FieldMayBeFinal", "unused"})
|
||||
public class BiomePipelineTemplate extends BiomeProviderTemplate {
|
||||
private final TerraPlugin main;
|
||||
@Value("pipeline.initial-size")
|
||||
@Default
|
||||
private int initialSize = 2;
|
||||
|
||||
@Value("pipeline.stages")
|
||||
private List<StageSeeded> stages;
|
||||
|
||||
@Value("pipeline.source")
|
||||
private SourceSeeded source;
|
||||
|
||||
public BiomePipelineTemplate(TerraPlugin main) {
|
||||
this.main = main;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider build(long seed) {
|
||||
BiomePipelineImpl.BiomePipelineBuilder biomePipelineBuilder = new BiomePipelineImpl.BiomePipelineBuilder(initialSize);
|
||||
stages.forEach(biomePipelineBuilder::addStage);
|
||||
BiomePipelineImpl pipeline = biomePipelineBuilder.build(source.apply(seed), seed);
|
||||
return new StandardBiomeProvider(pipeline, main, resolution, blend.apply(seed), blendAmp, (int) seed);
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.loading.object.ObjectTemplate;
|
||||
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
|
||||
import com.dfsek.terra.api.util.seeded.SeededBuilder;
|
||||
import com.dfsek.terra.api.util.seeded.StageSeeded;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
|
||||
|
||||
public abstract class StageTemplate implements ObjectTemplate<SeededBuilder<Stage>>, StageSeeded {
|
||||
@Value("noise")
|
||||
protected NoiseSeeded noise;
|
||||
|
||||
@Override
|
||||
public StageSeeded get() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.expander;
|
||||
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
|
||||
import com.dfsek.terra.addons.biome.pipeline.expand.FractalExpander;
|
||||
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
|
||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||
|
||||
public class ExpanderStageTemplate extends StageTemplate {
|
||||
@Override
|
||||
public Stage apply(Long seed) {
|
||||
return new ExpanderStage(new FractalExpander(noise.apply(seed)));
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderListMutator;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class BorderListMutatorTemplate extends MutatorStageTemplate {
|
||||
@Value("from")
|
||||
private String from;
|
||||
|
||||
@Value("default-replace")
|
||||
private String defaultReplace;
|
||||
|
||||
@Value("default-to")
|
||||
private ProbabilityCollection<BiomeBuilder> defaultTo;
|
||||
|
||||
@Value("replace")
|
||||
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
|
||||
|
||||
|
||||
@Override
|
||||
public BiomeMutator build(long seed) {
|
||||
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
|
||||
|
||||
replace.forEach((keyBuilder, replacements) -> replaceMap.put(keyBuilder.apply(seed), replacements.map(replacement -> replacement.apply(seed), true)));
|
||||
|
||||
return new BorderListMutator(replaceMap, from, defaultReplace, noise.apply(seed), defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true));
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.mutator.BorderMutator;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class BorderMutatorTemplate extends MutatorStageTemplate {
|
||||
@Value("from")
|
||||
private String from;
|
||||
|
||||
@Value("replace")
|
||||
private String replace;
|
||||
|
||||
@Value("to")
|
||||
private ProbabilityCollection<BiomeBuilder> to;
|
||||
|
||||
@Override
|
||||
public BiomeMutator build(long seed) {
|
||||
return new BorderMutator(from, replace, noise.apply(seed), to.map(biomeBuilder -> biomeBuilder.apply(seed), true));
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
|
||||
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
|
||||
import com.dfsek.terra.addons.biome.pipeline.config.stage.StageTemplate;
|
||||
|
||||
public abstract class MutatorStageTemplate extends StageTemplate {
|
||||
public abstract BiomeMutator build(long seed);
|
||||
|
||||
@Override
|
||||
public Stage apply(Long seed) {
|
||||
return new MutatorStage(build(seed));
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceListMutator;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ReplaceListMutatorTemplate extends MutatorStageTemplate {
|
||||
@Value("default-from")
|
||||
private String defaultFrom;
|
||||
|
||||
@Value("default-to")
|
||||
private ProbabilityCollection<BiomeBuilder> defaultTo;
|
||||
|
||||
@Value("to")
|
||||
private Map<BiomeBuilder, ProbabilityCollection<BiomeBuilder>> replace;
|
||||
|
||||
@Override
|
||||
public BiomeMutator build(long seed) {
|
||||
Map<TerraBiome, ProbabilityCollection<TerraBiome>> replaceMap = new HashMap<>();
|
||||
|
||||
replace.forEach((biomeBuilder, biomeBuilders) -> replaceMap.put(biomeBuilder.apply(seed), biomeBuilders.map(builder -> builder.apply(seed), true)));
|
||||
|
||||
return new ReplaceListMutator(replaceMap, defaultFrom, defaultTo.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.mutator.ReplaceMutator;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public class ReplaceMutatorTemplate extends MutatorStageTemplate {
|
||||
@Value("from")
|
||||
private String from;
|
||||
|
||||
@Value("to")
|
||||
private ProbabilityCollection<BiomeBuilder> to;
|
||||
|
||||
@Override
|
||||
public BiomeMutator build(long seed) {
|
||||
return new ReplaceMutator(from, to.map(biomeBuilder -> biomeBuilder.apply(seed), true), noise.apply(seed));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.config.stage.mutator;
|
||||
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.mutator.SmoothMutator;
|
||||
|
||||
public class SmoothMutatorTemplate extends MutatorStageTemplate {
|
||||
@Override
|
||||
public BiomeMutator build(long seed) {
|
||||
return new SmoothMutator(noise.apply(seed));
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.expand;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.MathUtil;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeExpander;
|
||||
|
||||
public class FractalExpander implements BiomeExpander {
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
public FractalExpander(NoiseSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBetween(double x, double z, TerraBiome... others) {
|
||||
return others[MathUtil.normalizeIndex(sampler.getNoise(x, z), others.length)];
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
|
||||
public class BorderMutator implements BiomeMutator {
|
||||
private final String border;
|
||||
private final NoiseSampler noiseSampler;
|
||||
private final ProbabilityCollection<TerraBiome> replace;
|
||||
private final String replaceTag;
|
||||
|
||||
public BorderMutator(String border, String replaceTag, NoiseSampler noiseSampler, ProbabilityCollection<TerraBiome> replace) {
|
||||
this.border = border;
|
||||
this.noiseSampler = noiseSampler;
|
||||
this.replace = replace;
|
||||
this.replaceTag = replaceTag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
|
||||
TerraBiome origin = viewPoint.getBiome(0, 0);
|
||||
if(origin.getTags().contains(replaceTag)) {
|
||||
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)) {
|
||||
TerraBiome biome = replace.get(noiseSampler, x, z);
|
||||
return biome == null ? origin : biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return origin;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
|
||||
public class ReplaceMutator implements BiomeMutator {
|
||||
private final String replaceableTag;
|
||||
private final ProbabilityCollection<TerraBiome> replace;
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
public ReplaceMutator(String replaceable, ProbabilityCollection<TerraBiome> replace, NoiseSampler sampler) {
|
||||
this.replaceableTag = replaceable;
|
||||
this.replace = replace;
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
|
||||
if(viewPoint.getBiome(0, 0).getTags().contains(replaceableTag)) {
|
||||
TerraBiome biome = replace.get(sampler, x, z);
|
||||
return biome == null ? viewPoint.getBiome(0, 0) : biome;
|
||||
}
|
||||
return viewPoint.getBiome(0, 0);
|
||||
}
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.mutator;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.MathUtil;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class SmoothMutator implements BiomeMutator {
|
||||
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
public SmoothMutator(NoiseSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
|
||||
TerraBiome top = viewPoint.getBiome(1, 0);
|
||||
TerraBiome bottom = viewPoint.getBiome(-1, 0);
|
||||
TerraBiome left = viewPoint.getBiome(0, 1);
|
||||
TerraBiome right = viewPoint.getBiome(0, -1);
|
||||
|
||||
|
||||
boolean vert = Objects.equals(top, bottom) && top != null;
|
||||
boolean horiz = Objects.equals(left, right) && left != null;
|
||||
|
||||
if(vert && horiz) {
|
||||
return MathUtil.normalizeIndex(sampler.getNoise(x, z), 2) == 0 ? left : top;
|
||||
}
|
||||
|
||||
if(vert) return top;
|
||||
if(horiz) return left;
|
||||
|
||||
return viewPoint.getBiome(0, 0);
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.source;
|
||||
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
|
||||
|
||||
public class RandomSource implements BiomeSource {
|
||||
private final ProbabilityCollection<TerraBiome> biomes;
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
public RandomSource(ProbabilityCollection<TerraBiome> biomes, NoiseSampler sampler) {
|
||||
this.biomes = biomes;
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBiome(double x, double z) {
|
||||
return biomes.get(sampler, x, z);
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.stages;
|
||||
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeExpander;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
|
||||
|
||||
public class ExpanderStage implements Stage {
|
||||
private final BiomeExpander expander;
|
||||
|
||||
public ExpanderStage(BiomeExpander expander) {
|
||||
this.expander = expander;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpansion() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeHolder apply(BiomeHolder in) {
|
||||
return in.expand(expander);
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
FRACTAL
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.dfsek.terra.addons.biome.pipeline.stages;
|
||||
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeHolder;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.BiomeMutator;
|
||||
import com.dfsek.terra.addons.biome.pipeline.api.Stage;
|
||||
|
||||
public class MutatorStage implements Stage {
|
||||
private final BiomeMutator mutator;
|
||||
|
||||
public MutatorStage(BiomeMutator mutator) {
|
||||
this.mutator = mutator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpansion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeHolder apply(BiomeHolder in) {
|
||||
in.mutate(mutator);
|
||||
return in;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
REPLACE, REPLACE_LIST, BORDER, BORDER_LIST, SMOOTH
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.dfsek.terra.addons.biome.single;
|
||||
|
||||
import com.dfsek.terra.api.world.biome.TerraBiome;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
|
||||
public class SingleBiomeProvider implements BiomeProvider, BiomeProvider.BiomeProviderBuilder {
|
||||
private final TerraBiome biome;
|
||||
|
||||
public SingleBiomeProvider(TerraBiome biome) {
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TerraBiome getBiome(int x, int z) {
|
||||
return biome;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider build(long seed) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.dfsek.terra.addons.biome.single;
|
||||
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
|
||||
|
||||
public class SingleBiomeProviderTemplate extends BiomeProviderTemplate {
|
||||
@Value("biome")
|
||||
private BiomeBuilder biome;
|
||||
|
||||
public SingleBiomeProviderTemplate() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeProvider build(long seed) {
|
||||
return new SingleBiomeProvider(biome.apply(seed));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user