implementation of BiomePipeline

This commit is contained in:
dfsek
2021-01-13 00:19:57 -07:00
parent 5c9a9c7dfa
commit fb32531584
54 changed files with 240 additions and 1332 deletions

View File

@@ -3,13 +3,11 @@ package com.dfsek.terra;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.generator.GeneratorWrapper;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.config.base.ConfigPack;
public class TerraWorld {
private final TerraBiomeGrid grid;
private final BiomeZone zone;
private final BiomeProvider provider;
private final ConfigPack config;
private final boolean safe;
private final TerraProfiler profiler;
@@ -19,8 +17,7 @@ public class TerraWorld {
public TerraWorld(World w, ConfigPack c, TerraPlugin main) {
config = c;
profiler = new TerraProfiler(w);
this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(w.getSeed(), c, main).build();
this.zone = grid.getZone();
this.provider = config.getTemplate().getProviderBuilder().build(w.getSeed());
this.world = w;
safe = true;
}
@@ -33,18 +30,14 @@ public class TerraWorld {
return w.getGenerator().getHandle() instanceof GeneratorWrapper;
}
public TerraBiomeGrid getGrid() {
return grid;
public BiomeProvider getBiomeProvider() {
return provider;
}
public ConfigPack getConfig() {
return config;
}
public BiomeZone getZone() {
return zone;
}
public boolean isSafe() {
return safe;
}

View File

@@ -6,11 +6,9 @@ import com.dfsek.terra.api.math.ProbabilityCollection;
import com.dfsek.terra.api.math.Range;
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.palette.PaletteHolder;
import com.dfsek.terra.biome.palette.PaletteLayer;
import com.dfsek.terra.carving.CarverPalette;
import com.dfsek.terra.config.loaders.ImageLoaderLoader;
import com.dfsek.terra.config.loaders.MaterialSetLoader;
import com.dfsek.terra.config.loaders.ProbabilityCollectionLoader;
import com.dfsek.terra.config.loaders.RangeLoader;
@@ -24,7 +22,6 @@ import com.dfsek.terra.config.loaders.palette.CarverPaletteLoader;
import com.dfsek.terra.config.loaders.palette.PaletteHolderLoader;
import com.dfsek.terra.config.loaders.palette.PaletteLayerLoader;
import com.dfsek.terra.generation.config.NoiseBuilder;
import com.dfsek.terra.image.ImageLoader;
import com.dfsek.terra.population.items.flora.FloraLayer;
import com.dfsek.terra.population.items.flora.TerraFlora;
import com.dfsek.terra.population.items.ores.Ore;
@@ -55,10 +52,6 @@ public class GenericLoaders implements LoaderRegistrar {
.registerLoader(TreeLayer.class, new TreeLayerLoader())
.registerLoader(MaterialSet.class, new MaterialSetLoader())
.registerLoader(OreHolder.class, new OreHolderLoader())
.registerLoader(ImageLoader.class, new ImageLoaderLoader())
.registerLoader(TerraBiomeGrid.Type.class, (t, o, l) -> TerraBiomeGrid.Type.valueOf(o.toString()))
.registerLoader(ImageLoader.Channel.class, (t, o, l) -> ImageLoader.Channel.valueOf(o.toString()))
.registerLoader(ImageLoader.Align.class, (t, o, l) -> ImageLoader.Align.valueOf(o.toString()))
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf(o.toString()))
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()));
}

View File

@@ -178,6 +178,14 @@ public class Vector2 implements Cloneable {
return this;
}
public int getBlockX() {
return FastMath.floorToInt(x);
}
public int getBlockZ() {
return FastMath.floorToInt(z);
}
@Override
public String toString() {
return "(" + x + ", " + z + ")";

View File

@@ -9,8 +9,8 @@ import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import net.jafama.FastMath;
public class BiomeFunction implements Function<String> {
@@ -36,7 +36,7 @@ public class BiomeFunction implements Function<String> {
RotationUtil.rotateVector(xz, arguments.getRotation());
TerraBiomeGrid grid = main.getWorld(arguments.getBuffer().getOrigin().getWorld()).getGrid();
BiomeProvider grid = main.getWorld(arguments.getBuffer().getOrigin().getWorld()).getBiomeProvider();
return ((UserDefinedBiome) grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments).intValue(), FastMath.roundToInt(xz.getZ()))))).getID();
}

View File

