move more things to new modules

This commit is contained in:
dfsek
2021-07-02 07:44:30 -07:00
parent 215a1e0e86
commit 62520af8e7
88 changed files with 300 additions and 313 deletions

View File

@@ -11,7 +11,7 @@ import java.util.Random;
/**
* Class to procedurally determine the spawn point of an object based on a grid with padding between cells.
*/
public class GridSpawn {
public class GridSpawn implements com.dfsek.terra.api.structure.StructureSpawn {
private final int separation;
private final int width;
private final int salt;
@@ -22,14 +22,7 @@ public class GridSpawn {
this.salt = salt;
}
/**
* Get nearest spawn point
*
* @param x X coordinate
* @param z Z coordinate
* @param seed Seed for RNG
* @return Vector representing nearest spawnpoint
*/
@Override
public Vector3 getNearestSpawn(int x, int z, long seed) {
int structureChunkX = x / (width + 2 * separation);
int structureChunkZ = z / (width + 2 * separation);

View File

@@ -1,70 +0,0 @@
package com.dfsek.terra.api.world.biome;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.world.World;
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() + "}";
}
}

View File

@@ -1,83 +0,0 @@
package com.dfsek.terra.api.world.biome.pipeline;
import com.dfsek.terra.api.vector.Vector2;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeExpander;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeHolder;
import com.dfsek.terra.api.world.biome.generation.pipeline.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];
}
}

View File

@@ -1,69 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.BiomeHolder;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
import com.dfsek.terra.api.world.biome.generation.pipeline.Stage;
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 GlueList<>();
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;
}
}
}

View File

@@ -1,19 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.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)];
}
}

View File

@@ -1,47 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.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;
}
}

View File

@@ -1,39 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.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;
}
}

View File

@@ -1,36 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.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;
}
}

View File

@@ -1,27 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.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);
}
}

View File

@@ -1,38 +0,0 @@
package com.dfsek.terra.api.world.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.api.world.biome.generation.pipeline.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);
}
}

View File

@@ -1,21 +0,0 @@
package com.dfsek.terra.api.world.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);
}
}

View File

@@ -1,27 +0,0 @@
package com.dfsek.terra.api.world.biome.pipeline.stages;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeExpander;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeHolder;
import com.dfsek.terra.api.world.biome.generation.pipeline.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
}
}

View File

@@ -1,28 +0,0 @@
package com.dfsek.terra.api.world.biome.pipeline.stages;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeHolder;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.generation.pipeline.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
}
}

View File

@@ -1,62 +0,0 @@
package com.dfsek.terra.api.world.biome.provider;
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);
}
}

View File

@@ -1,22 +0,0 @@
package com.dfsek.terra.api.world.biome.provider;
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;
}
}

View File

@@ -1,56 +0,0 @@
package com.dfsek.terra.api.world.biome.provider;
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());
}
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.api.world.locate;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.structure.rotation.Rotation;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.PopulationUtil;
@@ -8,15 +9,14 @@ 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.biome.generation.BiomeProvider;
import com.dfsek.terra.world.population.items.TerraStructure;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
import java.util.Random;
import java.util.function.Consumer;
public class AsyncStructureFinder extends AsyncFeatureFinder<TerraStructure> {
public AsyncStructureFinder(BiomeProvider provider, TerraStructure target, @NotNull Vector3 origin, World world, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
public class AsyncStructureFinder extends AsyncFeatureFinder<ConfiguredStructure> {
public AsyncStructureFinder(BiomeProvider provider, ConfiguredStructure target, @NotNull Vector3 origin, World world, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
super(provider, target, origin, world, startRadius, maxRadius, callback, main);
setSearchSize(target.getSpawn().getWidth() + 2 * target.getSpawn().getSeparation());
}
@@ -27,7 +27,7 @@ public class AsyncStructureFinder extends AsyncFeatureFinder<TerraStructure> {
}
@Override
public boolean isValid(int x, int z, TerraStructure target) {
public boolean isValid(int x, int z, ConfiguredStructure target) {
Vector3 spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed());
if(!((UserDefinedBiome) provider.getBiome(spawn)).getConfig().getStructures().contains(target)) return false;
Random random = new FastRandom(PopulationUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed()));

View File

@@ -1,22 +0,0 @@
package com.dfsek.terra.api.world.palette.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];
}
}

View File

@@ -1,37 +0,0 @@
package com.dfsek.terra.api.world.palette.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);
}
}

View File

@@ -1,31 +0,0 @@
package com.dfsek.terra.api.world.palette.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;
}
}

View File

@@ -1,23 +0,0 @@
package com.dfsek.terra.api.world.palette.slant;
import com.dfsek.terra.api.world.palette.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;
}
}

View File

