mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-12 18:56:04 +00:00
Merge pull request #50 from PolyhedralDev/palette
Noise config additions
This commit is contained in:
@@ -4,6 +4,7 @@ import com.dfsek.tectonic.loading.TypeRegistry;
|
||||
import com.dfsek.terra.api.math.GridSpawn;
|
||||
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;
|
||||
@@ -48,16 +49,17 @@ public class GenericLoaders implements LoaderRegistrar {
|
||||
.registerLoader(PaletteHolder.class, new PaletteHolderLoader())
|
||||
.registerLoader(PaletteLayer.class, new PaletteLayerLoader())
|
||||
.registerLoader(FloraLayer.class, new FloraLayerLoader())
|
||||
.registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf((String) o))
|
||||
.registerLoader(Ore.Type.class, (t, o, l) -> Ore.Type.valueOf(o.toString()))
|
||||
.registerLoader(OreConfig.class, new OreConfigLoader())
|
||||
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
|
||||
.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((String) o))
|
||||
.registerLoader(ImageLoader.Channel.class, (t, o, l) -> ImageLoader.Channel.valueOf((String) o))
|
||||
.registerLoader(ImageLoader.Align.class, (t, o, l) -> ImageLoader.Align.valueOf((String) o))
|
||||
.registerLoader(TerraFlora.Search.class, (t, o, l) -> TerraFlora.Search.valueOf((String) o));
|
||||
.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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package com.dfsek.terra.api.math;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
import com.dfsek.terra.api.world.biome.NormalizationUtil;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ProbabilityCollection<E> {
|
||||
@@ -25,19 +24,29 @@ public class ProbabilityCollection<E> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public E get() {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[ThreadLocalRandom.current().nextInt(array.length)];
|
||||
}
|
||||
|
||||
public E get(Random r) {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[r.nextInt(array.length)];
|
||||
}
|
||||
|
||||
private static double getNoise(double x, double y, double z, NoiseSampler sampler) {
|
||||
double n = sampler.getNoise(x, y, z);
|
||||
return FastMath.min(FastMath.max(n, -1), 1);
|
||||
}
|
||||
|
||||
private static double getNoise(double x, double z, NoiseSampler sampler) {
|
||||
double n = sampler.getNoise(x, z);
|
||||
return FastMath.min(FastMath.max(n, -1), 1);
|
||||
}
|
||||
|
||||
public E get(NoiseSampler n, double x, double y, double z) {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[FastMath.min(FastMath.floorToInt(((getNoise(x, y, z, n) + 1D) / 2D) * array.length), array.length - 1)];
|
||||
}
|
||||
|
||||
public E get(NoiseSampler n, double x, double z) {
|
||||
if(array.length == 0) return null;
|
||||
return (E) array[NormalizationUtil.normalize(n.getNoise(x, z), array.length, 1)];
|
||||
return (E) array[FastMath.min(FastMath.floorToInt(((getNoise(x, z, n) + 1D) / 2D) * array.length), array.length - 1)];
|
||||
}
|
||||
|
||||
public int getTotalProbability() {
|
||||
|
||||
@@ -278,6 +278,7 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
private static final int PRIME_Y = 1136930381;
|
||||
private static final int PRIME_Z = 1720413743;
|
||||
private static final NoiseSampler CELLULAR_LOOKUP_DEFAULT = new FastNoiseLite();
|
||||
private static final long POSITIVE_POW1 = 0b01111111111L << 52; // Bits that when applied to the exponent/sign section of a double, produce a positive number with a power of 1.
|
||||
private int mSeed = 1337;
|
||||
private double mFrequency = 0.01f;
|
||||
private NoiseType mNoiseType = NoiseType.OpenSimplex2;
|
||||
@@ -288,7 +289,7 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
private double mLacunarity = 2.0f;
|
||||
private double mGain = 0.5f;
|
||||
private double mWeightedStrength = 0.0f;
|
||||
private double mPingPongStength = 2.0f;
|
||||
private double mPingPongStrength = 2.0f;
|
||||
private double mFractalBounding = 1 / 1.75f;
|
||||
private CellularDistanceFunction mCellularDistanceFunction = CellularDistanceFunction.EuclideanSq;
|
||||
private CellularReturnType mCellularReturnType = CellularReturnType.Distance;
|
||||
@@ -569,7 +570,7 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
* Default: 2.0
|
||||
*/
|
||||
public void setFractalPingPongStrength(double pingPongStrength) {
|
||||
mPingPongStength = pingPongStrength;
|
||||
mPingPongStrength = pingPongStrength;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -886,7 +887,7 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
double amp = mFractalBounding;
|
||||
|
||||
for(int i = 0; i < mOctaves; i++) {
|
||||
double noise = pingPong((genNoiseSingle(seed++, x, y) + 1) * mPingPongStength);
|
||||
double noise = pingPong((genNoiseSingle(seed++, x, y) + 1) * mPingPongStrength);
|
||||
sum += (noise - 0.5f) * 2 * amp;
|
||||
amp *= lerp(1.0f, noise, mWeightedStrength);
|
||||
|
||||
@@ -905,7 +906,7 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
double amp = mFractalBounding;
|
||||
|
||||
for(int i = 0; i < mOctaves; i++) {
|
||||
double noise = pingPong((genNoiseSingle(seed++, x, y, z) + 1) * mPingPongStength);
|
||||
double noise = pingPong((genNoiseSingle(seed++, x, y, z) + 1) * mPingPongStrength);
|
||||
sum += (noise - 0.5f) * 2 * amp;
|
||||
amp *= lerp(1.0f, noise, mWeightedStrength);
|
||||
|
||||
@@ -1615,25 +1616,32 @@ public class FastNoiseLite implements NoiseSampler {
|
||||
return lerp(xf0, xf1, ys) * 1.4247691104677813f;
|
||||
}
|
||||
|
||||
private int doubleCast2Int(double f) {
|
||||
int i = Float.floatToRawIntBits((float) f);
|
||||
|
||||
return i ^ (i >> 16);
|
||||
private static long hash(long in) {
|
||||
in = (in + 0x7ed55d16) + (in << 12);
|
||||
in = (in ^ 0xc761c23c) ^ (in >> 19);
|
||||
in = (in + 0x165667b1) + (in << 5);
|
||||
in = (in + 0xd3a2646c) ^ (in << 9);
|
||||
in = (in + 0xfd7046c5) + (in << 3);
|
||||
in = (in ^ 0xb55a4f09) ^ (in >> 16);
|
||||
return in;
|
||||
}
|
||||
|
||||
private double singleWhiteNoise(int seed, double x, double y, double z) {
|
||||
int xi = doubleCast2Int(x);
|
||||
int yi = doubleCast2Int(y);
|
||||
int zi = doubleCast2Int(z);
|
||||
|
||||
return valCoord(seed, xi, yi, zi);
|
||||
long hashX = hash(Double.doubleToRawLongBits(x) ^ seed);
|
||||
long hashZ = hash(Double.doubleToRawLongBits(y) ^ seed);
|
||||
long hash = (((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed) + Double.doubleToRawLongBits(z);
|
||||
long base = ((hash(hash)) & 0x000fffffffffffffL)
|
||||
+ POSITIVE_POW1; // Sign and exponent
|
||||
return (Double.longBitsToDouble(base) - 1.5) * 2;
|
||||
}
|
||||
|
||||
private double singleWhiteNoise(int seed, double x, double y) {
|
||||
int xi = doubleCast2Int(x);
|
||||
int yi = doubleCast2Int(y);
|
||||
|
||||
return valCoord(seed, xi, yi);
|
||||
long hashX = hash(Double.doubleToRawLongBits(x) ^ seed);
|
||||
long hashZ = hash(Double.doubleToRawLongBits(y) ^ seed);
|
||||
long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed;
|
||||
long base = (hash(hash) & 0x000fffffffffffffL)
|
||||
+ POSITIVE_POW1; // Sign and exponent
|
||||
return (Double.longBitsToDouble(base) - 1.5) * 2;
|
||||
}
|
||||
|
||||
// Simplex/OpenSimplex2 Noise
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.dfsek.terra.api.math.noise.samplers;
|
||||
|
||||
public class LinearNormalizer extends Normalizer {
|
||||
private final double min;
|
||||
private final double max;
|
||||
|
||||
public LinearNormalizer(NoiseSampler sampler, double min, double max) {
|
||||
super(sampler);
|
||||
this.min = min;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double normalize(double in) {
|
||||
return (in - min) * (2 / (max - min)) - 1;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package com.dfsek.terra.api.math.noise.samplers;
|
||||
public abstract class Normalizer implements NoiseSampler {
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
protected Normalizer(NoiseSampler sampler) {
|
||||
public Normalizer(NoiseSampler sampler) {
|
||||
this.sampler = sampler;
|
||||
}
|
||||
|
||||
@@ -18,4 +18,8 @@ public abstract class Normalizer implements NoiseSampler {
|
||||
public double getNoise(double x, double y, double z) {
|
||||
return normalize(sampler.getNoise(x, y, z));
|
||||
}
|
||||
|
||||
public enum NormalType {
|
||||
LINEAR, NONE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,20 @@ import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SimplexPalette<E> extends Palette<E> {
|
||||
public class NoisePalette<E> extends Palette<E> {
|
||||
private final NoiseSampler r;
|
||||
private final boolean is2D;
|
||||
|
||||
public SimplexPalette(NoiseSampler r) {
|
||||
public NoisePalette(NoiseSampler r, boolean is2D) {
|
||||
this.r = r;
|
||||
this.is2D = is2D;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int layer, int x, int z) {
|
||||
if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r, x, z);
|
||||
public E get(int layer, double x, double y, double z) {
|
||||
if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r, x, y, z, is2D);
|
||||
List<PaletteLayer<E>> pl = getLayers();
|
||||
if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r, x, z);
|
||||
return pl.get(layer).get(r, x, z);
|
||||
if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r, x, y, z, is2D);
|
||||
return pl.get(layer).get(r, x, y, z, is2D);
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public abstract class Palette<E> {
|
||||
* @param layer - The layer at which to fetch the material.
|
||||
* @return BlockData - The material fetched.
|
||||
*/
|
||||
public abstract E get(int layer, int x, int z);
|
||||
public abstract E get(int layer, double x, double y, double z);
|
||||
|
||||
|
||||
public int getSize() {
|
||||
@@ -104,8 +104,9 @@ public abstract class Palette<E> {
|
||||
return m;
|
||||
}
|
||||
|
||||
public E get(NoiseSampler random, int x, int z) {
|
||||
if(col) return this.collection.get(random, x, z);
|
||||
public E get(NoiseSampler random, double x, double y, double z, boolean is2D) {
|
||||
if(col && is2D) return this.collection.get(random, x, z);
|
||||
else if(col) return this.collection.get(random, x, y, z);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public class RandomPalette<E> extends Palette<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int layer, int x, int z) {
|
||||
public E get(int layer, double x, double y, double z) {
|
||||
if(layer > this.getSize()) return this.getLayers().get(this.getLayers().size() - 1).get(r);
|
||||
List<PaletteLayer<E>> pl = getLayers();
|
||||
if(layer >= pl.size()) return pl.get(pl.size() - 1).get(r);
|
||||
|
||||
@@ -15,28 +15,28 @@ public class TreeGeometry {
|
||||
}
|
||||
|
||||
public static Vector3 getPerpendicular(Vector3 v) {
|
||||
return v.getZ() < v.getX() ? new Vector3(v.getY(), - v.getX(), 0) : new Vector3(0, - v.getZ(), v.getY());
|
||||
return v.getZ() < v.getX() ? new Vector3(v.getY(), -v.getX(), 0) : new Vector3(0, -v.getZ(), v.getY());
|
||||
}
|
||||
|
||||
public FractalTree getTree() {
|
||||
return tree;
|
||||
}
|
||||
|
||||
public void generateSphere(Location l, BlockData m, int radius, boolean overwrite) {
|
||||
generateSphere(l, new ProbabilityCollection<BlockData>().add(m, 1), radius, overwrite);
|
||||
public void generateSphere(Location l, BlockData m, int radius, boolean overwrite, Random r) {
|
||||
generateSphere(l, new ProbabilityCollection<BlockData>().add(m, 1), radius, overwrite, r);
|
||||
}
|
||||
|
||||
public void generateCylinder(Location l, BlockData m, int radius, int height, boolean overwrite) {
|
||||
generateCylinder(l, new ProbabilityCollection<BlockData>().add(m, 1), radius, height, overwrite);
|
||||
public void generateCylinder(Location l, BlockData m, int radius, int height, boolean overwrite, Random r) {
|
||||
generateCylinder(l, new ProbabilityCollection<BlockData>().add(m, 1), radius, height, overwrite, r);
|
||||
}
|
||||
|
||||
public void generateSphere(Location l, ProbabilityCollection<BlockData> m, int radius, boolean overwrite) {
|
||||
for(int x = - radius; x <= radius; x++) {
|
||||
for(int y = - radius; y <= radius; y++) {
|
||||
for(int z = - radius; z <= radius; z++) {
|
||||
public void generateSphere(Location l, ProbabilityCollection<BlockData> m, int radius, boolean overwrite, Random r) {
|
||||
for(int x = -radius; x <= radius; x++) {
|
||||
for(int y = -radius; y <= radius; y++) {
|
||||
for(int z = -radius; z <= radius; z++) {
|
||||
Vector3 position = l.toVector().clone().add(new Vector3(x, y, z));
|
||||
if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty()))
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get());
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,19 +48,19 @@ public class TreeGeometry {
|
||||
for(int z = -radius; z <= radius; z++) {
|
||||
Vector3 position = l.toVector().clone().add(new Vector3(x, y, z));
|
||||
if(r.nextInt(100) < sponginess && l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty()))
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get());
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateCylinder(Location l, ProbabilityCollection<BlockData> m, int radius, int height, boolean overwrite) {
|
||||
for(int x = - radius; x <= radius; x++) {
|
||||
public void generateCylinder(Location l, ProbabilityCollection<BlockData> m, int radius, int height, boolean overwrite, Random r) {
|
||||
for(int x = -radius; x <= radius; x++) {
|
||||
for(int y = 0; y <= height; y++) {
|
||||
for(int z = - radius; z <= radius; z++) {
|
||||
for(int z = -radius; z <= radius; z++) {
|
||||
Vector3 position = l.toVector().clone().add(new Vector3(x, 0, z));
|
||||
if(l.toVector().distance(position) <= radius + 0.5 && (overwrite || position.toLocation(l.getWorld()).getBlock().isEmpty()))
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get());
|
||||
tree.setBlock(position.toLocation(l.getWorld()), m.get(r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,13 +41,13 @@ public class OakTree extends FractalTree {
|
||||
BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:oak_wood");
|
||||
BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:oak_leave");
|
||||
if(recursions > 1) {
|
||||
geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false);
|
||||
geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false, r);
|
||||
if(recursions > 2) return;
|
||||
}
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, FastMath.max((int) d1, 0), true);
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, FastMath.max((int) d1, 0), true, r);
|
||||
}
|
||||
double runningAngle = (double) 45 / (recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.75).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
|
||||
|
||||
@@ -50,13 +50,13 @@ public class ShatteredTree extends FractalTree {
|
||||
|
||||
private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) {
|
||||
if(recursions > 2) {
|
||||
geo.generateSphere(l1, leaves, 1 + r.nextInt(2), false);
|
||||
geo.generateSphere(l1, leaves, 1 + r.nextInt(2), false, r);
|
||||
return;
|
||||
}
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true);
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true, r);
|
||||
}
|
||||
double runningAngle = (double) 45 / (recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.9).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
|
||||
|
||||
@@ -50,13 +50,13 @@ public class SmallShatteredTree extends FractalTree {
|
||||
|
||||
private void growBranch(Location l1, Vector3 diff, double d1, int recursions, Random r) {
|
||||
if(recursions > 2) {
|
||||
geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false);
|
||||
geo.generateSphere(l1, leaves, 1 + r.nextInt(2) + (3 - recursions), false, r);
|
||||
return;
|
||||
}
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true);
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), bark, FastMath.max((int) d1, 0), true, r);
|
||||
}
|
||||
double runningAngle = (double) 45 / (recursions + 1);
|
||||
growBranch(l1.clone().add(diff), diff.clone().multiply(0.7).rotateAroundX(FastMath.toRadians(runningAngle + getNoise(r))).rotateAroundZ(FastMath.toRadians(getNoise(r))),
|
||||
|
||||
@@ -33,19 +33,19 @@ public class SpruceTree extends FractalTree {
|
||||
*/
|
||||
@Override
|
||||
public void grow(Location origin, Random random) {
|
||||
growTrunk(origin.clone(), new Vector3(0, 16 + random.nextInt(5), 0));
|
||||
growTrunk(origin.clone(), new Vector3(0, 16 + random.nextInt(5), 0), random);
|
||||
}
|
||||
|
||||
private void growTrunk(Location l1, Vector3 diff) {
|
||||
private void growTrunk(Location l1, Vector3 diff, Random r) {
|
||||
if(diff.getY() < 0) diff.rotateAroundAxis(TreeGeometry.getPerpendicular(diff.clone()).normalize(), FastMath.PI);
|
||||
int d = (int) diff.length();
|
||||
int rad = 7;
|
||||
BlockData wood = getMain().getWorldHandle().createBlockData("minecraft:spruce_wood");
|
||||
BlockData leaves = getMain().getWorldHandle().createBlockData("minecraft:spruce_leave");
|
||||
for(int i = 0; i < d; i++) {
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, (int) ((i > d * 0.65) ? 0.5 : 1.5), true);
|
||||
geo.generateSphere(l1.clone().add(diff.clone().multiply((double) i / d)), wood, (int) ((i > d * 0.65) ? 0.5 : 1.5), true, r);
|
||||
if(i > 3)
|
||||
geo.generateCylinder(l1.clone().add(diff.clone().multiply((double) i / d)), leaves, (int) (((6 - (i % 4))) * (1.25 - ((double) i / d))), 1, false);
|
||||
geo.generateCylinder(l1.clone().add(diff.clone().multiply((double) i / d)), leaves, (int) (((6 - (i % 4))) * (1.25 - ((double) i / d))), 1, false, r);
|
||||
}
|
||||
setBlock(l1.clone().add(diff), leaves);
|
||||
setBlock(l1.clone().add(diff).add(0, 1, 0), leaves);
|
||||
|
||||
@@ -10,7 +10,7 @@ public class SinglePalette<E> extends Palette<E> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public E get(int i, int i1, int i2) {
|
||||
public E get(int layer, double x, double y, double z) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,25 +1,16 @@
|
||||
package com.dfsek.terra.config.factories;
|
||||
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.platform.TerraPlugin;
|
||||
import com.dfsek.terra.api.platform.block.BlockData;
|
||||
import com.dfsek.terra.api.util.FastRandom;
|
||||
import com.dfsek.terra.api.world.palette.NoisePalette;
|
||||
import com.dfsek.terra.api.world.palette.Palette;
|
||||
import com.dfsek.terra.api.world.palette.RandomPalette;
|
||||
import com.dfsek.terra.api.world.palette.SimplexPalette;
|
||||
import com.dfsek.terra.biome.palette.PaletteLayer;
|
||||
import com.dfsek.terra.config.templates.PaletteTemplate;
|
||||
|
||||
public class PaletteFactory implements TerraFactory<PaletteTemplate, Palette<BlockData>> {
|
||||
@Override
|
||||
public Palette<BlockData> build(PaletteTemplate config, TerraPlugin main) {
|
||||
Palette<BlockData> palette;
|
||||
if(config.isSimplex()) {
|
||||
FastNoiseLite noise = new FastNoiseLite((int) config.getSeed());
|
||||
noise.setFrequency(config.getFrequency());
|
||||
palette = new SimplexPalette<>(noise);
|
||||
} else palette = new RandomPalette<>(new FastRandom(config.getSeed()));
|
||||
|
||||
Palette<BlockData> palette = new NoisePalette<>(config.getNoise().build(2403), config.getNoise().getDimensions() == 2);
|
||||
for(PaletteLayer layer : config.getPalette()) {
|
||||
palette.add(layer.getLayer(), layer.getSize());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.config.loaders.config;
|
||||
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
@@ -8,6 +9,7 @@ import com.dfsek.terra.api.math.Range;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.world.flora.Flora;
|
||||
import com.dfsek.terra.config.loaders.Types;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import com.dfsek.terra.population.items.flora.FloraLayer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -23,12 +25,19 @@ public class FloraLayerLoader implements TypeLoader<FloraLayer> {
|
||||
if(range == null) throw new LoadException("Flora range unspecified");
|
||||
ProbabilityCollection<Flora> items = (ProbabilityCollection<Flora>) configLoader.loadType(Types.FLORA_PROBABILITY_COLLECTION_TYPE, map.get("items"));
|
||||
|
||||
if(map.containsKey("simplex-frequency")) {
|
||||
FastNoiseLite noiseLite = new FastNoiseLite();
|
||||
noiseLite.setFrequency((Double) map.get("simplex-frequency"));
|
||||
return new FloraLayer(density, range, items, noiseLite);
|
||||
NoiseBuilder sampler;
|
||||
if(map.containsKey("distribution")) {
|
||||
try {
|
||||
sampler = new NoiseBuilderLoader().load(NoiseBuilder.class, map.get("distribution"), configLoader);
|
||||
} catch(ConfigException e) {
|
||||
throw new LoadException("Unable to load noise", e);
|
||||
}
|
||||
return new FloraLayer(density, range, items, sampler.build(2403));
|
||||
}
|
||||
sampler = new NoiseBuilder();
|
||||
sampler.setType(FastNoiseLite.NoiseType.WhiteNoise);
|
||||
sampler.setDimensions(3);
|
||||
|
||||
return new FloraLayer(density, range, items, null);
|
||||
return new FloraLayer(density, range, items, sampler.build(2403));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -16,12 +17,14 @@ public class NoiseBuilderLoader implements TypeLoader<NoiseBuilder> {
|
||||
private static final ConfigLoader LOADER = new ConfigLoader();
|
||||
|
||||
static {
|
||||
LOADER.registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object));
|
||||
LOADER.registerLoader(FastNoiseLite.FractalType.class, (t, object, cf) -> FastNoiseLite.FractalType.valueOf((String) object));
|
||||
LOADER.registerLoader(FastNoiseLite.DomainWarpType.class, (t, object, cf) -> FastNoiseLite.DomainWarpType.valueOf((String) object));
|
||||
LOADER.registerLoader(FastNoiseLite.RotationType3D.class, (t, object, cf) -> FastNoiseLite.RotationType3D.valueOf((String) object));
|
||||
LOADER.registerLoader(FastNoiseLite.CellularReturnType.class, (t, object, cf) -> FastNoiseLite.CellularReturnType.valueOf((String) object));
|
||||
LOADER.registerLoader(FastNoiseLite.CellularDistanceFunction.class, (t, object, cf) -> FastNoiseLite.CellularDistanceFunction.valueOf((String) object));
|
||||
LOADER.registerLoader(FastNoiseLite.NoiseType.class, (t, object, cf) -> FastNoiseLite.NoiseType.valueOf((String) object))
|
||||
.registerLoader(FastNoiseLite.FractalType.class, (t, object, cf) -> FastNoiseLite.FractalType.valueOf((String) object))
|
||||
.registerLoader(FastNoiseLite.DomainWarpType.class, (t, object, cf) -> FastNoiseLite.DomainWarpType.valueOf((String) object))
|
||||
.registerLoader(FastNoiseLite.RotationType3D.class, (t, object, cf) -> FastNoiseLite.RotationType3D.valueOf((String) object))
|
||||
.registerLoader(FastNoiseLite.CellularReturnType.class, (t, object, cf) -> FastNoiseLite.CellularReturnType.valueOf((String) object))
|
||||
.registerLoader(FastNoiseLite.CellularDistanceFunction.class, (t, object, cf) -> FastNoiseLite.CellularDistanceFunction.valueOf((String) object))
|
||||
.registerLoader(NoiseBuilder.class, new NoiseBuilderLoader())
|
||||
.registerLoader(Normalizer.NormalType.class, (t, o, l) -> Normalizer.NormalType.valueOf(o.toString().toUpperCase()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.dfsek.terra.config.loaders.config;
|
||||
|
||||
import com.dfsek.tectonic.config.Configuration;
|
||||
import com.dfsek.tectonic.exception.ConfigException;
|
||||
import com.dfsek.tectonic.exception.LoadException;
|
||||
import com.dfsek.tectonic.loading.ConfigLoader;
|
||||
import com.dfsek.tectonic.loading.TypeLoader;
|
||||
@@ -8,6 +10,7 @@ import com.dfsek.terra.api.math.Range;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.world.tree.Tree;
|
||||
import com.dfsek.terra.config.loaders.Types;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import com.dfsek.terra.population.items.tree.TreeLayer;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
@@ -15,10 +18,6 @@ import java.util.Map;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class TreeLayerLoader implements TypeLoader<TreeLayer> {
|
||||
|
||||
public TreeLayerLoader() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public TreeLayer load(Type type, Object o, ConfigLoader configLoader) throws LoadException {
|
||||
Map<String, Object> map = (Map<String, Object>) o;
|
||||
@@ -27,12 +26,19 @@ public class TreeLayerLoader implements TypeLoader<TreeLayer> {
|
||||
if(range == null) throw new LoadException("Tree range unspecified");
|
||||
ProbabilityCollection<Tree> items = (ProbabilityCollection<Tree>) configLoader.loadType(Types.TREE_PROBABILITY_COLLECTION_TYPE, map.get("items"));
|
||||
|
||||
if(map.containsKey("simplex-frequency")) {
|
||||
FastNoiseLite noiseLite = new FastNoiseLite();
|
||||
noiseLite.setFrequency((Double) map.get("simplex-frequency"));
|
||||
return new TreeLayer(density, range, items, noiseLite);
|
||||
NoiseBuilder sampler = new NoiseBuilder();
|
||||
if(map.containsKey("distribution")) {
|
||||
try {
|
||||
configLoader.load(sampler, new Configuration((Map<String, Object>) map.get("distribution")));
|
||||
} catch(ConfigException e) {
|
||||
throw new LoadException("Unable to load noise", e);
|
||||
}
|
||||
return new TreeLayer(density, range, items, sampler.build(2403));
|
||||
}
|
||||
|
||||
return new TreeLayer(density, range, items, null);
|
||||
sampler.setType(FastNoiseLite.NoiseType.WhiteNoise);
|
||||
sampler.setDimensions(3);
|
||||
|
||||
return new TreeLayer(density, range, items, sampler.build(2403));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,12 +3,19 @@ package com.dfsek.terra.config.templates;
|
||||
import com.dfsek.tectonic.annotations.Abstractable;
|
||||
import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.biome.palette.PaletteLayer;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"FieldMayBeFinal", "unused"})
|
||||
public class PaletteTemplate extends AbstractableTemplate {
|
||||
@Value("noise")
|
||||
@Abstractable
|
||||
@Default
|
||||
private NoiseBuilder noise = new NoiseBuilder();
|
||||
|
||||
@Value("id")
|
||||
private String id;
|
||||
|
||||
@@ -16,38 +23,20 @@ public class PaletteTemplate extends AbstractableTemplate {
|
||||
@Abstractable
|
||||
private List<PaletteLayer> palette;
|
||||
|
||||
@Value("simplex")
|
||||
@Abstractable
|
||||
@Default
|
||||
private boolean simplex = false;
|
||||
|
||||
@Value("frequency")
|
||||
@Abstractable
|
||||
@Default
|
||||
private double frequency = 0.02D;
|
||||
|
||||
@Value("seed")
|
||||
@Abstractable
|
||||
@Default
|
||||
private long seed = 0;
|
||||
public PaletteTemplate() {
|
||||
noise.setType(FastNoiseLite.NoiseType.WhiteNoise);
|
||||
noise.setDimensions(3);
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public double getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public long getSeed() {
|
||||
return seed;
|
||||
}
|
||||
|
||||
public List<PaletteLayer> getPalette() {
|
||||
return palette;
|
||||
}
|
||||
|
||||
public boolean isSimplex() {
|
||||
return simplex;
|
||||
public NoiseBuilder getNoise() {
|
||||
return noise;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
for(int y = world.getMaxHeight() - 1; y >= 0; y--) {
|
||||
if(sampler.sample(x, y, z) > 0) {
|
||||
justSet = true;
|
||||
data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, cz);
|
||||
data = PaletteUtil.getPalette(x, y, z, c, sampler).get(paletteLevel, cx, y, cz);
|
||||
chunk.setBlock(x, y, z, data);
|
||||
if(paletteLevel == 0 && c.doSlabs() && y < 255) {
|
||||
prepareBlockPartFloor(data, chunk.getBlockData(x, y + 1, z), chunk, new Vector3(x, y + 1, z), c.getSlabPalettes(),
|
||||
@@ -122,7 +122,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
}
|
||||
paletteLevel++;
|
||||
} else if(y <= sea) {
|
||||
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, z + zOrig));
|
||||
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig));
|
||||
if(justSet && c.doSlabs()) {
|
||||
prepareBlockPartCeiling(data, chunk.getBlockData(x, y, z), chunk, new Vector3(x, y, z), c.getSlabPalettes(), c.getStairPalettes(), c.getSlabThreshold(), sampler);
|
||||
}
|
||||
@@ -144,18 +144,18 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
|
||||
private void prepareBlockPartFloor(BlockData down, BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, Map<MaterialData, Palette<BlockData>> slabs,
|
||||
Map<MaterialData, Palette<BlockData>> stairs, double thresh, Sampler sampler) {
|
||||
if(sampler.sample(block.getBlockX(), block.getBlockY() - 0.4, block.getBlockZ()) > thresh) {
|
||||
if(sampler.sample(block.getX(), block.getY() - 0.4, block.getZ()) > thresh) {
|
||||
if(stairs != null) {
|
||||
Palette<BlockData> stairPalette = stairs.get(down.getMaterial());
|
||||
if(stairPalette != null) {
|
||||
BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone();
|
||||
BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone();
|
||||
if(stair instanceof Stairs) {
|
||||
Stairs stairNew = (Stairs) stair;
|
||||
if(placeStair(orig, chunk, block, thresh, sampler, stairNew)) return; // Successfully placed part.
|
||||
}
|
||||
}
|
||||
}
|
||||
BlockData slab = slabs.getOrDefault(down.getMaterial(), blank).get(0, block.getBlockX(), block.getBlockZ());
|
||||
BlockData slab = slabs.getOrDefault(down.getMaterial(), blank).get(0, block.getX(), block.getY(), block.getZ());
|
||||
if(slab instanceof Waterlogged) {
|
||||
((Waterlogged) slab).setWaterlogged(orig.matches(water));
|
||||
} else if(orig.matches(water)) return;
|
||||
@@ -165,11 +165,11 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
|
||||
private void prepareBlockPartCeiling(BlockData up, BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, Map<MaterialData, Palette<BlockData>> slabs,
|
||||
Map<MaterialData, Palette<BlockData>> stairs, double thresh, Sampler sampler) {
|
||||
if(sampler.sample(block.getBlockX(), block.getBlockY() + 0.4, block.getBlockZ()) > thresh) {
|
||||
if(sampler.sample(block.getX(), block.getY() + 0.4, block.getZ()) > thresh) {
|
||||
if(stairs != null) {
|
||||
Palette<BlockData> stairPalette = stairs.get(up.getMaterial());
|
||||
if(stairPalette != null) {
|
||||
BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ()).clone();
|
||||
BlockData stair = stairPalette.get(0, block.getX(), block.getY(), block.getZ()).clone();
|
||||
if(stair instanceof Stairs) {
|
||||
Stairs stairNew = (Stairs) stair.clone();
|
||||
stairNew.setHalf(Bisected.Half.TOP);
|
||||
@@ -177,7 +177,7 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
}
|
||||
}
|
||||
}
|
||||
BlockData slab = slabs.getOrDefault(up.getMaterial(), blank).get(0, block.getBlockX(), block.getBlockZ()).clone();
|
||||
BlockData slab = slabs.getOrDefault(up.getMaterial(), blank).get(0, block.getX(), block.getY(), block.getZ()).clone();
|
||||
if(slab instanceof Bisected) ((Bisected) slab).setHalf(Bisected.Half.TOP);
|
||||
if(slab instanceof Slab) ((Slab) slab).setType(Slab.Type.TOP);
|
||||
if(slab instanceof Waterlogged) {
|
||||
@@ -189,14 +189,14 @@ public class MasterChunkGenerator implements TerraChunkGenerator {
|
||||
|
||||
private boolean placeStair(BlockData orig, ChunkGenerator.ChunkData chunk, Vector3 block, double thresh, Sampler sampler, Stairs stairNew) {
|
||||
|
||||
if(sampler.sample(block.getBlockX() - 0.55, block.getBlockY(), block.getBlockZ()) > thresh) {
|
||||
if(sampler.sample(block.getBlockX() - 0.55, block.getY(), block.getZ()) > thresh) {
|
||||
|
||||
stairNew.setFacing(BlockFace.WEST);
|
||||
} else if(sampler.sample(block.getBlockX(), block.getBlockY(), block.getBlockZ() - 0.55) > thresh) {
|
||||
} else if(sampler.sample(block.getBlockX(), block.getY(), block.getZ() - 0.55) > thresh) {
|
||||
stairNew.setFacing(BlockFace.NORTH);
|
||||
} else if(sampler.sample(block.getBlockX(), block.getBlockY(), block.getBlockZ() + 0.55) > thresh) {
|
||||
} else if(sampler.sample(block.getBlockX(), block.getY(), block.getZ() + 0.55) > thresh) {
|
||||
stairNew.setFacing(BlockFace.SOUTH);
|
||||
} else if(sampler.sample(block.getBlockX() + 0.55, block.getBlockY(), block.getBlockZ()) > thresh) {
|
||||
} else if(sampler.sample(block.getX() + 0.55, block.getY(), block.getZ()) > thresh) {
|
||||
stairNew.setFacing(BlockFace.EAST);
|
||||
} else stairNew = null;
|
||||
if(stairNew != null) {
|
||||
|
||||
@@ -4,8 +4,11 @@ import com.dfsek.tectonic.annotations.Default;
|
||||
import com.dfsek.tectonic.annotations.Value;
|
||||
import com.dfsek.tectonic.config.ConfigTemplate;
|
||||
import com.dfsek.terra.api.math.noise.samplers.FastNoiseLite;
|
||||
import com.dfsek.terra.api.math.noise.samplers.LinearNormalizer;
|
||||
import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
import com.dfsek.terra.api.math.noise.samplers.Normalizer;
|
||||
|
||||
@SuppressWarnings("FieldMayBeFinal")
|
||||
public class NoiseBuilder implements ConfigTemplate {
|
||||
@Value("type")
|
||||
@Default
|
||||
@@ -39,7 +42,7 @@ public class NoiseBuilder implements ConfigTemplate {
|
||||
@Default
|
||||
private double weightedStrength = 0.0D;
|
||||
|
||||
@Value("offset")
|
||||
@Value("salt")
|
||||
@Default
|
||||
private int seedOffset = 0;
|
||||
|
||||
@@ -71,6 +74,22 @@ public class NoiseBuilder implements ConfigTemplate {
|
||||
@Default
|
||||
private int dimensions = 2;
|
||||
|
||||
@Value("cellular.lookup")
|
||||
@Default
|
||||
private NoiseBuilder lookup;
|
||||
|
||||
@Value("normalize.type")
|
||||
@Default
|
||||
private Normalizer.NormalType normalType = Normalizer.NormalType.NONE;
|
||||
|
||||
@Value("normalize.linear.min")
|
||||
@Default
|
||||
private double linearMin = -1D;
|
||||
|
||||
@Value("normalize.linear.max")
|
||||
@Default
|
||||
private double linearMax = 1D;
|
||||
|
||||
public NoiseSampler build(int seed) {
|
||||
FastNoiseLite noise = new FastNoiseLite(seed + seedOffset);
|
||||
if(!fractalType.equals(FastNoiseLite.FractalType.None)) {
|
||||
@@ -85,6 +104,7 @@ public class NoiseBuilder implements ConfigTemplate {
|
||||
noise.setCellularDistanceFunction(cellularDistanceFunction);
|
||||
noise.setCellularReturnType(cellularReturnType);
|
||||
noise.setCellularJitter(cellularJitter);
|
||||
if(lookup != null) noise.setCellularNoiseLookup(lookup.build(seed));
|
||||
}
|
||||
|
||||
noise.setNoiseType(type);
|
||||
@@ -95,6 +115,7 @@ public class NoiseBuilder implements ConfigTemplate {
|
||||
noise.setRotationType3D(rotationType3D);
|
||||
|
||||
noise.setFrequency(frequency);
|
||||
if(!normalType.equals(Normalizer.NormalType.NONE)) return new LinearNormalizer(noise, linearMin, linearMax);
|
||||
return noise;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ public class FloraPopulator implements TerraBlockPopulator {
|
||||
if(entry.getValue().size() <= iter) continue;
|
||||
finished = false;
|
||||
FloraLayer layer = entry.getValue().get(iter);
|
||||
if(layer.getDensity() >= random.nextDouble() * 100D) layer.place(chunk, entry.getKey(), random);
|
||||
if(layer.getDensity() >= random.nextDouble() * 100D) layer.place(chunk, entry.getKey());
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class TreePopulator implements TerraBlockPopulator {
|
||||
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE);
|
||||
for(TreeLayer layer : biome.getConfig().getTrees()) {
|
||||
if(layer.getDensity() >= random.nextDouble() * 100)
|
||||
layer.place(chunk, new Vector2(offset(random, x), offset(random, z)), random);
|
||||
layer.place(chunk, new Vector2(offset(random, x), offset(random, z)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import com.dfsek.terra.api.math.noise.samplers.NoiseSampler;
|
||||
import com.dfsek.terra.api.math.vector.Vector2;
|
||||
import com.dfsek.terra.api.platform.world.Chunk;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public abstract class PlaceableLayer<T> {
|
||||
protected final double density;
|
||||
protected final Range level;
|
||||
@@ -37,5 +35,5 @@ public abstract class PlaceableLayer<T> {
|
||||
return layer;
|
||||
}
|
||||
|
||||
public abstract void place(Chunk chunk, Vector2 coords, Random random);
|
||||
public abstract void place(Chunk chunk, Vector2 coords);
|
||||
}
|
||||
|
||||
@@ -8,8 +8,6 @@ import com.dfsek.terra.api.platform.world.Chunk;
|
||||
import com.dfsek.terra.api.world.flora.Flora;
|
||||
import com.dfsek.terra.population.items.PlaceableLayer;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class FloraLayer extends PlaceableLayer<Flora> {
|
||||
|
||||
public FloraLayer(double density, Range level, ProbabilityCollection<Flora> layer, NoiseSampler noise) {
|
||||
@@ -21,8 +19,8 @@ public class FloraLayer extends PlaceableLayer<Flora> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void place(Chunk chunk, Vector2 coords, Random random) {
|
||||
Flora item = noise == null ? layer.get(random) : layer.get(noise, (chunk.getX() << 4) + coords.getX(), (chunk.getZ() << 4) + coords.getZ());
|
||||
public void place(Chunk chunk, Vector2 coords) {
|
||||
Flora item = layer.get(noise, (chunk.getX() << 4) + coords.getX(), (chunk.getZ() << 4) + coords.getZ());
|
||||
item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class TerraFlora implements Flora {
|
||||
|
||||
for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor
|
||||
int lvl = (FastMath.abs(i));
|
||||
BlockData data = floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getBlockX(), location.getBlockZ()).clone();
|
||||
BlockData data = floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getX(), location.getY(), location.getZ()).clone();
|
||||
if(doRotation) {
|
||||
if(data instanceof Directional) {
|
||||
((Directional) data).setFacing(oneFace);
|
||||
|
||||
@@ -9,8 +9,7 @@ import com.dfsek.terra.api.platform.block.BlockFace;
|
||||
import com.dfsek.terra.api.platform.world.Chunk;
|
||||
import com.dfsek.terra.api.world.tree.Tree;
|
||||
import com.dfsek.terra.population.items.PlaceableLayer;
|
||||
|
||||
import java.util.Random;
|
||||
import com.dfsek.terra.util.PopulationUtil;
|
||||
|
||||
public class TreeLayer extends PlaceableLayer<Tree> {
|
||||
|
||||
@@ -19,13 +18,13 @@ public class TreeLayer extends PlaceableLayer<Tree> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void place(Chunk chunk, Vector2 coords, Random random) {
|
||||
Tree item = layer.get(random);
|
||||
public void place(Chunk chunk, Vector2 coords) {
|
||||
Tree item = layer.get(noise, coords.getX(), coords.getZ());
|
||||
Block current = chunk.getBlock((int) coords.getX(), level.getMax(), (int) coords.getZ());
|
||||
for(int ignored : level) {
|
||||
current = current.getRelative(BlockFace.DOWN);
|
||||
if(item.getSpawnable().contains(current.getType())) {
|
||||
item.plant(current.getLocation().add(0, 1, 0), random);
|
||||
item.plant(current.getLocation().add(0, 1, 0), PopulationUtil.getRandom(chunk));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user