@@ -12,9 +12,8 @@ import com.dfsek.terra.api.structures.parser.lang.functions.Function;
import com.dfsek.terra.api.structures.script.TerraImplementationArguments;
import com.dfsek.terra.api.structures.structure.RotationUtil;
import com.dfsek.terra.api.structures.tokenizer.Position;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.generation.math.SamplerCache;
import net.jafama.FastMath;
@@ -54,8 +53,8 @@ public class CheckFunction implements Function<String> {
if(comp > 0) return "LAND"; // If noise val is greater than zero, location will always be land.
TerraBiomeGrid grid = tw.getGrid();
UserDefinedBiome b = (UserDefinedBiome) grid.getBiome(vector.getBlockX(), vector.getBlockZ(), GenerationPhase.POPULATE);
BiomeProvider provider = tw.getBiomeProvider();
UserDefinedBiome b = (UserDefinedBiome) provider.getBiome(vector.getBlockX(), vector.getBlockZ());
BiomeTemplate c = b.getConfig();
if(vector.getY() > c.getSeaLevel()) return "AIR"; // Above sea level

View File

@@ -1,115 +0,0 @@
package com.dfsek.terra.api.world.biome;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.world.generation.GenerationPhase;
public abstract class BiomeGrid {
private final FastNoiseLite noiseX;
private final FastNoiseLite noiseZ;
private final int sizeX;
private final int sizeZ;
private TerraBiome[][] grid;
public BiomeGrid(long seed, double freq1, double freq2, int sizeX, int sizeZ) {
this.sizeX = sizeX;
this.sizeZ = sizeZ;
this.noiseX = new FastNoiseLite((int) seed);
this.noiseZ = new FastNoiseLite((int) seed + 1);
this.noiseX.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
this.noiseX.setFractalType(FastNoiseLite.FractalType.FBm);
this.noiseX.setFractalOctaves(4);
this.noiseZ.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
this.noiseZ.setFractalType(FastNoiseLite.FractalType.FBm);
this.noiseZ.setFractalOctaves(4);
this.noiseX.setFrequency(freq1);
this.noiseZ.setFrequency(freq2);
}
/**
* Gets the biome at a pair of coordinates.
*
* @param x - X-coordinate at which to fetch biome
* @param z - Z-coordinate at which to fetch biome
* @return TerraBiome - TerraBiome at the given coordinates.
*/
public TerraBiome getBiome(int x, int z, GenerationPhase phase) {
return grid[getBiomeNoiseX(x, z)][getBiomeNoiseZ(x, z)];
}
/**
* Gets the biome at a location.
*
* @param l - The location at which to fetch the biome.
* @return TerraBiome - TerraBiome at the given coordinates.
*/
public TerraBiome getBiome(Location l) {
return getBiome(l, GenerationPhase.POST_GEN);
}
public double[] getRawNoise(int x, int z) {
return new double[] {noiseX.getNoise(x, z), noiseZ.getNoise(x, z)};
}
/**
* Get the raw X-noise for coordinates in the Grid.
*
* @param x X coordinate
* @param z Z coordinate
* @return Normalized noise
*/
public int getBiomeNoiseX(int x, int z) {
return normalize(noiseX.getNoise(x, z), sizeX);
}
/**
* Get the raw Z-noise for coordinates in the Grid.
*
* @param x X coordinate
* @param z Z coordinate
* @return Normalized noise
*/
public int getBiomeNoiseZ(int x, int z) {
return normalize(noiseZ.getNoise(x, z), sizeZ);
}
public TerraBiome[][] getGrid() {
return grid;
}
public void setGrid(TerraBiome[][] grid) {
if(grid.length != sizeX) throw new IllegalArgumentException("Invalid length for grid, expected " + sizeX + ", got " + grid.length);
for(TerraBiome[] gridLayer : grid) {
if(gridLayer.length != sizeZ)
throw new IllegalArgumentException("Invalid length for grid layer, expected " + sizeZ + ", got " + gridLayer.length);
}
this.grid = grid;
}
public TerraBiome getBiome(Location l, GenerationPhase phase) {
double biomeNoise = noiseX.getNoise(l.getBlockX(), l.getBlockZ());
double climateNoise = noiseZ.getNoise(l.getBlockX(), l.getBlockZ());
return grid[normalize(biomeNoise, sizeX)][normalize(climateNoise, sizeZ)];
}
public int getSizeX() {
return sizeX;
}
public int getSizeZ() {
return sizeZ;
}
/**
* Takes a noise input and normalizes it to a value between 0 and 15 inclusive.
*
* @param i - The noise value to normalize.
* @return int - The normalized value.
*/
protected int normalize(double i, int range) {
return NormalizationUtil.normalize(i, range, 4);
}
}

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,7 @@ import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.BiomeProvider;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
@@ -15,8 +14,8 @@ import java.util.function.Consumer;
*/
public class AsyncBiomeFinder extends AsyncFeatureFinder<TerraBiome> {
public AsyncBiomeFinder(TerraBiomeGrid grid, TerraBiome target, @NotNull Location origin, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
super(grid, target, origin, startRadius, maxRadius, callback, main);
public AsyncBiomeFinder(BiomeProvider provider, TerraBiome target, @NotNull Location origin, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
super(provider, target, origin, startRadius, maxRadius, callback, main);
}
/**
@@ -29,7 +28,7 @@ public class AsyncBiomeFinder extends AsyncFeatureFinder<TerraBiome> {
@Override
public boolean isValid(int x, int z, TerraBiome target) {
int res = main.getTerraConfig().getBiomeSearchResolution();
return getGrid().getBiome(x * res, z * res, GenerationPhase.POST_GEN).equals(target);
return getProvider().getBiome(x * res, z * res).equals(target);
}
@Override

View File

@@ -4,13 +4,13 @@ import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.BiomeProvider;
import org.jetbrains.annotations.NotNull;
import java.util.function.Consumer;
public abstract class AsyncFeatureFinder<T> implements Runnable {
protected final TerraBiomeGrid grid;
protected final BiomeProvider provider;
protected final T target;
protected final int startRadius;
protected final int maxRadius;
@@ -21,8 +21,8 @@ public abstract class AsyncFeatureFinder<T> implements Runnable {
protected int searchSize = 1;
protected final TerraPlugin main;
public AsyncFeatureFinder(TerraBiomeGrid grid, T target, @NotNull Location origin, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
this.grid = grid;
public AsyncFeatureFinder(BiomeProvider provider, T target, @NotNull Location origin, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
this.provider = provider;
this.target = target;
this.main = main;
this.startRadius = startRadius;
@@ -83,8 +83,8 @@ public abstract class AsyncFeatureFinder<T> implements Runnable {
return world;
}
public TerraBiomeGrid getGrid() {
return grid;
public BiomeProvider getProvider() {
return provider;
}
public int getSearchSize() {

View File

@@ -6,8 +6,8 @@ import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.population.items.TerraStructure;
import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
@@ -16,8 +16,8 @@ import java.util.Random;
import java.util.function.Consumer;
public class AsyncStructureFinder extends AsyncFeatureFinder<TerraStructure> {
public AsyncStructureFinder(TerraBiomeGrid grid, TerraStructure target, @NotNull Location origin, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
super(grid, target, origin, startRadius, maxRadius, callback, main);
public AsyncStructureFinder(BiomeProvider provider, TerraStructure target, @NotNull Location origin, int startRadius, int maxRadius, Consumer<Vector3> callback, TerraPlugin main) {
super(provider, target, origin, startRadius, maxRadius, callback, main);
setSearchSize(target.getSpawn().getWidth() + 2 * target.getSpawn().getSeparation());
}
@@ -29,7 +29,7 @@ public class AsyncStructureFinder extends AsyncFeatureFinder<TerraStructure> {
@Override
public boolean isValid(int x, int z, TerraStructure target) {
Location spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed()).toLocation(world);
if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(target)) return false;
if(!((UserDefinedBiome) provider.getBiome(spawn)).getConfig().getStructures().contains(target)) return false;
Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed()));
return target.getStructure().get(random).test(spawn.setY(target.getSpawnStart().get(random)), random, Rotation.fromDegrees(90 * random.nextInt(4)));
}

View File

@@ -0,0 +1,26 @@
package com.dfsek.terra.biome;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.math.vector.Vector3;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeProvider {
TerraBiome getBiome(int x, int z);
default TerraBiome getBiome(Vector2 vector2) {
return getBiome(vector2.getBlockX(), vector2.getBlockZ());
}
default TerraBiome getBiome(Vector3 vector3) {
return getBiome(vector3.getBlockX(), vector3.getBlockZ());
}
default TerraBiome getBiome(Location location) {
return getBiome(location.getBlockX(), location.getBlockZ());
}
interface BiomeProviderBuilder {
BiomeProvider build(long seed);
}
}

View File

@@ -1,78 +0,0 @@
package com.dfsek.terra.biome;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.api.world.biome.NormalizationUtil;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigPackTemplate;
import com.dfsek.terra.image.ImageLoader;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
/**
* Holds 1D array of BiomeGrids.
*/
public class BiomeZone {
private final BiomeGrid[] grids;
private final FastNoiseLite noise;
@Nullable
private final ImageLoader imageLoader;
private final boolean useImage;
private final ImageLoader.Channel channel;
public BiomeZone(long seed, ConfigPack wc, BiomeGrid[] grids) {
this.noise = new FastNoiseLite((int) seed + 2);
this.noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
this.noise.setFractalType(FastNoiseLite.FractalType.FBm);
this.noise.setFractalOctaves(4);
ConfigPackTemplate t = wc.getTemplate();
this.noise.setFrequency(1D / (t.getZoneFreq() * grids.length));
this.grids = grids;
imageLoader = t.getImageLoader();
useImage = t.isFromImage();
channel = t.getZoneChannel();
}
/**
* Get BiomeGrid at location
*
* @param x X coordinate
* @param z Z coordinate
* @return BiomeGrid at coordinates.
*/
public BiomeGrid getGrid(int x, int z) {
return grids[getNoise(x, z)];
}
/**
* Get the number of BiomeGrids this BiomeZone holds.
*
* @return Number of grids
*/
public int getSize() {
return grids.length;
}
/**
* Get the normalized grid noise at location
*
* @param x X coordinate
* @param z Z coordinate
* @return Normalized noise at coordinates
*/
public int getNoise(int x, int z) {
return useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, getSize() - 1, channel) : NormalizationUtil.normalize(noise.getNoise(x, z), grids.length, 4);
}
/**
* Get raw grid noise at location
*
* @param x X coordinate
* @param z Z coordinate
* @return Raw noise at coordinates
*/
public double getRawNoise(int x, int z) {
return useImage ? Objects.requireNonNull(imageLoader).getNoiseVal(x, z, getSize() - 1, channel) : noise.getNoise(x, z);
}
}

View File

@@ -0,0 +1,65 @@
package com.dfsek.terra.biome;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.biome.pipeline.BiomeHolder;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
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;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
public class StandardBiomeProvider implements BiomeProvider {
private final BiomePipeline pipeline;
private final LoadingCache<Vector2, BiomeHolder> cache = CacheBuilder.newBuilder()
.maximumSize(1024)
.build(
new CacheLoader<Vector2, BiomeHolder>() {
@Override
public BiomeHolder load(@NotNull Vector2 key) {
return pipeline.getBiomes(key.getBlockX(), key.getBlockZ());
}
}
);
private int resolution = 4;
protected StandardBiomeProvider(BiomePipeline pipeline) {
this.pipeline = pipeline;
}
@Override
public TerraBiome getBiome(int x, int z) {
x /= resolution;
z /= resolution;
try {
return cache.get(new Vector2(FastMath.floorDiv(x, pipeline.getSize()), FastMath.floorDiv(z, pipeline.getSize()))).getBiome(FastMath.floorMod(x, pipeline.getSize()), FastMath.floorMod(z, pipeline.getSize()));
} catch(ExecutionException e) {
throw new RuntimeException(e);
}
}
public int getResolution() {
return resolution;
}
public void setResolution(int resolution) {
this.resolution = resolution;
}
public static final class StandardBiomeProviderBuilder implements BiomeProviderBuilder {
private final Function<Long, BiomePipeline> pipelineBuilder;
public StandardBiomeProviderBuilder(Function<Long, BiomePipeline> pipelineBuilder) {
this.pipelineBuilder = pipelineBuilder;
}
@Override
public StandardBiomeProvider build(long seed) {
return new StandardBiomeProvider(pipelineBuilder.apply(seed));
}
}
}

View File

@@ -7,6 +7,7 @@ import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.builder.GeneratorBuilder;
import com.dfsek.terra.config.templates.BiomeTemplate;
import java.util.HashSet;
import java.util.Set;
/**
@@ -30,7 +31,7 @@ public class UserDefinedBiome implements TerraBiome {
this.config = config;
this.pack = pack;
this.color = config.getColor();
this.tags = config.getTags();
this.tags = config.getTags() == null ? new HashSet<>() : config.getTags();
tags.add("BIOME:" + id);
}

View File

@@ -1,28 +0,0 @@
package com.dfsek.terra.biome.grid;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
/**
* BiomeGrid implementation that holds a single biome.
*/
public class SingleBiomeGrid extends BiomeGrid {
private final TerraBiome biome;
public SingleBiomeGrid(long seed, TerraBiome biome) {
super(seed, 0, 0, 1, 1);
this.biome = biome;
}
@Override
public TerraBiome getBiome(int x, int z, GenerationPhase phase) {
return biome;
}
@Override
public TerraBiome getBiome(Location l) {
return biome;
}
}

View File

@@ -1,41 +0,0 @@
package com.dfsek.terra.biome.grid;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigPackTemplate;
import com.dfsek.terra.image.ImageLoader;
public class UserDefinedGrid extends BiomeGrid {
private final ImageLoader imageLoader;
private final boolean fromImage;
private final ImageLoader.Channel channelX;
private final ImageLoader.Channel channelZ;
public UserDefinedGrid(long seed, double freq1, double freq2, TerraBiome[][] b, ConfigPack c) {
super(seed, freq1, freq2, b.length, b[0].length);
super.setGrid(b);
ConfigPackTemplate t = c.getTemplate();
imageLoader = t.getImageLoader();
fromImage = t.isFromImage();
channelX = t.getBiomeXChannel();
channelZ = t.getBiomeZChannel();
}
@Override
public TerraBiome getBiome(int x, int z, GenerationPhase phase) {
if(fromImage) {
int xi = imageLoader.getNoiseVal(x, z, getSizeX() - 1, channelX);
int zi = imageLoader.getNoiseVal(x, z, getSizeZ() - 1, channelZ);
return super.getGrid()[xi][zi];
}
return super.getBiome(x, z, phase);
}
@Override
public TerraBiome getBiome(Location l, GenerationPhase phase) {
return this.getBiome(l.getBlockX(), l.getBlockZ(), phase);
}
}

View File

@@ -1,70 +0,0 @@
package com.dfsek.terra.biome.grid.master;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigPackTemplate;
import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
import com.dfsek.terra.debug.Debug;
public abstract class TerraBiomeGrid extends BiomeGrid {
protected final BiomeZone zone;
public TerraBiomeGrid(long seed, int sizeX, int sizeZ, BiomeZone zone) {
super(seed, 0, 0, sizeX, sizeZ);
this.zone = zone;
}
public BiomeZone getZone() {
return zone;
}
public abstract BiomeGrid getGrid(int x, int z);
public enum Type {
RADIAL, STANDARD
}
public abstract boolean isEroded(int x, int z);
public static final class TerraBiomeGridBuilder {
private final long seed;
private final ConfigPack config;
private final TerraPlugin main;
public TerraBiomeGridBuilder(long seed, ConfigPack config, TerraPlugin main) {
this.seed = seed;
this.config = config;
this.main = main;
}
public TerraBiomeGrid build() {
ConfigPackTemplate template = config.getTemplate();
int zoneSize = template.getGrids().size();
BiomeGrid[] definedGrids = new BiomeGrid[zoneSize];
for(int i = 0; i < zoneSize; i++) {
String partName = template.getGrids().get(i);
try {
BiomeGridBuilder g = config.getBiomeGrid(partName);
BiomeGrid b = g.build(seed, config);
definedGrids[i] = b;
} catch(NullPointerException e) {
Debug.stack(e);
main.getLogger().severe("No such BiomeGrid " + partName);
main.getLogger().severe("Please check configuration files for errors. Configuration errors will have been reported during initialization.");
main.getLogger().severe("ONLY report this to Terra if you are SURE your config is error-free.");
main.getLogger().severe("Terrain will NOT generate properly at this point. Correct your config before using your server!");
}
}
BiomeZone zone = new BiomeZone(seed, config, definedGrids);
if(template.getGridType().equals(TerraBiomeGrid.Type.RADIAL)) {
BiomeGrid internal = config.getBiomeGrid(template.getRadialInternalGrid()).build(seed, config);
return new TerraRadialBiomeGrid(seed, zone, config, template.getRadialGridRadius(), internal);
} else return new TerraStandardBiomeGrid(seed, zone, config);
}
}
}

View File

@@ -1,68 +0,0 @@
package com.dfsek.terra.biome.grid.master;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.postprocessing.CoordinatePerturb;
import com.dfsek.terra.biome.postprocessing.ErosionNoise;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigPackTemplate;
import net.jafama.FastMath;
public class TerraRadialBiomeGrid extends TerraBiomeGrid {
private final double radiusSq;
private final BiomeGrid internal;
private CoordinatePerturb perturb;
private ErosionNoise erode;
public TerraRadialBiomeGrid(long seed, BiomeZone zone, ConfigPack c, double radius, BiomeGrid internal) {
super(seed, 0, 0, zone);
ConfigPackTemplate t = c.getTemplate();
if(c.getTemplate().isBlend()) {
perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), seed);
}
if(c.getTemplate().isErode()) {
erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), seed);
}
this.radiusSq = FastMath.pow2(radius);
this.internal = internal;
}
@Override
public BiomeGrid getGrid(int x, int z) {
return zone.getGrid(x, z);
}
@Override
public boolean isEroded(int x, int z) {
return erode != null && erode.isEroded(x, z);
}
@Override
public TerraBiome getBiome(int x, int z, GenerationPhase phase) {
int xp = x, zp = z;
if(perturb != null && (phase.equals(GenerationPhase.PALETTE_APPLY) || phase.equals(GenerationPhase.POPULATE))) {
Vector2 perturbCoords = perturb.getShiftedCoords(x, z);
xp = (int) perturbCoords.getX();
zp = (int) perturbCoords.getZ();
}
UserDefinedBiome b;
if(x * x + z * z > radiusSq) {
b = (UserDefinedBiome) zone.getGrid(xp, zp).getBiome(xp, zp, phase);
} else {
b = (UserDefinedBiome) internal.getBiome(xp, zp, phase);
}
if(isEroded(xp, zp)) return b.getErode();
return b;
}
@Override
public TerraBiome getBiome(Location l, GenerationPhase phase) {
return getBiome(l.getBlockX(), l.getBlockZ(), phase);
}
}