@@ -1,60 +0,0 @@
package com.dfsek.terra.carving;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.MathUtil;
import com.dfsek.terra.api.util.PopulationUtil;
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.UserDefinedBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.carving.Worm;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class CarverCache {
private final LoadingCache<Long, List<Worm.WormPoint>> cache;
private final UserDefinedCarver carver;
public CarverCache(World w, TerraPlugin main, UserDefinedCarver carver) {
this.carver = carver;
cache = CacheBuilder.newBuilder().maximumSize(main.getTerraConfig().getCarverCacheSize())
.build(new CacheLoader<Long, List<Worm.WormPoint>>() {
@Override
public List<Worm.WormPoint> load(@NotNull Long key) {
int chunkX = (int) (key >> 32);
int chunkZ = (int) key.longValue();
BiomeProvider provider = main.getWorld(w).getBiomeProvider();
if(CarverCache.this.carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(PopulationUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + CarverCache.this.carver.hashCode())))) {
long seed = PopulationUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed());
Random r = new FastRandom(seed);
Worm carving = CarverCache.this.carver.getWorm(seed, new Vector3((chunkX << 4) + r.nextInt(16), CarverCache.this.carver.getConfig().getHeight().get(r), (chunkZ << 4) + r.nextInt(16)));
List<Worm.WormPoint> points = new GlueList<>();
for(int i = 0; i < carving.getLength(); i++) {
carving.step();
TerraBiome biome = provider.getBiome(carving.getRunning());
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in
return Collections.emptyList();
}
points.add(carving.getPoint());
}
return points;
}
return Collections.emptyList();
}
});
}
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ) {
return cache.getUnchecked(MathUtil.squash(chunkX, chunkZ));
}
}

View File

@@ -1,64 +0,0 @@
package com.dfsek.terra.carving;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.collections.MaterialSet;
import net.jafama.FastMath;
import java.util.Map;
import java.util.TreeMap;
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
public class CarverPalette {
private final boolean blacklist;
private final MaterialSet replace;
private final TreeMap<Integer, ProbabilityCollection<BlockState>> map = new TreeMap<>();
private ProbabilityCollection<BlockState>[] layers;
private int offset = 0;
public CarverPalette(MaterialSet replaceable, boolean blacklist) {
this.blacklist = blacklist;
this.replace = replaceable;
}
public CarverPalette add(ProbabilityCollection<BlockState> collection, int y) {
map.put(y, collection);
return this;
}
public ProbabilityCollection<BlockState> get(int y) {
int index = y + offset;
return index >= 0
? index < layers.length
? layers[index]
: layers[layers.length - 1]
: layers[0];
}
public boolean canReplace(BlockType material) {
return blacklist != replace.contains(material);
}
/**
* Build the palette to an array.
*/
public void build() {
int min = FastMath.min(map.keySet().stream().min(Integer::compareTo).orElse(0), 0);
int max = FastMath.max(map.keySet().stream().max(Integer::compareTo).orElse(255), 255);
layers = new ProbabilityCollection[map.lastKey() + 1 - min];
for(int y = min; y <= FastMath.max(map.lastKey(), max); y++) {
ProbabilityCollection<BlockState> d = null;
for(Map.Entry<Integer, ProbabilityCollection<BlockState>> e : map.entrySet()) {
if(e.getKey() >= y) {
d = e.getValue();
break;
}
}
if(d == null) throw new IllegalArgumentException("No palette for Y=" + y);
layers[y - min] = d;
}
offset = -min;
}
}

View File

