mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-06-14 04:41:13 +00:00
implementation of BiomePipeline
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user