View File

@@ -1,59 +0,0 @@
package com.dfsek.terra.biome.grid.master;
import com.dfsek.terra.api.math.vector.Location;
import com.dfsek.terra.api.math.vector.Vector2;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.postprocessing.CoordinatePerturb;
import com.dfsek.terra.biome.postprocessing.ErosionNoise;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.config.base.ConfigPackTemplate;
public class TerraStandardBiomeGrid extends TerraBiomeGrid {
private CoordinatePerturb perturb;
private ErosionNoise erode;
public TerraStandardBiomeGrid(long seed, BiomeZone zone, ConfigPack c) {
super(seed, 0, 0, zone);
ConfigPackTemplate t = c.getTemplate();
if(c.getTemplate().isBlend()) {
perturb = new CoordinatePerturb(t.getBlendFreq(), t.getBlendAmp(), seed);
}
if(c.getTemplate().isErode()) {
erode = new ErosionNoise(t.getErodeFreq(), t.getErodeThresh(), t.getErodeOctaves(), seed);
}
}
@Override
public BiomeGrid getGrid(int x, int z) {
return zone.getGrid(x, z);
}
@Override
public boolean isEroded(int x, int z) {
return erode != null && erode.isEroded(x, z);
}
@Override
public TerraBiome getBiome(int x, int z, GenerationPhase phase) {
int xp = x, zp = z;
if(perturb != null && (phase.equals(GenerationPhase.PALETTE_APPLY) || phase.equals(GenerationPhase.POPULATE))) {
Vector2 perturbCoords = perturb.getShiftedCoords(x, z);
xp = (int) perturbCoords.getX();
zp = (int) perturbCoords.getZ();
}
UserDefinedBiome b = (UserDefinedBiome) zone.getGrid(xp, zp).getBiome(xp, zp, phase);
if(isEroded(xp, zp)) return b.getErode();
return b;
}
@Override
public TerraBiome getBiome(Location l, GenerationPhase phase) {
return getBiome(l.getBlockX(), l.getBlockZ(), phase);
}
}

View File