@@ -1,188 +0,0 @@
package com.dfsek.terra.carving;
import com.dfsek.paralithic.Expression;
import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction2;
import com.dfsek.terra.api.math.paralithic.noise.NoiseFunction3;
import com.dfsek.terra.api.math.range.ConstantRange;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.Range;
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 com.dfsek.terra.config.templates.CarverTemplate;
import net.jafama.FastMath;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiConsumer;
public class UserDefinedCarver extends Carver {
private final double[] start; // 0, 1, 2 = x, y, z.
private final double[] mutate; // 0, 1, 2 = x, y, z. 3 = radius.
private final Range length;
private final long hash;
private final int topCut;
private final int bottomCut;
private final CarverTemplate config;
private final Expression xRad;
private final Expression yRad;
private final Expression zRad;
private final Map<Long, CarverCache> cacheMap = new ConcurrentHashMap<>();
private final TerraPlugin main;
private double step = 2;
private Range recalc = new ConstantRange(8, 10);
private double recalcMagnitude = 3;
public UserDefinedCarver(Range height, Range length, double[] start, double[] mutate, List<String> radii, Scope parent, long hash, int topCut, int bottomCut, CarverTemplate config, TerraPlugin main, Map<String, NoiseSeeded> functions, Map<String, FunctionTemplate> definedFunctions) throws ParseException {
super(height.getMin(), height.getMax());
this.length = length;
this.start = start;
this.mutate = mutate;
this.hash = hash;
this.topCut = topCut;
this.bottomCut = bottomCut;
this.config = config;
this.main = main;
Parser p = new Parser();
functions.forEach((id, noise) -> {
switch(noise.getDimensions()) {
case 2:
p.registerFunction(id, new NoiseFunction2(noise.apply(hash)));
break;
case 3:
p.registerFunction(id, new NoiseFunction3(noise.apply(hash)));
break;
}
});
for(Map.Entry<String, FunctionTemplate> entry : definedFunctions.entrySet()) {
p.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), p, parent));
}
Scope s = new Scope().withParent(parent);
s.addInvocationVariable("x");
s.addInvocationVariable("y");
s.addInvocationVariable("z");
s.addInvocationVariable("length");
s.addInvocationVariable("position");
s.addInvocationVariable("seed");
xRad = p.parse(radii.get(0), s);
yRad = p.parse(radii.get(1), s);
zRad = p.parse(radii.get(2), s);
}
@Override
public Worm getWorm(long l, Vector3 vector) {
Random r = new FastRandom(l + hash);
return new UserDefinedWorm(length.get(r) / 2, r, vector, topCut, bottomCut, l);
}
public void setStep(double step) {
this.step = step;
}
public void setRecalc(Range recalc) {
this.recalc = recalc;
}
@Override
public void carve(int chunkX, int chunkZ, World w, BiConsumer<Vector3, CarvingType> consumer) {
synchronized(cacheMap) {
CarverCache cache = cacheMap.computeIfAbsent(w.getSeed(), world -> new CarverCache(w, main, this));
int carvingRadius = getCarvingRadius();
for(int x = chunkX - carvingRadius; x <= chunkX + carvingRadius; x++) {
for(int z = chunkZ - carvingRadius; z <= chunkZ + carvingRadius; z++) {
cache.getPoints(x, z).forEach(point -> {
Vector3 origin = point.getOrigin();
if(FastMath.floorDiv(origin.getBlockX(), 16) != chunkX && FastMath.floorDiv(origin.getBlockZ(), 16) != chunkZ) // We only want to carve this chunk.
return;
point.carve(chunkX, chunkZ, consumer, w);
});
}
}
}
}
public void setRecalcMagnitude(double recalcMagnitude) {
this.recalcMagnitude = recalcMagnitude;
}
@Override
public boolean isChunkCarved(World w, int chunkX, int chunkZ, Random random) {
BiomeTemplate conf = ((UserDefinedBiome) main.getWorld(w).getBiomeProvider().getBiome((chunkX << 4) + 8, (chunkZ << 4) + 8)).getConfig();
if(conf.getCarvers().get(this) != null) {
return new FastRandom(random.nextLong() + hash).nextInt(100) < conf.getCarvers().get(this);
}
return false;
}
public CarverTemplate getConfig() {
return config;
}
private class UserDefinedWorm extends Worm {
private final Vector3 direction;
private final Vector3 origin;
private int steps;
private int nextDirection = 0;
private double[] currentRotation = new double[3];
private final long seed;
public UserDefinedWorm(int length, Random r, Vector3 origin, int topCut, int bottomCut, long seed) {
super(length, r, origin);
this.origin = origin;
this.seed = seed;
super.setTopCut(topCut);
super.setBottomCut(bottomCut);
direction = new Vector3((r.nextDouble() - 0.5D) * start[0], (r.nextDouble() - 0.5D) * start[1], (r.nextDouble() - 0.5D) * start[2]).normalize().multiply(step);
double[] args = {origin.getX(), origin.getY(), origin.getZ(), length, 0, seed};
setRadius(new int[] {(int) (xRad.evaluate(args)), (int) (yRad.evaluate(args)), (int) (zRad.evaluate(args))});
}
@Override
public WormPoint getPoint() {
return new WormPoint(getRunning().clone(), getRadius(), config.getCutTop(), config.getCutBottom());
}
@Override
public void step() {
if(steps == nextDirection) {
direction.rotateAroundX(FastMath.toRadians((getRandom().nextGaussian()) * mutate[0] * recalcMagnitude));
direction.rotateAroundY(FastMath.toRadians((getRandom().nextGaussian()) * mutate[1] * recalcMagnitude));
direction.rotateAroundZ(FastMath.toRadians((getRandom().nextGaussian()) * mutate[2] * recalcMagnitude));
currentRotation = new double[] {(getRandom().nextGaussian()) * mutate[0],
(getRandom().nextGaussian()) * mutate[1],
(getRandom().nextGaussian()) * mutate[2]};
nextDirection += recalc.get(getRandom());
}
steps++;
double[] args = {origin.getX(), origin.getY(), origin.getZ(), getLength(), steps, seed};
setRadius(new int[] {(int) (xRad.evaluate(args)), (int) (yRad.evaluate(args)), (int) (zRad.evaluate(args))});
direction.rotateAroundX(FastMath.toRadians(currentRotation[0] * mutate[0]));
direction.rotateAroundY(FastMath.toRadians(currentRotation[1] * mutate[1]));
direction.rotateAroundZ(FastMath.toRadians(currentRotation[2] * mutate[2]));
getRunning().add(direction);
}
}
}

View File

@@ -5,6 +5,7 @@ import com.dfsek.terra.api.command.annotation.Argument;
import com.dfsek.terra.api.command.annotation.Command;
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.commands.biome.arg.BiomeArgumentParser;
@@ -42,7 +43,7 @@ public class BiomeInfoCommand implements CommandTemplate {
bio.getExtended().forEach(id -> sender.sendMessage(" - " + id));
}
List<TerraStructure> structureConfigs = bio.getStructures();
List<ConfiguredStructure> structureConfigs = bio.getStructures();
if(structureConfigs.size() == 0) {
sender.sendMessage("No Structures");

View File

@@ -5,14 +5,15 @@ import com.dfsek.terra.api.command.arg.ArgumentParser;
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.structure.ConfiguredStructure;
import com.dfsek.terra.world.population.items.TerraStructure;
public class StructureArgumentParser implements ArgumentParser<TerraStructure> {
public class StructureArgumentParser implements ArgumentParser<ConfiguredStructure> {
@Inject
private TerraPlugin main;
@Override
public TerraStructure parse(CommandSender sender, String arg) {
public ConfiguredStructure parse(CommandSender sender, String arg) {
return main.getWorld(((Player) sender).world()).getConfig().getRegistry(TerraStructure.class).get(arg);
}
}

View File

@@ -13,8 +13,8 @@ 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.generation.pipeline.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.api.world.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
@@ -33,12 +33,12 @@ import com.dfsek.terra.config.loaders.config.biome.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.SourceBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.StageBuilderLoader;
import com.dfsek.terra.config.loaders.config.biome.templates.source.NoiseSourceTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader;
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;

View File

@@ -1,13 +0,0 @@
package com.dfsek.terra.config.builder;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.SeededBuilder;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
public interface BiomeBuilder extends SeededBuilder<TerraBiome> {
ProbabilityCollection<Biome> getVanillaBiomes();
BiomeTemplate getTemplate();
}

View File

@@ -1,73 +0,0 @@
package com.dfsek.terra.config.builder;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.terra.api.noise.NoiseSampler;
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.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 ConfigPackImpl pack;
private final Map<Long, UserDefinedBiome> biomeMap = new ConcurrentHashMap<>();
public UserDefinedBiomeBuilder(BiomeTemplate template, ConfigPackImpl 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();
Map<String, FunctionTemplate> functionTemplateMap = new LinkedHashMap<>(pack.getTemplate().getFunctions());
functionTemplateMap.putAll(template.getFunctions());
try {
noise = new ExpressionSampler(template.getNoiseEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
elevation = template.getElevationEquation() == null ? NoiseSampler.zero() : new ExpressionSampler(template.getElevationEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
carving = new ExpressionSampler(template.getCarvingEquation(), varScope, seed, noiseBuilderMap, functionTemplateMap);
} 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();
}
@Override
public BiomeTemplate getTemplate() {
return template;
}
}

View File

@@ -1,20 +0,0 @@
package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.builder.UserDefinedBiomeBuilder;
import com.dfsek.terra.config.pack.ConfigPackImpl;
import com.dfsek.terra.config.templates.BiomeTemplate;
public class BiomeFactory implements ConfigFactory<BiomeTemplate, BiomeBuilder> {
private final ConfigPackImpl pack;
public BiomeFactory(ConfigPackImpl pack) {
this.pack = pack;
}
@Override
public BiomeBuilder build(BiomeTemplate template, TerraPlugin main) {
return new UserDefinedBiomeBuilder(template, pack);
}
}

View File

@@ -1,37 +0,0 @@
package com.dfsek.terra.config.factories;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.util.MathUtil;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.pack.ConfigPackImpl;
import com.dfsek.terra.config.templates.CarverTemplate;
import java.util.Arrays;
import java.util.List;
public class CarverFactory implements ConfigFactory<CarverTemplate, UserDefinedCarver> {
private final ConfigPackImpl pack;
public CarverFactory(ConfigPackImpl pack) {
this.pack = pack;
}
@Override
public UserDefinedCarver build(CarverTemplate config, TerraPlugin main) throws LoadException {
double[] start = new double[] {config.getStartX(), config.getStartY(), config.getStartZ()};
double[] mutate = new double[] {config.getMutateX(), config.getMutateY(), config.getMutateZ()};
List<String> radius = Arrays.asList(config.getRadMX(), config.getRadMY(), config.getRadMZ());
long hash = MathUtil.hashToLong(config.getID());
UserDefinedCarver carver;
try {
carver = new UserDefinedCarver(config.getHeight(), config.getLength(), start, mutate, radius, pack.getVarScope(), hash, config.getCutTop(), config.getCutBottom(), config, main, pack.getTemplate().getNoiseBuilderMap(), pack.getTemplate().getFunctions());
} catch(ParseException e) {
throw new LoadException("Unable to parse radius equations", e);
}
carver.setRecalc(config.getRecalc());
carver.setRecalcMagnitude(config.getRecaclulateMagnitude());
return carver;
}
}

View File

@@ -1,9 +0,0 @@
package com.dfsek.terra.config.factories;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin;
public interface ConfigFactory<C extends ConfigTemplate, O> {
O build(C config, TerraPlugin main) throws LoadException;
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.world.Flora;
import com.dfsek.terra.api.world.palette.NoisePalette;
import com.dfsek.terra.api.world.palette.PaletteImpl;

View File

@@ -2,6 +2,7 @@ package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.config.templates.OreTemplate;
import com.dfsek.terra.world.population.items.ores.Ore;
import com.dfsek.terra.world.population.items.ores.VanillaOre;

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.world.generator.Palette;
import com.dfsek.terra.api.world.palette.NoisePalette;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;

View File

@@ -1,12 +1,14 @@
package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.config.templates.StructureTemplate;
import com.dfsek.terra.world.population.items.TerraStructure;
public class StructureFactory implements ConfigFactory<StructureTemplate, TerraStructure> {
public class StructureFactory implements ConfigFactory<StructureTemplate, ConfiguredStructure> {
@Override
public TerraStructure build(StructureTemplate config, TerraPlugin main) {
public ConfiguredStructure build(StructureTemplate config, TerraPlugin main) {
return new TerraStructure(config.getStructures(), config.getY(), config.getSpawn(), config);
}
}

View File

@@ -1,6 +1,7 @@
package com.dfsek.terra.config.factories;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.config.templates.TreeTemplate;
import com.dfsek.terra.world.population.items.tree.TerraTree;

View File

@@ -3,14 +3,15 @@ package com.dfsek.terra.config.loaders.config;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.structure.StructureSpawn;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class GridSpawnLoader implements TypeLoader<GridSpawn> {
public class GridSpawnLoader implements TypeLoader<StructureSpawn> {
@Override
public GridSpawn load(Type type, Object o, ConfigLoader configLoader) {
public StructureSpawn load(Type type, Object o, ConfigLoader configLoader) {
Map<String, Integer> map = (Map<String, Integer>) o;
return new GridSpawn(map.get("width"), map.get("padding"), map.getOrDefault("salt", 0));
}

View File

@@ -4,14 +4,14 @@ import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.api.util.seeded.StageSeeded;
import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator.SmoothMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.addons.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.addons.biome.pipeline.config.stage.expander.ExpanderStageTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.BorderMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceListMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.ReplaceMutatorTemplate;
import com.dfsek.terra.addons.biome.pipeline.config.stage.mutator.SmoothMutatorTemplate;
import java.lang.reflect.Type;
import java.util.Map;

View File

@@ -1,38 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
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.pipeline.BiomePipelineImpl;
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);
}
}

View File

@@ -14,17 +14,7 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
protected int resolution = 1;
@Value("blend.noise")
@Default
protected NoiseSeeded blend = new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return NoiseSampler.zero();
}
@Override
public int getDimensions() {
return 2;
}
};
protected NoiseSeeded blend = NoiseSeeded.zero(2);
@Value("blend.amplitude")
@Default
protected double blendAmp = 0d;

View File

@@ -1,28 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
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.world.biome.provider.ImageBiomeProvider;
import com.dfsek.terra.config.builder.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);
}
}

View File

@@ -1,19 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.provider;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.biome.provider.SingleBiomeProvider;
import com.dfsek.terra.config.builder.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));
}
}