@@ -30,8 +30,6 @@ public class TerraBiomeHolder implements BiomeHolder {
biomes = new TerraBiome[newWidth][newWidth];
System.out.println(biomes.length);
for(int x = 0; x < width; x++) {
for(int z = 0; z < width; z++) {
biomes[x * 2][z * 2] = old[x][z];

View File

@@ -8,9 +8,8 @@ import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.util.GlueList;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.carving.Worm;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import java.util.Collections;
import java.util.LinkedHashMap;
@@ -38,7 +37,7 @@ public class CarverCache {
public List<Worm.WormPoint> getPoints(int chunkX, int chunkZ, UserDefinedCarver carver) {
synchronized(carvers) {
return carvers.computeIfAbsent(MathUtil.squash(chunkX, chunkZ), key -> {
TerraBiomeGrid grid = main.getWorld(w).getGrid();
BiomeProvider provider = main.getWorld(w).getBiomeProvider();
if(carver.isChunkCarved(w, chunkX, chunkZ, new FastRandom(MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed() + carver.hashCode())))) {
long seed = MathUtil.getCarverChunkSeed(chunkX, chunkZ, w.getSeed());
carver.getSeedVar().setValue(seed);
@@ -47,7 +46,7 @@ public class CarverCache {
List<Worm.WormPoint> points = new GlueList<>();
for(int i = 0; i < carving.getLength(); i++) {
carving.step();
TerraBiome biome = grid.getBiome(carving.getRunning().toLocation(w), GenerationPhase.POPULATE);
TerraBiome biome = provider.getBiome(carving.getRunning().toLocation(w));
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(carver)) { // Stop if we enter a biome this carver is not present in
return new GlueList<>();
}

View File

@@ -8,7 +8,6 @@ import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.carving.Carver;
import com.dfsek.terra.api.world.carving.Worm;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
@@ -121,7 +120,7 @@ public class UserDefinedCarver extends Carver {
@Override
public boolean isChunkCarved(World w, int chunkX, int chunkZ, Random random) {
BiomeTemplate conf = ((UserDefinedBiome) main.getWorld(w).getGrid().getBiome((chunkX << 4) + 8, (chunkZ << 4) + 8, GenerationPhase.POPULATE)).getConfig();
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);
}

View File

@@ -13,13 +13,11 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.flora.Flora;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.api.world.tree.Tree;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.carving.UserDefinedCarver;
import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
import com.dfsek.terra.config.exception.FileMissingException;
import com.dfsek.terra.config.factories.BiomeFactory;
import com.dfsek.terra.config.factories.BiomeGridFactory;
import com.dfsek.terra.config.factories.CarverFactory;
import com.dfsek.terra.config.factories.FloraFactory;
import com.dfsek.terra.config.factories.OreFactory;
@@ -31,8 +29,8 @@ import com.dfsek.terra.config.files.FolderLoader;
import com.dfsek.terra.config.files.Loader;
import com.dfsek.terra.config.files.ZIPLoader;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.config.loaders.config.BiomeProviderBuilderLoader;
import com.dfsek.terra.config.templates.AbstractableTemplate;
import com.dfsek.terra.config.templates.BiomeGridTemplate;
import com.dfsek.terra.config.templates.BiomeTemplate;
import com.dfsek.terra.config.templates.CarverTemplate;
import com.dfsek.terra.config.templates.FloraTemplate;
@@ -43,7 +41,6 @@ import com.dfsek.terra.config.templates.TreeTemplate;
import com.dfsek.terra.generation.math.SamplerCache;
import com.dfsek.terra.population.items.TerraStructure;
import com.dfsek.terra.population.items.ores.Ore;
import com.dfsek.terra.registry.BiomeGridRegistry;
import com.dfsek.terra.registry.BiomeRegistry;
import com.dfsek.terra.registry.CarverRegistry;
import com.dfsek.terra.registry.FloraRegistry;
@@ -82,7 +79,6 @@ public class ConfigPack implements LoaderRegistrar {
private final ConfigPackTemplate template = new ConfigPackTemplate();
private final BiomeRegistry biomeRegistry = new BiomeRegistry();
private final BiomeGridRegistry biomeGridRegistry = new BiomeGridRegistry(biomeRegistry);
private final StructureRegistry structureRegistry = new StructureRegistry();
private final CarverRegistry carverRegistry = new CarverRegistry();
private final PaletteRegistry paletteRegistry;
@@ -106,6 +102,7 @@ public class ConfigPack implements LoaderRegistrar {
paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(main);
register(abstractConfigLoader);
register(selfLoader);
main.register(selfLoader);
main.register(abstractConfigLoader);
@@ -128,6 +125,7 @@ public class ConfigPack implements LoaderRegistrar {
paletteRegistry = new PaletteRegistry(main);
treeRegistry = new TreeRegistry(main);
register(abstractConfigLoader);
register(selfLoader);
main.register(selfLoader);
main.register(abstractConfigLoader);
@@ -184,8 +182,7 @@ public class ConfigPack implements LoaderRegistrar {
.open("structures/structures", ".yml").then(streams -> buildAll(new StructureFactory(), structureRegistry, abstractConfigLoader.load(streams, StructureTemplate::new), main)).close()
.open("flora", ".yml").then(streams -> buildAll(new FloraFactory(), floraRegistry, abstractConfigLoader.load(streams, FloraTemplate::new), main)).close()
.open("carving", ".yml").then(streams -> buildAll(new CarverFactory(this), carverRegistry, abstractConfigLoader.load(streams, CarverTemplate::new), main)).close()
.open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).close()
.open("grids", ".yml").then(streams -> buildAll(new BiomeGridFactory(), biomeGridRegistry, abstractConfigLoader.load(streams, BiomeGridTemplate::new), main)).close();
.open("biomes", ".yml").then(streams -> buildAll(new BiomeFactory(this), biomeRegistry, abstractConfigLoader.load(streams, () -> new BiomeTemplate(this, main)), main)).close();
for(UserDefinedBiome b : biomeRegistry.entries()) {
@@ -196,14 +193,6 @@ public class ConfigPack implements LoaderRegistrar {
}
}
for(String gridName : template.getGrids()) {
if(!biomeGridRegistry.contains(gridName)) throw new LoadException("No such BiomeGrid \"" + gridName + "\"");
}
if(template.getGridType().equals(TerraBiomeGrid.Type.RADIAL) && !biomeGridRegistry.contains(template.getRadialInternalGrid())) {
throw new LoadException("No such BiomeGrid \"" + template.getRadialInternalGrid() + "\"");
}
LangUtil.log("config-pack.loaded", Level.INFO, template.getID(), String.valueOf((System.nanoTime() - start) / 1000000D), template.getAuthor(), template.getVersion());
}
@@ -215,10 +204,6 @@ public class ConfigPack implements LoaderRegistrar {
return biomeRegistry.get(id);
}
public BiomeGridBuilder getBiomeGrid(String id) {
return biomeGridRegistry.get(id);
}
public List<String> getBiomeIDs() {
List<String> biomeIDs = new ArrayList<>();
biomeRegistry.forEach(biome -> biomeIDs.add(biome.getID()));
@@ -271,7 +256,8 @@ public class ConfigPack implements LoaderRegistrar {
.registerLoader(Tree.class, treeRegistry)
.registerLoader(StructureScript.class, scriptRegistry)
.registerLoader(TerraStructure.class, structureRegistry)
.registerLoader(LootTable.class, lootRegistry);
.registerLoader(LootTable.class, lootRegistry)
.registerLoader(BiomeProvider.BiomeProviderBuilder.class, new BiomeProviderBuilderLoader(this));
}
public ScriptRegistry getScriptRegistry() {

View File

@@ -5,9 +5,8 @@ import com.dfsek.tectonic.annotations.Value;
import com.dfsek.tectonic.config.ValidatedConfigTemplate;
import com.dfsek.tectonic.exception.ValidationException;
import com.dfsek.terra.api.math.MathUtil;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.generation.config.NoiseBuilder;
import com.dfsek.terra.image.ImageLoader;
import net.jafama.FastMath;
import java.util.HashMap;
@@ -101,36 +100,12 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate {
@Default
private String version = "0.1.0";
@Value("grid-options.type")
@Default
private TerraBiomeGrid.Type gridType = TerraBiomeGrid.Type.STANDARD;
@Value("grid-options.radial.radius")
@Default
private double radius = 1000D;
@Value("grid-options.radial.internal-grid")
@Default
private String internalGrid = null;
@Value("image.enable")
@Default
private boolean fromImage = false;
@Value("image.channels.biome-x")
@Default
private ImageLoader.Channel biomeXChannel = ImageLoader.Channel.RED;
@Value("image.channels.biome-z")
@Default
private ImageLoader.Channel biomeZChannel = ImageLoader.Channel.GREEN;
@Value("image.channels.zone")
@Default
private ImageLoader.Channel zoneChannel = ImageLoader.Channel.BLUE;
@Value("image")
@Default
private ImageLoader imageLoader = null;
@Value("biome-pipeline")
private BiomeProvider.BiomeProviderBuilder providerBuilder;
public BiomeProvider.BiomeProviderBuilder getProviderBuilder() {
return providerBuilder;
}
public String getVersion() {
return version;
@@ -172,7 +147,6 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate {
return variables;
}
public List<String> getGrids() {
return grids;
}
@@ -209,38 +183,6 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate {
return erodeOctaves;
}
public double getRadialGridRadius() {
return radius;
}
public String getRadialInternalGrid() {
return internalGrid;
}
public TerraBiomeGrid.Type getGridType() {
return gridType;
}
public ImageLoader.Channel getBiomeXChannel() {
return biomeXChannel;
}
public ImageLoader.Channel getBiomeZChannel() {
return biomeZChannel;
}
public boolean isFromImage() {
return fromImage;
}
public ImageLoader.Channel getZoneChannel() {
return zoneChannel;
}
public ImageLoader getImageLoader() {
return imageLoader;
}
public int getBaseBlend() {
return baseBlend;
}
@@ -255,11 +197,6 @@ public class ConfigPackTemplate implements ValidatedConfigTemplate {
@Override
public boolean validate() throws ValidationException {
if(gridType.equals(TerraBiomeGrid.Type.RADIAL) && internalGrid == null)
throw new ValidationException("No internal BiomeGrid specified");
if(biomeZChannel.equals(biomeXChannel) || zoneChannel.equals(biomeXChannel) || zoneChannel.equals(biomeZChannel))
throw new ValidationException("2 objects share the same image channels: biome-x and biome-z");
if(!MathUtil.equals(FastMath.log(baseBlend) / FastMath.log(2d), FastMath.round(FastMath.log(baseBlend) / FastMath.log(2d)))) {
throw new ValidationException("TerraBiome base blend value \"" + baseBlend + "\" is not a power of 2.");
}

View File

@@ -1,8 +0,0 @@
package com.dfsek.terra.config.builder.biomegrid;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.config.base.ConfigPack;
public interface BiomeGridBuilder {
BiomeGrid build(long seed, ConfigPack config);
}

View File

@@ -1,18 +0,0 @@
package com.dfsek.terra.config.builder.biomegrid;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.biome.grid.SingleBiomeGrid;
import com.dfsek.terra.config.base.ConfigPack;
public class SingleGridBuilder implements BiomeGridBuilder {
private final TerraBiome biome;
public SingleGridBuilder(TerraBiome biome) {
this.biome = biome;
}
@Override
public SingleBiomeGrid build(long seed, ConfigPack config) {
return new SingleBiomeGrid(seed, biome);
}
}

View File

@@ -1,41 +0,0 @@
package com.dfsek.terra.config.builder.biomegrid;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.biome.grid.UserDefinedGrid;
import com.dfsek.terra.config.base.ConfigPack;
public class UserDefinedGridBuilder implements BiomeGridBuilder {
private double xFreq;
private double zFreq;
private TerraBiome[][] biomes;
@Override
public UserDefinedGrid build(long seed, ConfigPack config) {
return new UserDefinedGrid(seed, 1D / xFreq, 1D / zFreq, biomes, config);
}
public double getXFreq() {
return xFreq;
}
public void setXFreq(double xFreq) {
this.xFreq = xFreq;
}
public double getZFreq() {
return zFreq;
}
public void setZFreq(double zFreq) {
this.zFreq = zFreq;
}
public TerraBiome[][] getBiomes() {
return biomes;
}
public void setBiomes(TerraBiome[][] biomes) {
this.biomes = biomes;
}
}

View File

@@ -1,39 +0,0 @@
package com.dfsek.terra.config.factories;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
import com.dfsek.terra.config.builder.biomegrid.UserDefinedGridBuilder;
import com.dfsek.terra.config.templates.BiomeGridTemplate;
import java.util.List;
public class BiomeGridFactory implements TerraFactory<BiomeGridTemplate, BiomeGridBuilder> {
@Override
public UserDefinedGridBuilder build(BiomeGridTemplate config, TerraPlugin main) throws LoadException {
UserDefinedGridBuilder holder = new UserDefinedGridBuilder();
int xSize = config.getGrid().size();
int zSize = config.getGrid().get(0).size();
holder.setXFreq(config.getXFreq() * xSize);
holder.setZFreq(config.getZFreq() * zSize);
TerraBiome[][] biomes = new UserDefinedBiome[xSize][zSize];
for(int x = 0; x < xSize; x++) {
List<TerraBiome> layer = config.getGrid().get(x);
if(!(layer.size() == zSize)) throw new LoadException("Expected " + zSize + " biomes in row " + x + ", found " + layer.size());
for(int z = 0; z < zSize; z++) {
biomes[x][z] = layer.get(z);
}
}
holder.setBiomes(biomes);
return holder;
}
}

View File

@@ -1,25 +0,0 @@
package com.dfsek.terra.config.loaders;
import com.dfsek.tectonic.exception.LoadException;
import com.dfsek.tectonic.loading.ConfigLoader;
import com.dfsek.tectonic.loading.TypeLoader;
import com.dfsek.terra.image.ImageLoader;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
@SuppressWarnings("unchecked")
public class ImageLoaderLoader implements TypeLoader<ImageLoader> {
@Override
public ImageLoader load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
Map<String, Object> map = (Map<String, Object>) o;
File image = new File((String) map.get("file"));
try {
return new ImageLoader(image, (ImageLoader.Align) configLoader.loadType(ImageLoader.Align.class, map.get("align")));
} catch(IOException e) {
throw new LoadException("Unable to load image", e);
}
}
}

View File

@@ -0,0 +1,56 @@
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.ProbabilityCollection;
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.StandardBiomeProvider;
import com.dfsek.terra.biome.pipeline.BiomePipeline;
import com.dfsek.terra.biome.pipeline.expand.FractalExpander;
import com.dfsek.terra.biome.pipeline.mutator.SmoothMutator;
import com.dfsek.terra.biome.pipeline.source.RandomSource;
import com.dfsek.terra.biome.pipeline.stages.ExpanderStage;
import com.dfsek.terra.biome.pipeline.stages.MutatorStage;
import com.dfsek.terra.config.base.ConfigPack;
import net.jafama.FastMath;
import java.lang.reflect.Type;
public class BiomeProviderBuilderLoader implements TypeLoader<BiomeProvider.BiomeProviderBuilder> {
private final ConfigPack pack;
public BiomeProviderBuilderLoader(ConfigPack pack) {
this.pack = pack;
}
private static NoiseSampler whiteNoise(int seed) {
FastNoiseLite noiseLite = new FastNoiseLite(seed);
noiseLite.setNoiseType(FastNoiseLite.NoiseType.WhiteNoise);
return noiseLite;
}
@Override
public BiomeProvider.BiomeProviderBuilder load(Type t, Object c, ConfigLoader loader) {
return new StandardBiomeProvider.StandardBiomeProviderBuilder(seed -> {
ProbabilityCollection<TerraBiome> biomes = new ProbabilityCollection<>();
biomes.add(pack.getBiome("PLAINS"), 1)
.add(pack.getBiome("SAVANNA"), 2);
BiomePipeline pipeline = new BiomePipeline.BiomePipelineBuilder(2)
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(FastMath.toInt(seed)))))
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(FastMath.toInt(seed + 1)))))
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(FastMath.toInt(seed + 2)))))
.addStage(new MutatorStage(new SmoothMutator(whiteNoise(FastMath.toInt(seed + 3)))))
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(FastMath.toInt(seed + 4)))))
.addStage(new ExpanderStage(new FractalExpander(whiteNoise(FastMath.toInt(seed + 5)))))
.build(new RandomSource(biomes, whiteNoise(FastMath.toInt(seed) + 4)));
System.out.println(pipeline.getSize());
return pipeline;
});
}
}

View File

@@ -1,50 +0,0 @@
package com.dfsek.terra.config.templates;
import com.dfsek.tectonic.annotations.Abstractable;
import com.dfsek.tectonic.annotations.Value;
import com.dfsek.terra.api.world.biome.TerraBiome;
import java.util.List;
@SuppressWarnings("unused")
public class BiomeGridTemplate extends AbstractableTemplate {
@Value("id")
private String id;
/**
* A 2D array of {@link TerraBiome} IDs that make up this grid.
*/
@Value("grid")
@Abstractable
private List<List<TerraBiome>> grid;
/**
* X frequency of noise function
*/
@Value("frequency.x")
@Abstractable
private double xFreq;
/**
* Z frequency of noise function
*/
@Value("frequency.z")
@Abstractable
private double zFreq;
public String getID() {
return id;
}
public List<List<TerraBiome>> getGrid() {
return grid;
}
public double getXFreq() {
return xFreq;
}
public double getZFreq() {
return zFreq;
}
}

View File

@@ -15,9 +15,9 @@ import com.dfsek.terra.api.platform.world.BiomeGrid;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.profiler.ProfileFuture;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.api.world.generation.TerraChunkGenerator;
import com.dfsek.terra.api.world.palette.Palette;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.palette.SinglePalette;
import com.dfsek.terra.config.base.ConfigPack;
@@ -88,7 +88,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
@SuppressWarnings({"try"})
public ChunkGenerator.ChunkData generateChunkData(@NotNull World world, Random random, int chunkX, int chunkZ, ChunkGenerator.ChunkData chunk) {
TerraWorld tw = main.getWorld(world);
com.dfsek.terra.api.world.biome.BiomeGrid grid = tw.getGrid();
BiomeProvider grid = tw.getBiomeProvider();
try(ProfileFuture ignore = tw.getProfiler().measure("TotalChunkGenTime")) {
if(!tw.isSafe()) return chunk;
int xOrig = (chunkX << 4);
@@ -103,7 +103,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
int cx = xOrig + x;
int cz = zOrig + z;
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z, GenerationPhase.PALETTE_APPLY);
TerraBiome b = grid.getBiome(xOrig + x, zOrig + z);
BiomeTemplate c = ((UserDefinedBiome) b).getConfig();
int sea = c.getSeaLevel();
@@ -211,12 +211,12 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
public void generateBiomes(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, @NotNull BiomeGrid biome) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
com.dfsek.terra.api.world.biome.BiomeGrid grid = main.getWorld(world).getGrid();
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(byte z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz, GenerationPhase.PALETTE_APPLY);
TerraBiome b = grid.getBiome(cx, cz);
biome.setBiome(x << 2, z << 2, b.getVanillaBiome());
}

View File

@@ -1,7 +1,7 @@
package com.dfsek.terra.generation.math;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.generation.math.interpolation.ChunkInterpolator;
import com.dfsek.terra.generation.math.interpolation.ElevationInterpolator;
import net.jafama.FastMath;
@@ -10,9 +10,9 @@ public class Sampler {
private final ChunkInterpolator interpolator;
private final ElevationInterpolator elevationInterpolator;
public Sampler(int x, int z, TerraBiomeGrid grid, World world, int elevationSmooth, int generationSmooth) {
this.interpolator = new ChunkInterpolator(world, x, z, grid, generationSmooth);
this.elevationInterpolator = new ElevationInterpolator(world, x, z, grid, elevationSmooth);
public Sampler(int x, int z, BiomeProvider provider, World world, int elevationSmooth, int generationSmooth) {
this.interpolator = new ChunkInterpolator(world, x, z, provider, generationSmooth);
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
}
public double sample(double x, double y, double z) {

View File

@@ -56,7 +56,7 @@ public class SamplerCache {
public Sampler getChunk(int cx, int cz) {
long key = MathUtil.squash(cx, cz);
synchronized(cache) {
return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, terraWorld.getGrid(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend()));
return cache.computeIfAbsent(key, k -> new Sampler(cx, cz, terraWorld.getBiomeProvider(), world, terraWorld.getConfig().getTemplate().getBaseBlend(), terraWorld.getConfig().getTemplate().getElevationBlend()));
}
}
}

View File

@@ -2,8 +2,7 @@ package com.dfsek.terra.generation.math.interpolation;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.Generator;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.biome.BiomeProvider;
import net.jafama.FastMath;
/**
@@ -20,18 +19,18 @@ public class ChunkInterpolator {
/**
* Instantiates a 3D ChunkInterpolator at a pair of chunk coordinates.
*
* @param chunkX X coordinate of the chunk.
* @param chunkZ Z coordinate of the chunk.
* @param grid BiomeGrid to use for noise fetching.
* @param chunkX X coordinate of the chunk.
* @param chunkZ Z coordinate of the chunk.
* @param provider BiomeGrid to use for noise fetching.
*/
public ChunkInterpolator(World w, int chunkX, int chunkZ, TerraBiomeGrid grid, int smooth) {
public ChunkInterpolator(World w, int chunkX, int chunkZ, BiomeProvider provider, int smooth) {
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
this.smooth = smooth;
for(int x = -1; x < 6; x++) {
for(int z = -1; z < 6; z++) {
gens[x + 1][z + 1] = grid.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth), GenerationPhase.BASE).getGenerator(w);
gens[x + 1][z + 1] = provider.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth)).getGenerator(w);
}
}

View File

@@ -1,8 +1,7 @@
package com.dfsek.terra.generation.math.interpolation;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.BiomeGrid;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.generation.config.WorldGenerator;
import net.jafama.FastMath;
@@ -11,15 +10,15 @@ public class ElevationInterpolator {
private final double[][] values = new double[18][18];
private final int xOrigin;
private final int zOrigin;
private final BiomeGrid grid;
private final BiomeProvider provider;
private final int smooth;
private final int pow;
private final World world;
public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeGrid grid, int smooth) {
public ElevationInterpolator(World world, int chunkX, int chunkZ, BiomeProvider provider, int smooth) {
this.xOrigin = chunkX << 4;
this.zOrigin = chunkZ << 4;
this.grid = grid;
this.provider = provider;
this.smooth = smooth;
this.pow = FastMath.log2(smooth);
this.gens = new WorldGenerator[6 + 2 * pow][6 + 2 * pow];
@@ -28,7 +27,7 @@ public class ElevationInterpolator {
for(int x = -pow; x < 6 + pow; x++) {
for(int z = -pow; z < 6 + pow; z++) {
gens[x + pow][z + pow] = (WorldGenerator) grid.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth), GenerationPhase.BASE).getGenerator(world);
gens[x + pow][z + pow] = (WorldGenerator) provider.getBiome(xOrigin + (x * smooth), zOrigin + (z * smooth)).getGenerator(world);
}
}
@@ -47,7 +46,7 @@ public class ElevationInterpolator {
}
private WorldGenerator getGenerator(int x, int z) {
return (WorldGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator(world);
return (WorldGenerator) provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world);
}
private WorldGenerator getStoredGen(int x, int z) {

View File

@@ -1,124 +0,0 @@
package com.dfsek.terra.image;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.NormalizationUtil;
import com.dfsek.terra.biome.BiomeZone;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.debug.gui.DebugGUI;
import net.jafama.FastMath;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class ImageLoader {
private final BufferedImage image;
private final Align align;
public ImageLoader(File file, Align align) throws IOException {
image = ImageIO.read(file);
this.align = align;
}
public static void debugWorld(boolean genStep, World w, TerraPlugin main) {
if(!main.isDebug()) return;
BufferedImage newImg = new WorldImageGenerator(w, 1024, 1024, main).drawWorld(0, 0).getDraw();
if(genStep) newImg = redrawStepped(newImg, w, Align.CENTER, main);
DebugGUI debugGUI = new DebugGUI(newImg, main);
debugGUI.start();
}
private static BufferedImage redrawStepped(BufferedImage original, World w, Align align, TerraPlugin main) {
BufferedImage newImg = copyImage(original);
TerraBiomeGrid tb = main.getWorld(w).getGrid();
BiomeZone zone = main.getWorld(w).getZone();
for(int x = 0; x < newImg.getWidth(); x++) {
for(int y = 0; y < newImg.getHeight(); y++) {
double[] noise;
if(align.equals(Align.CENTER))
noise = tb.getGrid(x - original.getWidth() / 2, y - original.getHeight() / 2).getRawNoise(x - original.getWidth() / 2, y - original.getHeight() / 2);
else noise = tb.getGrid(x, y).getRawNoise(x, y);
newImg.setRGB(x, y, new Color((int) (NormalizationUtil.normalize(noise[0], tb.getGrid(x, y).getSizeX(), 4) * ((double) 255 / tb.getGrid(x, y).getSizeX())),
(int) (NormalizationUtil.normalize(noise[1], tb.getGrid(x, y).getSizeZ(), 4) * ((double) 255 / tb.getGrid(x, y).getSizeZ())),
(int) (NormalizationUtil.normalize(zone.getNoise(x, y), zone.getSize(), 4) * ((double) 255 / zone.getSize())))
.getRGB());
}
}
return newImg;
}
private static int normal(double val) {
return FastMath.floorToInt(FastMath.min(FastMath.max(val, 255), 0));
}
private static BufferedImage copyImage(BufferedImage source) {
BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
Graphics g = b.getGraphics();
g.drawImage(source, 0, 0, null);
g.dispose();
return b;
}
public void debug(boolean genStep, World w, TerraPlugin main) {
if(!main.isDebug()) return;
BufferedImage newImg = copyImage(image);
if(genStep) {
newImg = redrawStepped(image, w, align, main);
}
DebugGUI debugGUI = new DebugGUI(newImg, main);
debugGUI.start();
}
public int getNoiseVal(int x, int y, int size, Channel channel) {
return (size * getChannel(x, y, channel)) / 255;
}
public int getChannel(int x, int y, Channel channel) {
int rgb;
rgb = align.getRGB(image, x, y);
switch(channel) {
case RED:
return rgb >> 16 & 0xff;
case GREEN:
return rgb >> 8 & 0xff;
case BLUE:
return rgb & 0xff;
case ALPHA:
return rgb >> 24 & 0xff;
default:
throw new IllegalArgumentException();
}
}
public Align getAlign() {
return align;
}
public enum Channel {
RED, GREEN, BLUE, ALPHA
}
public enum Align {
CENTER {
@Override
public int getRGB(BufferedImage image, int x, int y) {
return Align.getRGBNoAlign(image, x - (image.getWidth() / 2), y - (image.getHeight() / 2));
}
},
NONE {
@Override
public int getRGB(BufferedImage image, int x, int y) {
return image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(y, image.getHeight()));
}
};
private static int getRGBNoAlign(BufferedImage image, int x, int y) {
return image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(y, image.getHeight()));
}
public abstract int getRGB(BufferedImage image, int x, int y);
}
}

View File

@@ -1,55 +0,0 @@
package com.dfsek.terra.image;
import com.dfsek.terra.TerraWorld;
import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.world.biome.NormalizationUtil;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class WorldImageGenerator {
private final World w;
private final BufferedImage draw;
private final TerraPlugin main;
public WorldImageGenerator(World w, int width, int height, TerraPlugin main) {
draw = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
this.w = w;
this.main = main;
}
public WorldImageGenerator drawWorld(int centerX, int centerZ) {
TerraWorld tw = main.getWorld(w);
TerraBiomeGrid tb = tw.getGrid();
int imY = 0;
for(int y = centerZ - (draw.getHeight() / 2); y < centerZ + (draw.getHeight() / 2); y++) {
int imX = 0;
for(int x = centerX - (draw.getWidth() / 2); x < centerX + (draw.getWidth() / 2); x++) {
int zone = NormalizationUtil.normalize(tw.getZone().getRawNoise(x, y), 256, 4);
double[] noise = tb.getGrid(x, y).getRawNoise(x, y);
Color c = new Color(NormalizationUtil.normalize(noise[0], 256, 4), NormalizationUtil.normalize(noise[1], 256, 4), zone);
draw.setRGB(imX, imY, c.getRGB());
imX++;
}
imY++;
}
return this;
}
public BufferedImage getDraw() {
return draw;
}
public void save(File file) {
try {
ImageIO.write(draw, "png", file);
} catch(IOException e) {
e.printStackTrace();
}
}
}

View File

@@ -6,10 +6,9 @@ import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.profiler.ProfileFuture;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.population.items.flora.FloraLayer;
import com.dfsek.terra.util.PopulationUtil;
import org.jetbrains.annotations.NotNull;
@@ -35,11 +34,11 @@ public class FloraPopulator implements TerraBlockPopulator {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("FloraTime")) {
if(!tw.isSafe()) return;
TerraBiomeGrid grid = tw.getGrid();
BiomeProvider provider = tw.getBiomeProvider();
Map<Vector2, List<FloraLayer>> layers = new HashMap<>();
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE);
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
Vector2 l = new Vector2(x, z);
layers.put(l, biome.getConfig().getFlora());
}

View File

@@ -9,7 +9,6 @@ import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.profiler.ProfileFuture;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.config.templates.BiomeTemplate;
@@ -35,7 +34,7 @@ public class OrePopulator implements TerraBlockPopulator {
Random random = new FastRandom(MathUtil.getCarverChunkSeed(chunk.getX() + cx, chunk.getZ() + cz, world.getSeed()));
int originX = ((chunk.getX() + cx) << 4);
int originZ = ((chunk.getZ() + cz) << 4);
TerraBiome b = tw.getGrid().getBiome(originX + 8, originZ + 8, GenerationPhase.POPULATE);
TerraBiome b = tw.getBiomeProvider().getBiome(originX + 8, originZ + 8);
BiomeTemplate config = ((UserDefinedBiome) b).getConfig();
int finalCx = cx;
int finalCz = cz;

View File

@@ -10,8 +10,8 @@ import com.dfsek.terra.api.profiler.ProfileFuture;
import com.dfsek.terra.api.structures.structure.Rotation;
import com.dfsek.terra.api.util.FastRandom;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.population.items.TerraStructure;
import net.jafama.FastMath;
@@ -34,12 +34,12 @@ public class StructurePopulator implements TerraBlockPopulator {
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
if(!tw.isSafe()) return;
TerraBiomeGrid grid = tw.getGrid();
BiomeProvider provider = tw.getBiomeProvider();
ConfigPack config = tw.getConfig();
for(TerraStructure conf : config.getStructures()) {
Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world);
if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(conf))
if(!((UserDefinedBiome) provider.getBiome(spawn)).getConfig().getStructures().contains(conf))
continue;
Random random = new FastRandom(MathUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed()));
conf.getStructure().get(random).execute(spawn.setY(conf.getSpawnStart().get(random)), chunk, random, Rotation.fromDegrees(90 * random.nextInt(4)));

View File

@@ -6,10 +6,9 @@ import com.dfsek.terra.api.platform.TerraPlugin;
import com.dfsek.terra.api.platform.world.Chunk;
import com.dfsek.terra.api.platform.world.World;
import com.dfsek.terra.api.profiler.ProfileFuture;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.api.world.generation.TerraBlockPopulator;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.population.items.tree.TreeLayer;
import com.dfsek.terra.util.PopulationUtil;
import net.jafama.FastMath;
@@ -35,11 +34,11 @@ public class TreePopulator implements TerraBlockPopulator {
TerraWorld tw = main.getWorld(world);
try(ProfileFuture ignored = tw.getProfiler().measure("TreeTime")) {
if(!tw.isSafe()) return;
TerraBiomeGrid grid = tw.getGrid();
BiomeProvider provider = tw.getBiomeProvider();
Random random = PopulationUtil.getRandom(chunk);
for(int x = 0; x < 16; x += 2) {
for(int z = 0; z < 16; z += 2) {
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE);
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z);
for(TreeLayer layer : biome.getConfig().getTrees()) {
if(layer.getDensity() >= random.nextDouble() * 100)
layer.place(chunk, new Vector2(offset(random, x), offset(random, z)));

View File

@@ -1,24 +0,0 @@
package com.dfsek.terra.registry;
import com.dfsek.terra.config.builder.biomegrid.BiomeGridBuilder;
import com.dfsek.terra.config.builder.biomegrid.SingleGridBuilder;
public class BiomeGridRegistry extends TerraRegistry<BiomeGridBuilder> {
private final BiomeRegistry biomeRegistry;
public BiomeGridRegistry(BiomeRegistry biomeRegistry) {
this.biomeRegistry = biomeRegistry;
}
@Override
public BiomeGridBuilder get(String id) {
if(id.startsWith("BIOME:")) return new SingleGridBuilder(biomeRegistry.get(id.substring(6)));
return super.get(id);
}
@Override
public boolean contains(String name) {
if(name.startsWith("BIOME:")) return biomeRegistry.contains(name.substring(6));
return super.contains(name);
}
}

View File

@@ -5,7 +5,6 @@ import com.dfsek.terra.bukkit.BukkitCommandSender;
import com.dfsek.terra.bukkit.command.Command;
import com.dfsek.terra.bukkit.command.command.biome.BiomeCommand;
import com.dfsek.terra.bukkit.command.command.geometry.GeometryCommand;
import com.dfsek.terra.bukkit.command.command.image.ImageCommand;
import com.dfsek.terra.bukkit.command.command.profile.ProfileCommand;
import com.dfsek.terra.bukkit.command.command.structure.StructureCommand;
import com.dfsek.terra.config.lang.LangUtil;
@@ -22,7 +21,6 @@ public class TerraCommand extends Command {
new ProfileCommand(this),
new SaveDataCommand(this),
new StructureCommand(this),
new ImageCommand(this),
new GeometryCommand(this),
new FixChunkCommand(this),
new VersionCommand(this),

View File

@@ -1,8 +1,7 @@
package com.dfsek.terra.bukkit.command.command.biome;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.lang.LangUtil;
@@ -23,8 +22,8 @@ public class BiomeCommand extends WorldCommand {
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) {
TerraBiomeGrid grid = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())).getGrid();
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(BukkitAdapter.adapt(sender.getLocation()), GenerationPhase.POPULATE);
BiomeProvider grid = getMain().getWorld(BukkitAdapter.adapt(sender.getWorld())).getBiomeProvider();
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(BukkitAdapter.adapt(sender.getLocation()));
LangUtil.send("command.biome.in", BukkitAdapter.adapt(sender), biome.getID());
return true;
}

View File

@@ -48,7 +48,7 @@ public class BiomeLocateCommand extends WorldCommand {
LangUtil.send("command.biome.invalid", BukkitAdapter.adapt(sender), id);
return true;
}
Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncBiomeFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getGrid(), b, BukkitAdapter.adapt(sender.getLocation().clone().multiply((1D / ((TerraBukkitPlugin) getMain()).getTerraConfig().getBiomeSearchResolution()))), 0, maxRadius, location -> {
Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncBiomeFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getBiomeProvider(), b, BukkitAdapter.adapt(sender.getLocation().clone().multiply((1D / ((TerraBukkitPlugin) getMain()).getTerraConfig().getBiomeSearchResolution()))), 0, maxRadius, location -> {
if(location != null) {
ComponentBuilder cm = new ComponentBuilder(String.format("The nearest %s is at ", id.toLowerCase()))
.append(String.format("[%d, ~, %d]", location.getBlockX(), location.getBlockZ()), ComponentBuilder.FormatRetention.NONE)

View File

@@ -1,47 +0,0 @@
package com.dfsek.terra.bukkit.command.command.image;
import com.dfsek.terra.bukkit.BukkitCommandSender;
import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.bukkit.command.command.image.gui.GUICommand;
import com.dfsek.terra.config.lang.LangUtil;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class ImageCommand extends WorldCommand {
public ImageCommand(com.dfsek.terra.bukkit.command.Command parent) {
super(parent);
}
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) {
LangUtil.send("command.image.main-menu", new BukkitCommandSender(sender));
return true;
}
@Override
public String getName() {
return "image";
}
@Override
public List<com.dfsek.terra.bukkit.command.Command> getSubCommands() {
return Arrays.asList(new RenderCommand(this), new GUICommand(this));
}
@Override
public int arguments() {
return 1;
}
@Override
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
return Collections.emptyList();
}
}

View File

@@ -1,61 +0,0 @@
package com.dfsek.terra.bukkit.command.command.image;
import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.config.lang.LangUtil;
import com.dfsek.terra.image.WorldImageGenerator;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.Collections;
import java.util.List;
public class RenderCommand extends WorldCommand {
public RenderCommand(com.dfsek.terra.bukkit.command.Command parent) {
super(parent);
}
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
try {
WorldImageGenerator g = new WorldImageGenerator(BukkitAdapter.adapt(world), Integer.parseInt(args[0]), Integer.parseInt(args[1]), getMain());
g.drawWorld(sender.getLocation().getBlockX(), sender.getLocation().getBlockZ());
File file = new File(getMain().getDataFolder() + File.separator + "export" + File.separator + "map" + File.separator + "map_" + System.currentTimeMillis() + ".png");
//noinspection ResultOfMethodCallIgnored
file.mkdirs();
//noinspection ResultOfMethodCallIgnored
file.createNewFile();
g.save(file);
LangUtil.send("command.image.render.save", BukkitAdapter.adapt(sender), file.getAbsolutePath());
return true;
} catch(Exception e) {
e.printStackTrace();
LangUtil.send("command.image.render.error", BukkitAdapter.adapt(sender));
return true;
}
}
@Override
public String getName() {
return "render";
}
@Override
public List<com.dfsek.terra.bukkit.command.Command> getSubCommands() {
return Collections.emptyList();
}
@Override
public int arguments() {
return 2;
}
@Override
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
return Collections.emptyList();
}
}

View File

@@ -1,47 +0,0 @@
package com.dfsek.terra.bukkit.command.command.image.gui;
import com.dfsek.terra.bukkit.BukkitCommandSender;
import com.dfsek.terra.bukkit.command.DebugCommand;
import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.config.lang.LangUtil;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class GUICommand extends WorldCommand implements DebugCommand {
public GUICommand(com.dfsek.terra.bukkit.command.Command parent) {
super(parent);
}
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
LangUtil.send("command.image.gui.main-menu", new BukkitCommandSender(sender));
return true;
}
@Override
public String getName() {
return "gui";
}
@Override
public List<com.dfsek.terra.bukkit.command.Command> getSubCommands() {
return Arrays.asList(new StepGUICommand(this), new RawGUICommand(this));
}
@Override
public int arguments() {
return 1;
}
@Override
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
return Collections.emptyList();
}
}

View File

@@ -1,48 +0,0 @@
package com.dfsek.terra.bukkit.command.command.image.gui;
import com.dfsek.terra.bukkit.command.DebugCommand;
import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.image.ImageLoader;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
public class RawGUICommand extends WorldCommand implements DebugCommand {
public RawGUICommand(com.dfsek.terra.bukkit.command.Command parent) {
super(parent);
}
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
ImageLoader loader = getMain().getWorld(BukkitAdapter.adapt(world)).getConfig().getTemplate().getImageLoader();
if(loader != null) loader.debug(false, BukkitAdapter.adapt(sender.getWorld()), getMain());
else ImageLoader.debugWorld(false, BukkitAdapter.adapt(world), getMain());
return true;
}
@Override
public String getName() {
return "raw";
}
@Override
public List<com.dfsek.terra.bukkit.command.Command> getSubCommands() {
return Collections.emptyList();
}
@Override
public int arguments() {
return 0;
}
@Override
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
return Collections.emptyList();
}
}