View File

@@ -4,8 +4,8 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
import com.dfsek.terra.api.world.biome.pipeline.source.RandomSource;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.addons.biome.pipeline.source.RandomSource;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
public class NoiseSourceTemplate extends SourceTemplate {
@Value("noise")

View File

@@ -1,18 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.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.api.world.biome.generation.pipeline.Stage;
public abstract class StageTemplate implements ObjectTemplate<SeededBuilder<Stage>>, StageSeeded {
@Value("noise")
protected NoiseSeeded noise;
@Override
public StageSeeded get() {
return this;
}
}

View File

@@ -1,13 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.expander;
import com.dfsek.terra.api.world.biome.generation.pipeline.Stage;
import com.dfsek.terra.api.world.biome.pipeline.expand.FractalExpander;
import com.dfsek.terra.api.world.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.config.loaders.config.biome.templates.stage.StageTemplate;
public class ExpanderStageTemplate extends StageTemplate {
@Override
public Stage apply(Long seed) {
return new ExpanderStage(new FractalExpander(noise.apply(seed)));
}
}

View File

@@ -1,36 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.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.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderListMutator;
import com.dfsek.terra.config.builder.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));
}
}

View File

@@ -1,24 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.BorderMutator;
import com.dfsek.terra.config.builder.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));
}
}

View File

@@ -1,15 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.generation.pipeline.Stage;
import com.dfsek.terra.api.world.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.config.loaders.config.biome.templates.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));
}
}

View File

@@ -1,32 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.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.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceListMutator;
import com.dfsek.terra.config.builder.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));
}
}

View File

@@ -1,21 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.ReplaceMutator;
import com.dfsek.terra.config.builder.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));
}
}

View File

@@ -1,11 +0,0 @@
package com.dfsek.terra.config.loaders.config.biome.templates.stage.mutator;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeMutator;
import com.dfsek.terra.api.world.biome.pipeline.mutator.SmoothMutator;
public class SmoothMutatorTemplate extends MutatorStageTemplate {
@Override
public BiomeMutator build(long seed) {
return new SmoothMutator(noise.apply(seed));
}
}

View File

@@ -20,6 +20,7 @@ import com.dfsek.terra.api.event.events.config.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.registry.OpenRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.structure.LootTable;
import com.dfsek.terra.api.structure.Structure;
import com.dfsek.terra.api.structures.loot.LootTableImpl;
@@ -29,7 +30,7 @@ import com.dfsek.terra.api.util.generic.pair.ImmutablePair;
import com.dfsek.terra.api.util.seeded.NoiseProvider;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.config.dummy.DummyWorld;
import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.Loader;
@@ -274,7 +275,7 @@ public class ConfigPackImpl implements ConfigPack {
}
public Set<TerraStructure> getStructures() {
public Set<ConfiguredStructure> getStructures() {
return new HashSet<>(getRegistry(TerraStructure.class).entries());
}

View File

@@ -4,11 +4,12 @@ import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.registry.OpenRegistry;
import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.generator.SamplerCache;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.registry.LockedRegistryImpl;
import com.dfsek.terra.registry.OpenRegistryImpl;
import com.dfsek.terra.world.generation.math.SamplerCacheImpl;
@@ -119,7 +120,7 @@ public class WorldConfigImpl implements WorldConfig {
return getTemplate().isDisableSaplings();
}
public Set<TerraStructure> getStructures() {
public Set<ConfiguredStructure> getStructures() {
return new HashSet<>(getRegistry(TerraStructure.class).entries());
}

View File

@@ -1,7 +0,0 @@
package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.config.ConfigTemplate;
public abstract class AbstractableTemplate implements ConfigTemplate {
public abstract String getID();
}

View File

@@ -1,382 +0,0 @@
package com.dfsek.terra.config.templates;
import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.math.paralithic.BlankFunction;
import com.dfsek.terra.api.math.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.api.noise.NoiseSampler;
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.api.world.palette.PaletteImpl;
import com.dfsek.terra.api.world.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.slant.SlantHolder;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.loaders.config.function.FunctionTemplate;
import com.dfsek.terra.config.pack.ConfigPackImpl;
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.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class BiomeTemplate extends AbstractableTemplate implements ValidatedConfigTemplate {
private final ConfigPackImpl 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("functions")
@Default
@Abstractable
private LinkedHashMap<String, FunctionTemplate> functions = new LinkedHashMap<>();
@Value("beta.carving.equation")
@Abstractable
@Default
private String carvingEquation = "0";
@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;
@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("erode")
@Abstractable
@Default
private String erode = null;
@Value("structures")
@Abstractable
@Default
private List<TerraStructure> structures = new GlueList<>();
@Value("noise-equation")
@Abstractable
private String noiseEquation;
@Value("ores")
@Abstractable
@Default
private OreHolder oreHolder = new OreHolder();
@Value("ocean.level")
@Abstractable
@Default
private int seaLevel = 62;
@Value("ocean.palette")
@Abstractable
@Default
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 Map<String, FunctionTemplate> getFunctions() {
return functions;
}
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(ConfigPackImpl pack, TerraPlugin main) {
this.pack = pack;
biomeNoise = new NoiseSeeded() {
@Override
public NoiseSampler apply(Long seed) {
return NoiseSampler.zero();
}
@Override
public int getDimensions() {
return 2;
}
};
oceanPalette = new PaletteImpl.Singleton(main.getWorldHandle().createBlockData("minecraft:water"));
}
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 String getErode() {
return erode;
}
public List<TerraStructure> getStructures() {
return structures;
}
public String 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
Map<String, FunctionTemplate> testFunctions = new LinkedHashMap<>(pack.getTemplate().getFunctions());
testFunctions.putAll(functions);
for(Map.Entry<String, FunctionTemplate> entry : testFunctions.entrySet()) {
try {
tester.registerFunction(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue(), tester, testScope));
} catch(ParseException e) {
throw new ValidationException("Invalid function: ", e);
}
}
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;
}
}

View File

@@ -1,206 +0,0 @@
package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.math.range.ConstantRange;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.carving.CarverPalette;
import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class CarverTemplate extends AbstractableTemplate {
@Value("id")
private String id;
@Value("step")
@Abstractable
@Default
private int step = 2;
@Value("recalculate-magnitude")
@Default
@Abstractable
private double recaclulateMagnitude = 4;
@Value("recalculate-direction")
@Abstractable
@Default
private Range recalc = new ConstantRange(8, 10);
@Value("length")
@Abstractable
private Range length;
@Value("start.x")
@Abstractable
private double startX;
@Value("start.y")
@Abstractable
private double startY;
@Value("start.z")
@Abstractable
private double startZ;
@Value("start.radius.x")
@Abstractable
private String radMX;
@Value("start.radius.y")
@Abstractable
private String radMY;
@Value("start.radius.z")
@Abstractable
private String radMZ;
@Value("start.height")
@Abstractable
private Range height;
@Value("cut.bottom")
@Abstractable
@Default
private int cutBottom = 0;
@Value("cut.top")
@Abstractable
@Default
private int cutTop = 0;
@Value("mutate.x")
@Abstractable
private double mutateX;
@Value("mutate.y")
@Abstractable
private double mutateY;
@Value("mutate.z")
@Abstractable
private double mutateZ;
@Value("palette.top")
@Abstractable
private CarverPalette top;
@Value("palette.bottom")
@Abstractable
private CarverPalette bottom;
@Value("palette.outer")
@Abstractable
private CarverPalette outer;
@Value("palette.inner")
@Abstractable
private CarverPalette inner;
@Value("shift")
@Abstractable
@Default
private Map<BlockType, MaterialSet> shift = new HashMap<>();
@Value("update")
@Abstractable
@Default
private MaterialSet update = new MaterialSet();
public String getID() {
return id;
}
public int getStep() {
return step;
}
public Range getLength() {
return length;
}
public double getStartX() {
return startX;
}
public double getStartY() {
return startY;
}
public double getStartZ() {
return startZ;
}
public String getRadMX() {
return radMX;
}
public String getRadMY() {
return radMY;
}
public String getRadMZ() {
return radMZ;
}
public Range getHeight() {
return height;
}
public int getCutBottom() {
return cutBottom;
}
public int getCutTop() {
return cutTop;
}
public double getMutateX() {
return mutateX;
}
public double getMutateY() {
return mutateY;
}
public double getMutateZ() {
return mutateZ;
}
public CarverPalette getTop() {
return top;
}
public CarverPalette getBottom() {
return bottom;
}
public CarverPalette getOuter() {
return outer;
}
public CarverPalette getInner() {
return inner;
}
public Map<BlockType, MaterialSet> getShift() {
return shift;
}
public MaterialSet getUpdate() {
return update;
}
public Range getRecalc() {
return recalc;
}
public double getRecaclulateMagnitude() {
return recaclulateMagnitude;
}
}