View File

@@ -1,48 +0,0 @@
package com.dfsek.terra.bukkit.command.command.image.gui;
import com.dfsek.terra.bukkit.command.DebugCommand;
import com.dfsek.terra.bukkit.command.WorldCommand;
import com.dfsek.terra.bukkit.world.BukkitAdapter;
import com.dfsek.terra.image.ImageLoader;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
public class StepGUICommand extends WorldCommand implements DebugCommand {
public StepGUICommand(com.dfsek.terra.bukkit.command.Command parent) {
super(parent);
}
@Override
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World world) {
ImageLoader loader = (getMain()).getWorld(BukkitAdapter.adapt(world)).getConfig().getTemplate().getImageLoader();
if(loader != null) loader.debug(true, BukkitAdapter.adapt(sender.getWorld()), getMain());
else ImageLoader.debugWorld(true, BukkitAdapter.adapt(world), getMain());
return true;
}
@Override
public String getName() {
return "step";
}
@Override
public List<com.dfsek.terra.bukkit.command.Command> getSubCommands() {
return Collections.emptyList();
}
@Override
public int arguments() {
return 0;
}
@Override
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
return Collections.emptyList();
}
}

View File

@@ -51,7 +51,7 @@ public class LocateCommand extends WorldCommand {
LangUtil.send("command.structure.invalid", BukkitAdapter.adapt(sender), id);
return true;
}
Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncStructureFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getGrid(), s, BukkitAdapter.adapt(sender.getLocation()), 0, maxRadius, (location) -> {
Bukkit.getScheduler().runTaskAsynchronously((TerraBukkitPlugin) getMain(), new AsyncStructureFinder(getMain().getWorld(BukkitAdapter.adapt(world)).getBiomeProvider(), s, BukkitAdapter.adapt(sender.getLocation()), 0, maxRadius, (location) -> {
if(sender.isOnline()) {
if(location != null) {
ComponentBuilder cm = new ComponentBuilder(String.format("The nearest %s is at ", id.toLowerCase()))

View File

@@ -41,7 +41,7 @@ public class SpigotListener implements Listener {
TerraStructure config = tw.getConfig().getStructure(tw.getConfig().getTemplate().getLocatable().get("STRONGHOLD"));
if(config != null) {
Debug.info("Overriding Ender Signal...");
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getGrid(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> {
AsyncStructureFinder finder = new AsyncStructureFinder(tw.getBiomeProvider(), config, BukkitAdapter.adapt(e.getLocation()), 0, 500, location -> {
if(location != null)
signal.setTargetLocation(BukkitAdapter.adapt(location.toLocation(BukkitAdapter.adapt(signal.getWorld()))));
Debug.info("Location: " + location);

View File

@@ -1,8 +1,7 @@
package com.dfsek.terra.fabric.world;
import com.dfsek.terra.api.world.generation.GenerationPhase;
import com.dfsek.terra.biome.BiomeProvider;
import com.dfsek.terra.biome.UserDefinedBiome;
import com.dfsek.terra.biome.grid.master.TerraBiomeGrid;
import com.dfsek.terra.config.base.ConfigPack;
import com.dfsek.terra.fabric.TerraFabricPlugin;
import com.mojang.serialization.Codec;
@@ -28,14 +27,14 @@ public class TerraBiomeSource extends BiomeSource {
private final Registry<Biome> biomeRegistry;
private final long seed;
private final TerraBiomeGrid grid;
private final BiomeProvider grid;
private final ConfigPack pack;
public TerraBiomeSource(Registry<Biome> biomes, long seed, ConfigPack pack) {
super(biomes.stream().collect(Collectors.toList()));
this.biomeRegistry = biomes;
this.seed = seed;
this.grid = new TerraBiomeGrid.TerraBiomeGridBuilder(seed, pack, TerraFabricPlugin.getInstance()).build();
this.grid = pack.getTemplate().getProviderBuilder().build(seed);
this.pack = pack;
}
@@ -51,7 +50,7 @@ public class TerraBiomeSource extends BiomeSource {
@Override
public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) {
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX * 4, biomeZ * 4, GenerationPhase.BASE);
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(biomeX * 4, biomeZ * 4);
return biomeRegistry.get(new Identifier("terra", TerraFabricPlugin.createBiomeID(pack, biome)));
}