View File

@@ -3,6 +3,7 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.util.collections.MaterialSet;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
import com.dfsek.terra.world.population.items.flora.TerraFlora;
@@ -10,7 +11,7 @@ import com.dfsek.terra.world.population.items.flora.TerraFlora;
import java.util.List;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class FloraTemplate extends AbstractableTemplate {
public class FloraTemplate implements AbstractableTemplate {
@Value("id")
private String id;

View File

@@ -5,6 +5,7 @@ import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.collections.MaterialSet;
@@ -12,7 +13,7 @@ import java.util.HashMap;
import java.util.Map;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class OreTemplate extends AbstractableTemplate {
public class OreTemplate implements AbstractableTemplate {
@Value("id")
private String id;

View File

@@ -3,6 +3,7 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.NoiseSeeded;
import com.dfsek.terra.api.world.palette.holder.PaletteLayerHolder;
@@ -11,7 +12,7 @@ import com.dfsek.terra.noise.samplers.noise.random.WhiteNoiseSampler;
import java.util.List;
@SuppressWarnings({"FieldMayBeFinal", "unused"})
public class PaletteTemplate extends AbstractableTemplate {
public class PaletteTemplate implements AbstractableTemplate {
@Value("noise")
@Abstractable
@Default

View File

@@ -4,8 +4,9 @@ import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.structure.Structure;
import com.dfsek.terra.api.structure.StructureSpawn;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.Range;
@@ -13,7 +14,7 @@ import com.dfsek.terra.api.util.Range;
import java.util.List;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class StructureTemplate extends AbstractableTemplate implements ConfigTemplate {
public class StructureTemplate implements AbstractableTemplate, ConfigTemplate {
@Value("id")
private String id;
@@ -27,7 +28,7 @@ public class StructureTemplate extends AbstractableTemplate implements ConfigTem
@Value("spawn")
@Abstractable
private GridSpawn spawn;
private StructureSpawn spawn;
@Value("features")
@Abstractable
@@ -50,7 +51,7 @@ public class StructureTemplate extends AbstractableTemplate implements ConfigTem
return features;
}
public GridSpawn getSpawn() {
public StructureSpawn getSpawn() {
return spawn;
}
}

View File

@@ -3,12 +3,13 @@ package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Default;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.structure.Structure;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.collections.MaterialSet;
@SuppressWarnings({"unused", "FieldMayBeFinal"})
public class TreeTemplate extends AbstractableTemplate {
public class TreeTemplate implements AbstractableTemplate {
@Value("scripts")
@Abstractable
private ProbabilityCollection<Structure> structure;

View File

@@ -2,7 +2,7 @@ package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.registry.OpenRegistryImpl;
import java.lang.reflect.Type;

View File

@@ -3,24 +3,24 @@ package com.dfsek.terra.registry.config;
import com.dfsek.tectonic.config.ConfigTemplate;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.AbstractableTemplate;
import com.dfsek.terra.api.config.ConfigFactory;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.config.ConfigType;
import com.dfsek.terra.api.registry.OpenRegistry;
import com.dfsek.terra.api.util.seeded.BiomeBuilder;
import com.dfsek.terra.api.world.Flora;
import com.dfsek.terra.api.world.Tree;
import com.dfsek.terra.api.world.generator.Palette;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.BiomeBuilder;
import com.dfsek.terra.config.factories.BiomeFactory;
import com.dfsek.terra.config.factories.CarverFactory;
import com.dfsek.terra.config.factories.ConfigFactory;
import com.dfsek.terra.config.factories.FloraFactory;
import com.dfsek.terra.config.factories.OreFactory;
import com.dfsek.terra.config.factories.PaletteFactory;
import com.dfsek.terra.config.factories.StructureFactory;
import com.dfsek.terra.config.factories.TreeFactory;
import com.dfsek.terra.config.pack.ConfigPackImpl;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.config.templates.FloraTemplate;

View File

@@ -1,88 +0,0 @@
package com.dfsek.terra.world.generation;
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.palette.holder.PaletteHolder;
import com.dfsek.terra.api.world.palette.slant.SlantHolder;
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;
}
}

View File

@@ -1,96 +0,0 @@
package com.dfsek.terra.world.population;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.api.profiler.ProfileFrame;
import com.dfsek.terra.api.util.PopulationUtil;
import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.Chunk;
import com.dfsek.terra.api.world.TerraWorld;
import com.dfsek.terra.api.world.World;
import com.dfsek.terra.api.world.generator.Chunkified;
import com.dfsek.terra.api.world.generator.TerraBlockPopulator;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.templates.CarverTemplate;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class CavePopulator implements TerraBlockPopulator, Chunkified {
private static final Map<BlockType, BlockState> shiftStorage = new HashMap<>(); // Persist BlockData created for shifts, to avoid re-calculating each time.
private final TerraPlugin main;
public CavePopulator(TerraPlugin main) {
this.main = main;
}
@SuppressWarnings("try")
@Override
public void populate(@NotNull World world, @NotNull Chunk chunk) {
TerraWorld tw = main.getWorld(world);
WorldHandle handle = main.getWorldHandle();
BlockState AIR = handle.createBlockData("minecraft:air");
try(ProfileFrame ignore = main.getProfiler().profile("carving")) {
Random random = PopulationUtil.getRandom(chunk);
if(!tw.isSafe()) return;
WorldConfig config = tw.getConfig();
if(config.disableCarving()) return;
for(UserDefinedCarver c : config.getRegistry(UserDefinedCarver.class).entries()) {
CarverTemplate template = c.getConfig();
Map<Vector3, BlockState> shiftCandidate = new HashMap<>();
c.carve(chunk.getX(), chunk.getZ(), world, (v, type) -> {
try(ProfileFrame ignored = main.getProfiler().profile("carving:" + c.getConfig().getID())) {
BlockState m = chunk.getBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ());
BlockType re = m.getBlockType();
switch(type) {
case CENTER:
if(template.getInner().canReplace(re)) {
chunk.setBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ(), template.getInner().get(v.getBlockY()).get(random), template.getUpdate().contains(re));
if(template.getShift().containsKey(re)) shiftCandidate.put(v, m);
}
break;
case WALL:
if(template.getOuter().canReplace(re)) {
chunk.setBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ(), template.getOuter().get(v.getBlockY()).get(random), template.getUpdate().contains(re));
if(template.getShift().containsKey(re)) shiftCandidate.put(v, m);
}
break;
case TOP:
if(template.getTop().canReplace(re)) {
chunk.setBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ(), template.getTop().get(v.getBlockY()).get(random), template.getUpdate().contains(re));
if(template.getShift().containsKey(re)) shiftCandidate.put(v, m);
}
break;
case BOTTOM:
if(template.getBottom().canReplace(re)) {
chunk.setBlock(v.getBlockX(), v.getBlockY(), v.getBlockZ(), template.getBottom().get(v.getBlockY()).get(random), template.getUpdate().contains(re));
if(template.getShift().containsKey(re)) shiftCandidate.put(v, m);
}
break;
}
}
});
for(Map.Entry<Vector3, BlockState> entry : shiftCandidate.entrySet()) {
Vector3 l = entry.getKey();
Vector3 mut = l.clone();
BlockState orig = chunk.getBlock(l.getBlockX(), l.getBlockY(), l.getBlockZ());
do mut.subtract(0, 1, 0);
while(mut.getY() > world.getMinHeight() && chunk.getBlock(mut.getBlockX(), mut.getBlockY(), mut.getBlockZ()).matches(orig));
try {
if(template.getShift().get(entry.getValue().getBlockType()).contains(chunk.getBlock(mut.getBlockX(), mut.getBlockY(), mut.getBlockZ()).getBlockType())) {
chunk.setBlock(mut.getBlockX(), mut.getBlockY(), mut.getBlockZ(), shiftStorage.computeIfAbsent(entry.getValue().getBlockType(), BlockType::getDefaultData), false);
}
} catch(NullPointerException ignored) {
}
}
}
}
}
}

View File

@@ -3,6 +3,7 @@ package com.dfsek.terra.world.population;
import com.dfsek.terra.api.TerraPlugin;
import com.dfsek.terra.api.config.WorldConfig;
import com.dfsek.terra.api.profiler.ProfileFrame;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.structure.rotation.Rotation;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.PopulationUtil;
@@ -39,7 +40,7 @@ public class StructurePopulator implements TerraBlockPopulator, Chunkified {
if(!tw.isSafe()) return;
BiomeProvider provider = tw.getBiomeProvider();
WorldConfig config = tw.getConfig();
for(TerraStructure conf : config.getRegistry(TerraStructure.class).entries()) {
for(ConfiguredStructure conf : config.getRegistry(TerraStructure.class).entries()) {
Vector3 spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed());
if(!((UserDefinedBiome) provider.getBiome(spawn)).getConfig().getStructures().contains(conf))

View File

@@ -1,18 +1,19 @@
package com.dfsek.terra.world.population.items;
import com.dfsek.terra.api.math.GridSpawn;
import com.dfsek.terra.api.structure.ConfiguredStructure;
import com.dfsek.terra.api.structure.Structure;
import com.dfsek.terra.api.structure.StructureSpawn;
import com.dfsek.terra.api.util.ProbabilityCollection;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.config.templates.StructureTemplate;
public class TerraStructure {
public class TerraStructure implements ConfiguredStructure {
private final ProbabilityCollection<Structure> structure;
private final Range spawnStart;
private final GridSpawn spawn;
private final StructureSpawn spawn;
private final StructureTemplate template;
public TerraStructure(ProbabilityCollection<Structure> structures, Range spawnStart, GridSpawn spawn, StructureTemplate template) {
public TerraStructure(ProbabilityCollection<Structure> structures, Range spawnStart, StructureSpawn spawn, StructureTemplate template) {
this.structure = structures;
this.spawnStart = spawnStart;
this.spawn = spawn;
@@ -23,15 +24,18 @@ public class TerraStructure {
return template;
}
@Override
public ProbabilityCollection<Structure> getStructure() {
return structure;
}
@Override
public Range getSpawnStart() {
return spawnStart;
}
public GridSpawn getSpawn() {
@Override
public StructureSpawn getSpawn() {
return spawn;
}
}