pass seed to noise functions

This commit is contained in:
dfsek 2021-07-19 19:24:54 -07:00
parent 7acfc5e3d0
commit 3bf8fe7901
79 changed files with 299 additions and 382 deletions

View File

@ -29,7 +29,7 @@ public class ImageBiomeProvider implements BiomeProvider, SeededBuilder<BiomePro
}
@Override
public TerraBiome getBiome(int x, int z) {
public TerraBiome getBiome(int x, int z, long seed) {
x /= resolution;
z /= resolution;
Color color = align.getColor(image, x, z);

View File

@ -29,7 +29,7 @@ public class BiomeHolderImpl implements BiomeHolder {
}
@Override
public BiomeHolder expand(BiomeExpander expander) {
public BiomeHolder expand(BiomeExpander expander, long seed) {
TerraBiome[][] old = biomes;
int newWidth = width * 2 - 1;
@ -39,31 +39,31 @@ public class BiomeHolderImpl implements BiomeHolder {
for(int z = 0; z < width; z++) {
biomes[x * 2][z * 2] = old[x][z];
if(z != width - 1)
biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x][z + 1]);
biomes[x * 2][z * 2 + 1] = expander.getBetween(x + origin.getX(), z + 1 + origin.getZ(), seed, old[x][z], old[x][z + 1]);
if(x != width - 1)
biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), old[x][z], old[x + 1][z]);
biomes[x * 2 + 1][z * 2] = expander.getBetween(x + 1 + origin.getX(), z + origin.getZ(), seed, old[x][z], old[x + 1][z]);
if(x != width - 1 && z != width - 1)
biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]);
biomes[x * 2 + 1][z * 2 + 1] = expander.getBetween(x + 1 + origin.getX(), z + 1 + origin.getZ(), seed, old[x][z], old[x + 1][z + 1], old[x][z + 1], old[x + 1][z]);
}
}
return new BiomeHolderImpl(biomes, origin.setX(origin.getX() * 2 - 1).setZ(origin.getZ() * 2 - 1), newWidth, offset);
}
@Override
public void mutate(BiomeMutator mutator) {
public void mutate(BiomeMutator mutator, long seed) {
for(int x = 0; x < width; x++) {
for(int z = 0; z < width; z++) {
BiomeMutator.ViewPoint viewPoint = new BiomeMutator.ViewPoint(this, x, z);
biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ());
biomes[x][z] = mutator.mutate(viewPoint, x + origin.getX(), z + origin.getZ(), seed);
}
}
}
@Override
public void fill(BiomeSource source) {
public void fill(BiomeSource source, long seed) {
for(int x = 0; x < width; x++) {
for(int z = 0; z < width; z++) {
biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z);
biomes[x][z] = source.getBiome(origin.getX() + x, origin.getZ() + z, seed);
}
}
}

View File

@ -29,10 +29,10 @@ public class BiomePipelineImpl {
* @param z Chunk Z coord
* @return BiomeHolder containing biomes.
*/
public BiomeHolder getBiomes(int x, int z) {
public BiomeHolder getBiomes(int x, int z, long seed) {
BiomeHolder holder = new BiomeHolderImpl(init, new Vector2(x * (init - 1), z * (init - 1)));
holder.fill(source);
for(Stage stage : stages) holder = stage.apply(holder);
holder.fill(source, seed);
for(Stage stage : stages) holder = stage.apply(holder, seed);
return holder;
}

View File

@ -13,25 +13,23 @@ import net.jafama.FastMath;
import org.jetbrains.annotations.NotNull;
public class StandardBiomeProvider implements BiomeProvider {
private final LoadingCache<Vector2, BiomeHolder> holderCache;
private final LoadingCache<SeededVector, BiomeHolder> holderCache;
private final BiomePipelineImpl pipeline;
private final int resolution;
private final NoiseSampler mutator;
private final double noiseAmp;
private final int seed;
public StandardBiomeProvider(BiomePipelineImpl pipeline, TerraPlugin main, int resolution, NoiseSampler mutator, double noiseAmp, int seed) {
this.resolution = resolution;
this.mutator = mutator;
this.noiseAmp = noiseAmp;
this.seed = seed;
holderCache = CacheBuilder.newBuilder()
.maximumSize(main == null ? 32 : main.getTerraConfig().getProviderCache())
.build(
new CacheLoader<Vector2, BiomeHolder>() {
new CacheLoader<SeededVector, BiomeHolder>() {
@Override
public BiomeHolder load(@NotNull Vector2 key) {
return pipeline.getBiomes(key.getBlockX(), key.getBlockZ());
public BiomeHolder load(@NotNull SeededVector key) {
return pipeline.getBiomes(key.x, key.z, key.seed);
}
}
);
@ -39,9 +37,9 @@ public class StandardBiomeProvider implements BiomeProvider {
}
@Override
public TerraBiome getBiome(int x, int z) {
x += mutator.getNoiseSeeded(seed, x, z) * noiseAmp;
z += mutator.getNoiseSeeded(1 + seed, x, z) * noiseAmp;
public TerraBiome getBiome(int x, int z, long seed) {
x += mutator.getNoiseSeeded(seed + 1, x, z) * noiseAmp;
z += mutator.getNoiseSeeded(seed + 2, x, z) * noiseAmp;
x = FastMath.floorToInt(FastMath.floorDiv(x, resolution));
@ -50,6 +48,35 @@ public class StandardBiomeProvider implements BiomeProvider {
int fdX = FastMath.floorDiv(x, pipeline.getSize());
int fdZ = FastMath.floorDiv(z, pipeline.getSize());
return holderCache.getUnchecked(new Vector2(fdX, fdZ)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
return holderCache.getUnchecked(new SeededVector(fdX, fdZ, seed)).getBiome(x - fdX * pipeline.getSize(), z - fdZ * pipeline.getSize());
}
private static final class SeededVector {
private final int x;
private final int z;
private final long seed;
private SeededVector(int x, int z, long seed) {
this.x = x;
this.z = z;
this.seed = seed;
}
@Override
public int hashCode() {
int result = 0;
result = 31 * result + ((int) (seed ^ (seed >>> 32)));
result = 31 * result + x;
result = 31 * result + z;
return result;
}
@Override
public boolean equals(Object obj) {
if(!(obj instanceof SeededVector)) return false;
SeededVector that = (SeededVector) obj;
return this.seed == that.seed && this.x == that.x && this.z == that.z;
}
}
}

View File

@ -3,5 +3,5 @@ package com.dfsek.terra.addons.biome.pipeline.api;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeExpander {
TerraBiome getBetween(double x, double z, TerraBiome... others);
TerraBiome getBetween(double x, double z, long seed, TerraBiome... others);
}

View File

@ -4,11 +4,11 @@ import com.dfsek.terra.api.world.biome.TerraBiome;
import com.dfsek.terra.api.world.biome.generation.pipeline.BiomeSource;
public interface BiomeHolder {
BiomeHolder expand(BiomeExpander expander);
BiomeHolder expand(BiomeExpander expander, long seed);
void mutate(BiomeMutator mutator);
void mutate(BiomeMutator mutator, long seed);
void fill(BiomeSource source);
void fill(BiomeSource source, long seed);
TerraBiome getBiome(int x, int z);

View File

@ -3,7 +3,7 @@ package com.dfsek.terra.addons.biome.pipeline.api;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeMutator {
TerraBiome mutate(ViewPoint viewPoint, double x, double z);
TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed);
class ViewPoint {
private final BiomeHolder biomes;

View File

@ -3,6 +3,6 @@ package com.dfsek.terra.addons.biome.pipeline.api;
public interface Stage {
boolean isExpansion();
BiomeHolder apply(BiomeHolder in);
BiomeHolder apply(BiomeHolder in, long seed);
}

View File

@ -13,7 +13,7 @@ public class FractalExpander implements BiomeExpander {
}
@Override
public TerraBiome getBetween(double x, double z, TerraBiome... others) {
return others[MathUtil.normalizeIndex(sampler.getNoise(x, z), others.length)];
public TerraBiome getBetween(double x, double z, long seed, TerraBiome... others) {
return others[MathUtil.normalizeIndex(sampler.getNoiseSeeded(seed, x, z), others.length)];
}
}

View File

@ -23,7 +23,7 @@ public class BorderListMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome origin = viewPoint.getBiome(0, 0);
if(origin.getTags().contains(defaultReplace)) {
for(int xi = -1; xi <= 1; xi++) {
@ -33,10 +33,10 @@ public class BorderListMutator implements BiomeMutator {
if(current == null) continue;
if(current.getTags().contains(border)) {
if(replace.containsKey(origin)) {
TerraBiome biome = replace.get(origin).get(noiseSampler, x, z);
TerraBiome biome = replace.get(origin).get(noiseSampler, x, z, seed);
return biome == null ? origin : biome;
}
TerraBiome biome = replaceDefault.get(noiseSampler, x, z);
TerraBiome biome = replaceDefault.get(noiseSampler, x, z, seed);
return biome == null ? origin : biome;
}
}

View File

@ -19,7 +19,7 @@ public class BorderMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome origin = viewPoint.getBiome(0, 0);
if(origin.getTags().contains(replaceTag)) {
for(int xi = -1; xi <= 1; xi++) {
@ -28,7 +28,7 @@ public class BorderMutator implements BiomeMutator {
TerraBiome current = viewPoint.getBiome(xi, zi);
if(current == null) continue;
if(current.getTags().contains(border)) {
TerraBiome biome = replace.get(noiseSampler, x, z);
TerraBiome biome = replace.get(noiseSampler, x, z, seed);
return biome == null ? origin : biome;
}
}

View File

@ -21,14 +21,14 @@ public class ReplaceListMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome center = viewPoint.getBiome(0, 0);
if(replace.containsKey(center)) {
TerraBiome biome = replace.get(center).get(sampler, x, z);
TerraBiome biome = replace.get(center).get(sampler, x, z, seed);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
if(viewPoint.getBiome(0, 0).getTags().contains(defaultTag)) {
TerraBiome biome = replaceDefault.get(sampler, x, z);
TerraBiome biome = replaceDefault.get(sampler, x, z, seed);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
return center;

View File

@ -17,9 +17,9 @@ public class ReplaceMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
if(viewPoint.getBiome(0, 0).getTags().contains(replaceableTag)) {
TerraBiome biome = replace.get(sampler, x, z);
TerraBiome biome = replace.get(sampler, x, z, seed);
return biome == null ? viewPoint.getBiome(0, 0) : biome;
}
return viewPoint.getBiome(0, 0);

View File

@ -16,7 +16,7 @@ public class SmoothMutator implements BiomeMutator {
}
@Override
public TerraBiome mutate(ViewPoint viewPoint, double x, double z) {
public TerraBiome mutate(ViewPoint viewPoint, double x, double z, long seed) {
TerraBiome top = viewPoint.getBiome(1, 0);
TerraBiome bottom = viewPoint.getBiome(-1, 0);
TerraBiome left = viewPoint.getBiome(0, 1);
@ -27,7 +27,7 @@ public class SmoothMutator implements BiomeMutator {
boolean horiz = Objects.equals(left, right) && left != null;
if(vert && horiz) {
return MathUtil.normalizeIndex(sampler.getNoise(x, z), 2) == 0 ? left : top;
return MathUtil.normalizeIndex(sampler.getNoiseSeeded(seed, x, z), 2) == 0 ? left : top;
}
if(vert) return top;

View File

@ -15,7 +15,7 @@ public class RandomSource implements BiomeSource {
}
@Override
public TerraBiome getBiome(double x, double z) {
return biomes.get(sampler, x, z);
public TerraBiome getBiome(double x, double z, long seed) {
return biomes.get(sampler, x, z, seed);
}
}

View File

@ -17,8 +17,8 @@ public class ExpanderStage implements Stage {
}
@Override
public BiomeHolder apply(BiomeHolder in) {
return in.expand(expander);
public BiomeHolder apply(BiomeHolder in, long seed) {
return in.expand(expander, seed);
}
public enum Type {

View File

@ -17,8 +17,8 @@ public class MutatorStage implements Stage {
}
@Override
public BiomeHolder apply(BiomeHolder in) {
in.mutate(mutator);
public BiomeHolder apply(BiomeHolder in, long seed) {
in.mutate(mutator, seed);
return in;
}

View File

@ -12,7 +12,7 @@ public class SingleBiomeProvider implements BiomeProvider, SeededBuilder<BiomePr
}
@Override
public TerraBiome getBiome(int x, int z) {
public TerraBiome getBiome(int x, int z, long seed) {
return biome;
}

View File

@ -47,14 +47,15 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
try(ProfileFrame ignore = main.getProfiler().profile("biomes")) {
int xOrig = (chunkX << 4);
int zOrig = (chunkZ << 4);
long seed = world.getSeed();
BiomeProvider grid = main.getWorld(world).getBiomeProvider();
for(int x = 0; x < 4; x++) {
for(int z = 0; z < 4; z++) {
int cx = xOrig + (x << 2);
int cz = zOrig + (z << 2);
TerraBiome b = grid.getBiome(cx, cz);
TerraBiome b = grid.getBiome(cx, cz, seed);
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz));
biome.setBiome(cx, cz, b.getVanillaBiomes().get(b.getGenerator(world).getBiomeNoise(), cx, 0, cz, world.getSeed()));
}
}
}
@ -82,6 +83,8 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
Sampler sampler = tw.getConfig().getSamplerCache().getChunk(chunkX, chunkZ);
long seed = world.getSeed();
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
int paletteLevel = 0;
@ -89,7 +92,7 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
int cx = xOrig + x;
int cz = zOrig + z;
TerraBiome biome = grid.getBiome(cx, cz);
TerraBiome biome = grid.getBiome(cx, cz, seed);
PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class);
@ -108,12 +111,12 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
if(sampler.sample(x, y, z) > 0) {
justSet = true;
data = PaletteUtil.getPalette(x, y, z, generator, sampler, paletteInfo).get(paletteLevel, cx, y, cz);
data = PaletteUtil.getPalette(x, y, z, generator, sampler, paletteInfo).get(paletteLevel, cx, y, cz, seed);
chunk.setBlock(x, y, z, data);
paletteLevel++;
} else if(y <= sea) {
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig));
chunk.setBlock(x, y, z, seaPalette.get(sea - y, x + xOrig, y, z + zOrig, seed));
justSet = false;
paletteLevel = 0;
@ -167,7 +170,7 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
public BlockState getBlock(World world, int x, int y, int z) {
TerraWorld terraWorld = main.getWorld(world);
BiomeProvider provider = terraWorld.getBiomeProvider();
TerraBiome biome = provider.getBiome(x, z);
TerraBiome biome = provider.getBiome(x, z, world.getSeed());
Sampler sampler = terraWorld.getConfig().getSamplerCache().get(x, z);
PaletteInfo paletteInfo = biome.getContext().get(PaletteInfo.class);
@ -181,9 +184,9 @@ public class NoiseChunkGenerator3D implements TerraChunkGenerator {
if(sampler.sample(fdX, yi, fdZ) > 0) level++;
else level = 0;
}
return palette.get(level, x, y, z);
return palette.get(level, x, y, z, world.getSeed());
} else if(y <= paletteInfo.getSeaLevel()) {
return paletteInfo.getOcean().get(paletteInfo.getSeaLevel() - y, x, y, z);
return paletteInfo.getOcean().get(paletteInfo.getSeaLevel() - y, x, y, z, world.getSeed());
} else return air;
}
}

View File

@ -32,11 +32,13 @@ public class ChunkInterpolator2D implements ChunkInterpolator {
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
long seed = w.getSeed();
double[][] noiseStorage = new double[5][5];
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), seed).getGenerator(w);
Map<Generator, MutableInteger> genMap = new HashMap<>();
int step = generator.getBlendStep();
@ -44,7 +46,7 @@ public class ChunkInterpolator2D implements ChunkInterpolator {
for(int xi = -blend; xi <= blend; xi++) {
for(int zi = -blend; zi <= blend; zi++) {
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step), seed).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
}
}

View File

@ -45,9 +45,11 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
double[][][] noiseStorage = new double[5][5][size + 1];
long seed = w.getSeed();
for(int x = 0; x < 5; x++) {
for(int z = 0; z < 5; z++) {
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2)).getGenerator(w);
Generator generator = provider.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), seed).getGenerator(w);
Map<Generator, MutableInteger> genMap = new HashMap<>();
int step = generator.getBlendStep();
@ -55,7 +57,7 @@ public class ChunkInterpolator3D implements ChunkInterpolator {
for(int xi = -blend; xi <= blend; xi++) {
for(int zi = -blend; zi <= blend; zi++) {
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step)).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
genMap.computeIfAbsent(provider.getBiome(xOrigin + (x << 2) + (xi * step), zOrigin + (z << 2) + (zi * step), seed).getGenerator(w), g -> new MutableInteger(0)).increment(); // Increment by 1
}
}

View File

@ -11,12 +11,14 @@ public class ElevationInterpolator {
int xOrigin = chunkX << 4;
int zOrigin = chunkZ << 4;
long seed = world.getSeed();
Generator[][] gens = new Generator[18 + 2 * smooth][18 + 2 * smooth];
// Precompute generators.
for(int x = -1 - smooth; x <= 16 + smooth; x++) {
for(int z = -1 - smooth; z <= 16 + smooth; z++) {
gens[x + 1 + smooth][z + 1 + smooth] = provider.getBiome(xOrigin + x, zOrigin + z).getGenerator(world);
gens[x + 1 + smooth][z + 1 + smooth] = provider.getBiome(xOrigin + x, zOrigin + z, seed).getGenerator(world);
}
}
@ -27,7 +29,7 @@ public class ElevationInterpolator {
for(int xi = -smooth; xi <= smooth; xi++) {
for(int zi = -smooth; zi <= smooth; zi++) {
Generator gen = gens[x + 1 + smooth + xi][z + 1 + smooth + zi];
noise += gen.getElevationSampler().getNoise(xOrigin + x, zOrigin + z) * gen.getElevationWeight();
noise += gen.getElevationSampler().getNoiseSeeded(seed, xOrigin + x, zOrigin + z) * gen.getElevationWeight();
div += gen.getElevationWeight();
}
}

View File

@ -12,7 +12,7 @@ public class Sampler3D implements Sampler {
private final ElevationInterpolator elevationInterpolator;
public Sampler3D(int x, int z, BiomeProvider provider, World world, int elevationSmooth) {
this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoise(coord));
this.interpolator = new ChunkInterpolator3D(world, x, z, provider, (generator, coord) -> generator.getBaseSampler().getNoiseSeeded(coord, world.getSeed()));
this.elevationInterpolator = new ElevationInterpolator(world, x, z, provider, elevationSmooth);
}

View File

@ -46,7 +46,7 @@ public class AsyncBiomeFinder implements Runnable {
*/
public boolean isValid(int x, int z, TerraBiome target) {
int res = main.getTerraConfig().getBiomeSearchResolution();
return getProvider().getBiome(x * res, z * res).equals(target);
return getProvider().getBiome(x * res, z * res, world.getSeed()).equals(target);
}
public Vector3 finalizeVector(Vector3 orig) {

View File

@ -38,7 +38,7 @@ public class BiomeCommand implements CommandTemplate {
Player player = (Player) sender;
BiomeProvider provider = main.getWorld(player.world()).getBiomeProvider();
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.position());
UserDefinedBiome biome = (UserDefinedBiome) provider.getBiome(player.position(), player.world().getSeed());
sender.sendMessage("You are standing in " + biome.getID());
}
}

View File

@ -39,7 +39,7 @@ public class CarverCache {
List<Worm.WormPoint> points = new ArrayList<>();
for(int i = 0; i < carving.getLength(); i++) {
carving.step();
TerraBiome biome = provider.getBiome(carving.getRunning());
TerraBiome biome = provider.getBiome(carving.getRunning(), w.getSeed());
/*
if(!((UserDefinedBiome) biome).getConfig().getCarvers().containsKey(CarverCache.this.carver)) { // Stop if we enter a biome this carver is not present in
return Collections.emptyList();

View File

@ -11,7 +11,7 @@ public class NoiseDistributor implements Distributor {
}
@Override
public boolean matches(int x, int z) {
return sampler.getNoise(x, z) > 0;
public boolean matches(int x, int z, long seed) {
return sampler.getNoiseSeeded(seed, x, z) > 0;
}
}

View File

@ -116,7 +116,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));
BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), location.getZ()).clone();
BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), location.getZ(), world.getSeed()).clone();
if(doRotation) {
Direction oneFace = new ArrayList<>(faces).get(new Random(location.getBlockX() ^ location.getBlockZ()).nextInt(faces.size())); // Get random face.

View File

@ -16,8 +16,6 @@ import com.dfsek.terra.addons.noise.config.templates.noise.fractal.RidgedFractal
import com.dfsek.terra.addons.noise.config.templates.normalizer.ClampNormalizerTemplate;
import com.dfsek.terra.addons.noise.config.templates.normalizer.LinearNormalizerTemplate;
import com.dfsek.terra.addons.noise.config.templates.normalizer.NormalNormalizerTemplate;
import com.dfsek.terra.addons.noise.samplers.ImageSampler;
import com.dfsek.terra.addons.noise.samplers.noise.CellularSampler;
import com.dfsek.terra.addons.noise.samplers.noise.random.GaussianNoiseSampler;
import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler;
import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2SSampler;
@ -64,10 +62,7 @@ public class NoiseAddon extends TerraAddon implements EventListener {
.applyLoader(DomainWarpTemplate.class, DomainWarpTemplate::new)
.applyLoader(LinearNormalizerTemplate.class, LinearNormalizerTemplate::new)
.applyLoader(NormalNormalizerTemplate.class, NormalNormalizerTemplate::new)
.applyLoader(ImageSampler.Channel.class, (t, object, cf) -> ImageSampler.Channel.valueOf((String) object))
.applyLoader(ClampNormalizerTemplate.class, ClampNormalizerTemplate::new)
.applyLoader(CellularSampler.ReturnType.class, (t, object, cf) -> CellularSampler.ReturnType.valueOf((String) object))
.applyLoader(CellularSampler.DistanceFunction.class, (t, object, cf) -> CellularSampler.DistanceFunction.valueOf((String) object));
.applyLoader(ClampNormalizerTemplate.class, ClampNormalizerTemplate::new);
noiseRegistry.register("LINEAR", LinearNormalizerTemplate::new);
noiseRegistry.register("NORMAL", NormalNormalizerTemplate::new);
@ -81,20 +76,20 @@ public class NoiseAddon extends TerraAddon implements EventListener {
noiseRegistry.register("PINGPONG", PingPongTemplate::new);
noiseRegistry.register("RIDGED", RidgedFractalTemplate::new);
noiseRegistry.register("OPENSIMPLEX2", () -> new SimpleNoiseTemplate(OpenSimplex2Sampler::new));
noiseRegistry.register("OPENSIMPLEX2S", () -> new SimpleNoiseTemplate(OpenSimplex2SSampler::new));
noiseRegistry.register("PERLIN", () -> new SimpleNoiseTemplate(PerlinSampler::new));
noiseRegistry.register("SIMPLEX", () -> new SimpleNoiseTemplate(SimplexSampler::new));
noiseRegistry.register("OPENSIMPLEX2", () -> new SimpleNoiseTemplate(seed3 -> new OpenSimplex2Sampler()));
noiseRegistry.register("OPENSIMPLEX2S", () -> new SimpleNoiseTemplate(seed3 -> new OpenSimplex2SSampler()));
noiseRegistry.register("PERLIN", () -> new SimpleNoiseTemplate(seed2 -> new PerlinSampler()));
noiseRegistry.register("SIMPLEX", () -> new SimpleNoiseTemplate(seed2 -> new SimplexSampler()));
noiseRegistry.register("GABOR", GaborNoiseTemplate::new);
noiseRegistry.register("VALUE", () -> new SimpleNoiseTemplate(ValueSampler::new));
noiseRegistry.register("VALUECUBIC", () -> new SimpleNoiseTemplate(ValueCubicSampler::new));
noiseRegistry.register("VALUECUBIC", () -> new SimpleNoiseTemplate(seed1 -> new ValueCubicSampler()));
noiseRegistry.register("CELLULAR", CellularNoiseTemplate::new);
noiseRegistry.register("WHITENOISE", () -> new SimpleNoiseTemplate(WhiteNoiseSampler::new));
noiseRegistry.register("GAUSSIAN", () -> new SimpleNoiseTemplate(GaussianNoiseSampler::new));
noiseRegistry.register("WHITENOISE", () -> new SimpleNoiseTemplate(seed -> new WhiteNoiseSampler()));
noiseRegistry.register("GAUSSIAN", () -> new SimpleNoiseTemplate(seed -> new GaussianNoiseSampler()));
noiseRegistry.register("CONSTANT", ConstantNoiseTemplate::new);

View File

@ -24,6 +24,6 @@ public class DomainWarpTemplate extends SamplerTemplate<DomainWarpedSampler> {
@Override
public NoiseSampler build(long seed) {
return new DomainWarpedSampler(function.build(seed), warp.build(seed), (int) (seed + salt), amplitude);
return new DomainWarpedSampler(function.build(seed), warp.build(seed), amplitude);
}
}

View File

@ -27,7 +27,7 @@ public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
private SeededNoiseSampler lookup = new SeededNoiseSampler() {
@Override
public NoiseSampler build(long seed) {
return new OpenSimplex2Sampler((int) seed);
return new OpenSimplex2Sampler();
}
@Override
@ -38,7 +38,7 @@ public class CellularNoiseTemplate extends NoiseTemplate<CellularSampler> {
@Override
public NoiseSampler build(long seed) {
CellularSampler sampler = new CellularSampler((int) seed + salt);
CellularSampler sampler = new CellularSampler();
sampler.setNoiseLookup(lookup.build(seed));
sampler.setFrequency(frequency);
sampler.setJitterModifier(cellularJitter);

View File

@ -28,7 +28,7 @@ public class GaborNoiseTemplate extends NoiseTemplate<GaborNoiseSampler> {
@Override
public NoiseSampler build(long seed) {
GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler((int) seed + salt);
GaborNoiseSampler gaborNoiseSampler = new GaborNoiseSampler();
gaborNoiseSampler.setFrequency(frequency);
gaborNoiseSampler.setRotation(rotation);
gaborNoiseSampler.setIsotropic(isotropic);

View File

@ -12,22 +12,12 @@ public abstract class Normalizer implements NoiseSampler {
public abstract double normalize(double in);
@Override
public double getNoise(double x, double y) {
return normalize(sampler.getNoise(x, y));
}
@Override
public double getNoise(double x, double y, double z) {
return normalize(sampler.getNoise(x, y, z));
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
return normalize(sampler.getNoiseSeeded(seed, x, y));
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
public double getNoiseSeeded(long seed, double x, double y, double z) {
return normalize(sampler.getNoiseSeeded(seed, x, y, z));
}
}

View File

@ -4,6 +4,7 @@ import com.dfsek.paralithic.Expression;
import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
@ -31,6 +32,11 @@ public class UserDefinedFunction implements DynamicFunction {
return expression.evaluate(args);
}
@Override
public double eval(Context context, double... args) {
return expression.evaluate(context, args);
}
@Override
public boolean isStateless() {
return true;

View File

@ -1,7 +0,0 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
public interface NoiseFunction extends DynamicFunction {
}

View File

@ -1,12 +1,13 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.terra.addons.noise.util.HashMapDoubleDouble;
import com.dfsek.terra.api.noise.NoiseSampler;
public class NoiseFunction2 implements NoiseFunction {
public class NoiseFunction2 implements DynamicFunction {
private final NoiseSampler gen;
private final Cache cache = new Cache();
public NoiseFunction2(NoiseSampler gen) {
this.gen = gen;
@ -19,36 +20,16 @@ public class NoiseFunction2 implements NoiseFunction {
@Override
public double eval(double... args) {
return cache.get(gen, args[0], args[1]);
throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context.");
}
@Override
public double eval(Context context, double... args) {
return gen.getNoiseSeeded(((SeedContext) context).getSeed(), args[0], args[1]);
}
@Override
public boolean isStateless() {
return true;
}
private static class Cache extends HashMapDoubleDouble {
private static final long serialVersionUID = 8915092734723467010L;
private static final int cacheSize = 384;
public Cache() {
super(cacheSize);
}
public double get(NoiseSampler noise, double x, double z) {
double xx = x >= 0 ? x * 2 : x * -2 - 1;
double zz = z >= 0 ? z * 2 : z * -2 - 1;
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
double value = this.get(key);
if(this.size() > cacheSize) {
this.clear();
}
return (value == 4.9E-324D ? addAndReturn(noise.getNoise(x, z), key) : value);
}
private synchronized double addAndReturn(double value, double key) {
this.put(key, value);
return value;
}
return false;
}
}

View File

@ -1,8 +1,10 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.terra.api.noise.NoiseSampler;
public class NoiseFunction3 implements NoiseFunction {
public class NoiseFunction3 implements DynamicFunction {
private final NoiseSampler gen;
public NoiseFunction3(NoiseSampler gen) {
@ -16,11 +18,16 @@ public class NoiseFunction3 implements NoiseFunction {
@Override
public double eval(double... args) {
return gen.getNoise(args[0], args[1], args[2]);
throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context.");
}
@Override
public double eval(Context context, double... args) {
return gen.getNoiseSeeded(((SeedContext) context).getSeed(), args[0], args[1], args[2]);
}
@Override
public boolean isStateless() {
return true;
return false;
}
}

View File

@ -0,0 +1,15 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
public class SeedContext implements Context {
private final long seed;
public SeedContext(long seed) {
this.seed = seed;
}
public long getSeed() {
return seed;
}
}

View File

@ -5,40 +5,28 @@ import com.dfsek.terra.api.noise.NoiseSampler;
public class DomainWarpedSampler implements NoiseSampler {
private final NoiseSampler function;
private final NoiseSampler warp;
private final int seed;
private final double amplitude;
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, int seed, double amplitude) {
public DomainWarpedSampler(NoiseSampler function, NoiseSampler warp, double amplitude) {
this.function = function;
this.warp = warp;
this.seed = seed;
this.amplitude = amplitude;
}
@Override
public double getNoise(double x, double y) {
return getNoiseSeeded(seed, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return getNoiseSeeded(seed, x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y) * amplitude,
y + warp.getNoiseSeeded(seed + 1, x, y) * amplitude
public double getNoiseSeeded(long seed, double x, double y) {
return function.getNoiseSeeded(seed++,
x + warp.getNoiseSeeded(seed++, x, y) * amplitude,
y + warp.getNoiseSeeded(seed, x, y) * amplitude
);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return function.getNoise(
x + warp.getNoiseSeeded(seed, x, y, z) * amplitude,
y + warp.getNoiseSeeded(seed + 1, x, y, z) * amplitude,
z + warp.getNoiseSeeded(seed + 2, x, y, z) * amplitude
public double getNoiseSeeded(long seed, double x, double y, double z) {
return function.getNoiseSeeded(seed++,
x + warp.getNoiseSeeded(seed++, x, y, z) * amplitude,
y + warp.getNoiseSeeded(seed++, x, y, z) * amplitude,
z + warp.getNoiseSeeded(seed, x, y, z) * amplitude
);
}
}

View File

@ -8,6 +8,7 @@ import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3;
import com.dfsek.terra.addons.noise.paralithic.noise.SeedContext;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.seeded.SeededNoiseSampler;
@ -46,22 +47,12 @@ public class ExpressionSampler implements NoiseSampler {
}
@Override
public double getNoise(double x, double y) {
return getNoise(x, 0, y);
public double getNoiseSeeded(long seed, double x, double y) {
return getNoiseSeeded(seed, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return expression.evaluate(x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
public double getNoiseSeeded(long seed, double x, double y, double z) {
return expression.evaluate(new SeedContext(seed), x, y, z);
}
}

View File

@ -18,23 +18,13 @@ public class ImageSampler implements NoiseSampler {
}
@Override
public double getNoise(double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
return ((channel.getChannel(image.getRGB(FastMath.floorMod(FastMath.floorToInt(x * frequency), image.getWidth()), FastMath.floorMod(FastMath.floorToInt(y * frequency), image.getHeight()))) / 255D) - 0.5) * 2;
}
@Override
public double getNoise(double x, double y, double z) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return getNoise(x, y);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
return getNoise(x, y, z);
public double getNoiseSeeded(long seed, double x, double y, double z) {
return getNoiseSeeded(seed, x, y);
}
public enum Channel {

View File

@ -13,24 +13,14 @@ public class KernelSampler implements NoiseSampler {
}
@Override
public double getNoise(double x, double y) {
return getNoiseSeeded(0, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return getNoiseSeeded(0, x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
x *= frequency;
y *= frequency;
double accumulator = 0;
for(int kx = 0; kx < kernel.length; kx++) {
for(int ky = 0; ky < kernel[kx].length; ky++) {
accumulator += in.getNoise(x + kx, y + ky) * kernel[kx][ky];
accumulator += in.getNoiseSeeded(seed, x + kx, y + ky) * kernel[kx][ky];
}
}
@ -38,7 +28,7 @@ public class KernelSampler implements NoiseSampler {
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
public double getNoiseSeeded(long seed, double x, double y, double z) {
x *= frequency;
y *= frequency;
z *= frequency;
@ -46,7 +36,7 @@ public class KernelSampler implements NoiseSampler {
for(int kx = 0; kx < kernel.length; kx++) {
for(int ky = 0; ky < kernel[kx].length; ky++) {
accumulator += in.getNoise(x + kx, y, z + ky) * kernel[kx][ky];
accumulator += in.getNoiseSeeded(seed, x + kx, y, z + ky) * kernel[kx][ky];
}
}

View File

@ -192,9 +192,8 @@ public class CellularSampler extends NoiseFunction {
private NoiseSampler noiseLookup;
public CellularSampler(int seed) {
super(seed);
noiseLookup = new OpenSimplex2Sampler(seed);
public CellularSampler() {
noiseLookup = new OpenSimplex2Sampler();
}
public void setDistanceFunction(DistanceFunction distanceFunction) {
@ -214,7 +213,8 @@ public class CellularSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
int xr = fastRound(x);
int yr = fastRound(y);
@ -349,7 +349,7 @@ public class CellularSampler extends NoiseFunction {
case Distance2Div:
return distance0 / distance1 - 1;
case NoiseLookup:
return noiseLookup.getNoise(center.getX(), center.getZ());
return noiseLookup.getNoiseSeeded(sl, center.getX(), center.getZ());
case Distance3:
return distance2 - 1;
case Distance3Add:
@ -366,7 +366,8 @@ public class CellularSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
int xr = fastRound(x);
int yr = fastRound(y);
int zr = fastRound(z);
@ -523,7 +524,7 @@ public class CellularSampler extends NoiseFunction {
case Distance2Div:
return distance0 / distance1 - 1;
case NoiseLookup:
return noiseLookup.getNoise(center.getX(), center.getY(), center.getZ());
return noiseLookup.getNoiseSeeded(sl, center.getX(), center.getY(), center.getZ());
case Distance3:
return distance2 - 1;
case Distance3Add:

View File

@ -7,17 +7,16 @@ public class ConstantSampler extends NoiseFunction {
private final double constant;
public ConstantSampler(double constant) {
super(0);
this.constant = constant;
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
return constant;
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
return constant;
}
}

View File

@ -5,6 +5,7 @@ import com.dfsek.paralithic.eval.parser.Parser;
import com.dfsek.paralithic.eval.parser.Scope;
import com.dfsek.paralithic.eval.tokenizer.ParseException;
import com.dfsek.paralithic.functions.Function;
import com.dfsek.terra.addons.noise.paralithic.noise.SeedContext;
import java.util.Map;
@ -15,7 +16,6 @@ public class ExpressionFunction extends NoiseFunction {
private final Expression expression;
public ExpressionFunction(Map<String, Function> functions, String eq, Map<String, Double> vars) throws ParseException {
super(0);
Parser p = new Parser();
Scope scope = new Scope();
@ -32,12 +32,12 @@ public class ExpressionFunction extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
return expression.evaluate(x, 0, y);
public double getNoiseRaw(long seed, double x, double y) {
return expression.evaluate(new SeedContext(seed), x, 0, y);
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
return expression.evaluate(x, y, z);
public double getNoiseRaw(long seed, double x, double y, double z) {
return expression.evaluate(new SeedContext(seed), x, y, z);
}
}

View File

@ -18,9 +18,8 @@ public class GaborNoiseSampler extends NoiseFunction {
private double g = FastMath.exp(-impulsesPerCell);
public GaborNoiseSampler(int seed) {
super(seed);
rand = new WhiteNoiseSampler(seed);
public GaborNoiseSampler() {
rand = new WhiteNoiseSampler();
}
public void setIsotropic(boolean isotropic) {
@ -57,16 +56,16 @@ public class GaborNoiseSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double z) {
public double getNoiseRaw(long seed, double x, double z) {
return gaborNoise(seed, x, z);
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
return gaborNoise(seed, x, z);
}
private double gaborNoise(int seed, double x, double y) {
private double gaborNoise(long seed, double x, double y) {
x /= kernelRadius;
y /= kernelRadius;
int xi = fastFloor(x);
@ -82,7 +81,7 @@ public class GaborNoiseSampler extends NoiseFunction {
return noise;
}
private double calculateCell(int seed, int xi, int yi, double x, double y) {
private double calculateCell(long seed, int xi, int yi, double x, double y) {
long mashedSeed = murmur64(31L * xi + yi) + seed;
double gaussianSource = (rand.getNoiseRaw(mashedSeed++) + 1) / 2;

View File

@ -20,11 +20,6 @@ public abstract class NoiseFunction implements NoiseSampler {
}
protected double frequency = 0.02d;
protected int seed;
public NoiseFunction(int seed) {
this.seed = seed;
}
protected static int fastFloor(double f) {
return f >= 0 ? (int) f : (int) f - 1;
@ -114,11 +109,6 @@ public abstract class NoiseFunction implements NoiseSampler {
return sinLookup((int) ((a + Math.PI / 2) * precision + 0.5f));
}
public void setSeed(int seed) {
this.seed = seed;
}
public double getFrequency() {
return frequency;
}
@ -128,26 +118,16 @@ public abstract class NoiseFunction implements NoiseSampler {
}
@Override
public double getNoise(double x, double y) {
return getNoiseSeeded(seed, x, y);
}
@Override
public double getNoise(double x, double y, double z) {
return getNoiseSeeded(seed, x, y, z);
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
return getNoiseRaw(seed, x * frequency, y * frequency);
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
public double getNoiseSeeded(long seed, double x, double y, double z) {
return getNoiseRaw(seed, x * frequency, y * frequency, z * frequency);
}
public abstract double getNoiseRaw(int seed, double x, double y);
public abstract double getNoiseRaw(long seed, double x, double y);
public abstract double getNoiseRaw(int seed, double x, double y, double z);
public abstract double getNoiseRaw(long seed, double x, double y, double z);
}

View File

@ -4,11 +4,11 @@ import com.dfsek.terra.api.noise.NoiseSampler;
public class BrownianMotionSampler extends FractalNoiseFunction {
public BrownianMotionSampler(int seed, NoiseSampler input) {
super(seed, input);
super(input);
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
double sum = 0;
double amp = fractalBounding;
@ -26,7 +26,7 @@ public class BrownianMotionSampler extends FractalNoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
double sum = 0;
double amp = fractalBounding;

View File

@ -11,8 +11,7 @@ public abstract class FractalNoiseFunction extends NoiseFunction {
protected double lacunarity = 2.0d;
protected double weightedStrength = 0.0d;
public FractalNoiseFunction(int seed, NoiseSampler input) {
super(seed);
public FractalNoiseFunction(NoiseSampler input) {
this.input = input;
frequency = 1;
}

View File

@ -6,7 +6,7 @@ public class PingPongSampler extends FractalNoiseFunction {
private double pingPongStrength = 2.0;
public PingPongSampler(int seed, NoiseSampler input) {
super(seed, input);
super(input);
}
@ -20,7 +20,7 @@ public class PingPongSampler extends FractalNoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
double sum = 0;
double amp = fractalBounding;
@ -38,7 +38,7 @@ public class PingPongSampler extends FractalNoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
double sum = 0;
double amp = fractalBounding;

View File

@ -5,11 +5,11 @@ import com.dfsek.terra.api.noise.NoiseSampler;
public class RidgedFractalSampler extends FractalNoiseFunction {
public RidgedFractalSampler(int seed, NoiseSampler input) {
super(seed, input);
super(input);
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
double sum = 0;
double amp = fractalBounding;
@ -27,7 +27,7 @@ public class RidgedFractalSampler extends FractalNoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
double sum = 0;
double amp = fractalBounding;

View File

@ -8,13 +8,12 @@ import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction;
public class GaussianNoiseSampler extends NoiseFunction {
private final WhiteNoiseSampler whiteNoiseSampler; // Back with a white noise sampler.
public GaussianNoiseSampler(int seed) {
super(seed);
whiteNoiseSampler = new WhiteNoiseSampler(seed);
public GaussianNoiseSampler() {
whiteNoiseSampler = new WhiteNoiseSampler();
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
double v1, v2, s;
do {
v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y);
@ -26,7 +25,7 @@ public class GaussianNoiseSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
double v1, v2, s;
do {
v1 = whiteNoiseSampler.getNoiseSeeded(seed++, x, y, z);

View File

@ -8,8 +8,7 @@ import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction;
public class WhiteNoiseSampler extends NoiseFunction {
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.
public WhiteNoiseSampler(int seed) {
super(seed);
public WhiteNoiseSampler() {
}
public double getNoiseRaw(long seed) {
@ -17,33 +16,33 @@ public class WhiteNoiseSampler extends NoiseFunction {
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long seed, double x, double y) {
return (getNoiseUnmapped(seed, x, y) - 1.5) * 2;
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long seed, double x, double y, double z) {
return (getNoiseUnmapped(seed, x, y, z) - 1.5) * 2;
}
public double getNoiseUnmapped(int seed, double x, double y, double z) {
public double getNoiseUnmapped(long seed, double x, double y, double z) {
long base = ((randomBits(seed, x, y, z)) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent
return Double.longBitsToDouble(base);
}
public double getNoiseUnmapped(int seed, double x, double y) {
public double getNoiseUnmapped(long seed, double x, double y) {
long base = (randomBits(seed, x, y) & 0x000fffffffffffffL) | POSITIVE_POW1; // Sign and exponent
return Double.longBitsToDouble(base);
}
public long randomBits(int seed, double x, double y, double z) {
public long randomBits(long seed, double x, double y, double z) {
long hashX = Double.doubleToRawLongBits(x) ^ seed;
long hashZ = Double.doubleToRawLongBits(y) ^ seed;
long hash = (((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed) + Double.doubleToRawLongBits(z);
return murmur64(hash);
}
public long randomBits(int seed, double x, double y) {
public long randomBits(long seed, double x, double y) {
long hashX = Double.doubleToRawLongBits(x) ^ seed;
long hashZ = Double.doubleToRawLongBits(y) ^ seed;
long hash = ((hashX ^ (hashX >>> 32)) + ((hashZ ^ (hashZ >>> 32)) << 32)) ^ seed;

View File

@ -4,13 +4,10 @@ package com.dfsek.terra.addons.noise.samplers.noise.simplex;
* NoiseSampler implementation to provide OpenSimplex2 (Smooth Variant) noise.
*/
public class OpenSimplex2SSampler extends SimplexStyleSampler {
public OpenSimplex2SSampler(int seed) {
super(seed);
}
@Override
@SuppressWarnings("NumericOverflow")
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
// 2D OpenSimplex2S case is a modified 2D simplex noise.
final double SQRT3 = 1.7320508075688772935274463415059;
@ -117,7 +114,8 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler {
@Override
@SuppressWarnings("NumericOverflow")
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
// 3D OpenSimplex2S case uses two offset rotated cube grids.
final double R3 = (2.0 / 3.0);
double r = (x + y + z) * R3; // Rotation, not skew

View File

@ -6,12 +6,9 @@ package com.dfsek.terra.addons.noise.samplers.noise.simplex;
public class OpenSimplex2Sampler extends SimplexStyleSampler {
private static final double SQRT3 = 1.7320508075688772935274463415059;
public OpenSimplex2Sampler(int seed) {
super(seed);
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
// 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex.
final double G2 = (3 - SQRT3) / 6;
@ -71,7 +68,8 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
// 3D OpenSimplex2Sampler case uses two offset rotated cube grids.
final double R3 = (2.0 / 3.0);
double r = (x + y + z) * R3; // Rotation, not skew

View File

@ -4,12 +4,9 @@ package com.dfsek.terra.addons.noise.samplers.noise.simplex;
* NoiseSampler implementation to provide Perlin Noise.
*/
public class PerlinSampler extends SimplexStyleSampler {
public PerlinSampler(int seed) {
super(seed);
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
int x0 = fastFloor(x);
int y0 = fastFloor(y);
@ -33,7 +30,8 @@ public class PerlinSampler extends SimplexStyleSampler {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
int x0 = fastFloor(x);
int y0 = fastFloor(y);
int z0 = fastFloor(z);

View File

@ -23,10 +23,6 @@ public class SimplexSampler extends SimplexStyleSampler {
private static final int Z_PRIME = 6971;
public SimplexSampler(int seed) {
super(seed);
}
private static double gradCoord3D(int seed, int x, int y, int z, double xd, double yd, double zd) {
int hash = seed;
hash ^= X_PRIME * x;
@ -55,7 +51,8 @@ public class SimplexSampler extends SimplexStyleSampler {
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
double t = (x + y) * F2;
int i = fastFloor(x + t);
int j = fastFloor(y + t);
@ -111,7 +108,8 @@ public class SimplexSampler extends SimplexStyleSampler {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
double t = (x + y + z) * F3;
int i = fastFloor(x + t);
int j = fastFloor(y + t);

View File

@ -71,10 +71,6 @@ public abstract class SimplexStyleSampler extends NoiseFunction {
1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0
};
public SimplexStyleSampler(int seed) {
super(seed);
}
protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) {
int hash = hash(seed, xPrimed, yPrimed);
hash ^= hash >> 15;

View File

@ -1,12 +1,9 @@
package com.dfsek.terra.addons.noise.samplers.noise.value;
public class ValueCubicSampler extends ValueStyleNoise {
public ValueCubicSampler(int seed) {
super(seed);
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
int x1 = fastFloor(x);
int y1 = fastFloor(y);
@ -35,7 +32,8 @@ public class ValueCubicSampler extends ValueStyleNoise {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
int x1 = fastFloor(x);
int y1 = fastFloor(y);
int z1 = fastFloor(z);

View File

@ -2,11 +2,12 @@ package com.dfsek.terra.addons.noise.samplers.noise.value;
public class ValueSampler extends ValueStyleNoise {
public ValueSampler(int seed) {
super(seed);
super();
}
@Override
public double getNoiseRaw(int seed, double x, double y) {
public double getNoiseRaw(long sl, double x, double y) {
int seed = (int) sl;
int x0 = fastFloor(x);
int y0 = fastFloor(y);
@ -25,7 +26,8 @@ public class ValueSampler extends ValueStyleNoise {
}
@Override
public double getNoiseRaw(int seed, double x, double y, double z) {
public double getNoiseRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
int x0 = fastFloor(x);
int y0 = fastFloor(y);
int z0 = fastFloor(z);

View File

@ -3,9 +3,6 @@ package com.dfsek.terra.addons.noise.samplers.noise.value;
import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction;
public abstract class ValueStyleNoise extends NoiseFunction {
public ValueStyleNoise(int seed) {
super(seed);
}
protected static double valCoord(int seed, int xPrimed, int yPrimed) {
int hash = hash(seed, xPrimed, yPrimed);

View File

@ -31,7 +31,7 @@ public class OrePopulator implements TerraGenerationStage {
Random random = new Random(PopulationUtil.getCarverChunkSeed(chunk.getX() + cx, chunk.getZ() + cz, world.getSeed()));
int originX = ((chunk.getX() + cx) << 4);
int originZ = ((chunk.getZ() + cz) << 4);
TerraBiome b = tw.getBiomeProvider().getBiome(originX + 8, originZ + 8);
TerraBiome b = tw.getBiomeProvider().getBiome(originX + 8, originZ + 8, world.getSeed());
/*
BiomeTemplate config = ((UserDefinedBiome) b).getConfig();
int finalCx = cx;

View File

@ -15,7 +15,7 @@ public class NoisePalette extends PaletteImpl {
}
@Override
public BlockState get(int layer, double x, double y, double z) {
public BlockState get(int layer, double x, double y, double z, long seed) {
PaletteLayer paletteLayer;
if(layer > this.getSize()) paletteLayer = this.getLayers().get(this.getLayers().size() - 1);
else {
@ -24,6 +24,6 @@ public class NoisePalette extends PaletteImpl {
else paletteLayer = pl.get(layer);
}
NoiseSampler paletteSampler = paletteLayer.getSampler();
return paletteLayer.get(paletteSampler == null ? sampler : paletteSampler, x, y, z, is2D);
return paletteLayer.get(paletteSampler == null ? sampler : paletteSampler, x, y, z, is2D, seed);
}
}

View File

@ -13,7 +13,7 @@ import java.util.Random;
* A class representation of a "slice" of the world.
* Used to get a section of blocks, based on the depth at which they are found.
*/
public abstract class PaletteImpl implements com.dfsek.terra.api.world.generator.Palette {
public abstract class PaletteImpl implements Palette {
private final List<PaletteLayer> pallet = new ArrayList<>();
/**
@ -96,9 +96,9 @@ public abstract class PaletteImpl implements com.dfsek.terra.api.world.generator
return m;
}
public BlockState 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);
public BlockState get(NoiseSampler random, double x, double y, double z, boolean is2D, long seed) {
if(col && is2D) return this.collection.get(random, x, z, seed);
else if(col) return this.collection.get(random, x, y, z, seed);
return m;
}
@ -115,7 +115,7 @@ public abstract class PaletteImpl implements com.dfsek.terra.api.world.generator
}
@Override
public BlockState get(int layer, double x, double y, double z) {
public BlockState get(int layer, double x, double y, double z, long seed) {
return item;
}
}

View File

@ -39,7 +39,7 @@ public class StructurePopulator implements TerraGenerationStage, Chunkified {
for(ConfiguredStructure conf : config.getRegistry(TerraStructure.class).entries()) {
Vector3 spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed());
if(!provider.getBiome(spawn).getContext().get(BiomeStructures.class).getStructures().contains(conf)) {
if(!provider.getBiome(spawn, world.getSeed()).getContext().get(BiomeStructures.class).getStructures().contains(conf)) {
continue;
}
Random random = new Random(PopulationUtil.getCarverChunkSeed(FastMath.floorDiv(spawn.getBlockX(), 16), FastMath.floorDiv(spawn.getBlockZ(), 16), world.getSeed()));

View File

@ -25,13 +25,14 @@ public class FeatureGenerationStage implements TerraGenerationStage {
try(ProfileFrame ignore = main.getProfiler().profile("feature")) {
int cx = chunk.getX() << 4;
int cz = chunk.getZ() << 4;
long seed = world.getSeed();
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
int tx = cx + x;
int tz = cz + z;
ColumnImpl column = new ColumnImpl(tx, tz, world);
terraWorld.getBiomeProvider().getBiome(tx, tz).getContext().get(BiomeFeatures.class).getFeatures().forEach(feature -> {
if(feature.getDistributor().matches(tx, tz)) {
terraWorld.getBiomeProvider().getBiome(tx, tz, seed).getContext().get(BiomeFeatures.class).getFeatures().forEach(feature -> {
if(feature.getDistributor().matches(tx, tz, seed)) {
feature.getLocator()
.getSuitableCoordinates(column)
.forEach(y ->

View File

@ -33,12 +33,13 @@ public class FloraGenerationStage implements TerraGenerationStage {
try(ProfileFrame ignore = main.getProfiler().profile("flora")) {
if(tw.getConfig().disableFlora()) return;
long seed = world.getSeed();
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++) {
Vector2 l = new Vector2(x, z);
layers.put(l, provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z).getContext().get(BiomeFlora.class).getLayers());
layers.put(l, provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, seed).getContext().get(BiomeFlora.class).getLayers());
}
}

View File

@ -39,7 +39,7 @@ public class FloraLayer {
public void place(Chunk chunk, Vector2 coords) {
int cx = (chunk.getX() << 4);
int cz = (chunk.getZ() << 4);
Flora item = layer.get(noise, cx + coords.getX(), cz + coords.getZ());
Flora item = layer.get(noise, cx + coords.getX(), cz + coords.getZ(), chunk.getWorld().getSeed());
item.getValidSpawnsAt(chunk, (int) coords.getX(), (int) coords.getZ(), level).forEach(block -> item.plant(block.add(cx, 0, cz), chunk.getWorld()));
}
}

View File

@ -40,7 +40,7 @@ public class TreeLayer {
}
public void place(Chunk chunk, Vector2 coords) {
Tree item = layer.get(noise, coords.getX(), coords.getZ());
Tree item = layer.get(noise, coords.getX(), coords.getZ(), chunk.getWorld().getSeed());
BlockState current;
int cx = (chunk.getX()) << 4;
int cz = (chunk.getZ()) << 4;

View File

@ -35,9 +35,10 @@ public class TreePopulator implements TerraGenerationStage {
BiomeProvider provider = tw.getBiomeProvider();
Random random = PopulationUtil.getRandom(chunk);
long seed = world.getSeed();
for(int x = 0; x < 16; x += 2) {
for(int z = 0; z < 16; z += 2) {
for(TreeLayer layer : provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z).getContext().get(BiomeTrees.class).getTrees()) {
for(TreeLayer layer : provider.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, seed).getContext().get(BiomeTrees.class).getTrees()) {
if(layer.getDensity() >= random.nextDouble() * 100) {
layer.place(chunk, new Vector2(offset(random, x), offset(random, z)));
}

View File

@ -40,7 +40,7 @@ public class BiomeFunction implements Function<String> {
BiomeProvider grid = main.getWorld(arguments.getWorld()).getBiomeProvider();
return grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ())))).getID();
return grid.getBiome(arguments.getBuffer().getOrigin().clone().add(new Vector3(FastMath.roundToInt(xz.getX()), y.apply(implementationArguments, variableMap).intValue(), FastMath.roundToInt(xz.getZ()))), arguments.getWorld().getSeed()).getID();
}

View File

@ -13,7 +13,7 @@ configureDependencies()
group = "com.dfsek.terra.common"
dependencies {
"shadedApi"("com.dfsek:Paralithic:0.3.2")
"shadedApi"("com.dfsek:Paralithic:0.4.0")
"shadedApi"("com.dfsek.tectonic:common:2.1.1")
"shadedApi"("com.dfsek.tectonic:yaml:2.1.1")

View File

@ -8,50 +8,26 @@ public interface NoiseSampler {
static NoiseSampler zero() {
return new NoiseSampler() {
@Override
public double getNoise(double x, double y) {
public double getNoiseSeeded(long seed, double x, double y) {
return 0;
}
@Override
public double getNoise(double x, double y, double z) {
return 0;
}
@Override
public double getNoiseSeeded(int seed, double x, double y) {
return 0;
}
@Override
public double getNoiseSeeded(int seed, double x, double y, double z) {
public double getNoiseSeeded(long seed, double x, double y, double z) {
return 0;
}
};
}
/**
* 2D noise at given position using current settings
* <p>
* Noise output bounded between -1...1
*/
double getNoise(double x, double y);
/**
* 3D noise at given position using current settings
* <p>
* Noise output bounded between -1...1
*/
double getNoise(double x, double y, double z);
default double getNoise(Vector3 vector3) {
return getNoise(vector3.getX(), vector3.getY(), vector3.getZ());
default double getNoiseSeeded(Vector3 vector3, long seed) {
return getNoiseSeeded(seed, vector3.getX(), vector3.getY(), vector3.getZ());
}
default double getNoise(Vector2 vector2) {
return getNoise(vector2.getX(), vector2.getZ());
default double getNoiseSeeded(Vector2 vector2, long seed) {
return getNoiseSeeded(seed, vector2.getX(), vector2.getZ());
}
double getNoiseSeeded(int seed, double x, double y);
double getNoiseSeeded(long seed, double x, double y);
double getNoiseSeeded(int seed, double x, double y, double z);
double getNoiseSeeded(long seed, double x, double y, double z);
}

View File

@ -1,13 +1,13 @@
package com.dfsek.terra.api.structure.feature;
public interface Distributor {
boolean matches(int x, int z);
boolean matches(int x, int z, long seed);
default Distributor and(Distributor other) {
return (x, z) -> this.matches(x, z) && other.matches(x, z);
return (x, z, seed) -> this.matches(x, z, seed) && other.matches(x, z, seed);
}
default Distributor or(Distributor other) {
return (x, z) -> this.matches(x, z) || other.matches(x, z);
return (x, z, seed) -> this.matches(x, z, seed) || other.matches(x, z, seed);
}
}

View File

@ -38,15 +38,15 @@ public class ProbabilityCollection<E> implements Collection<E> {
}
@SuppressWarnings("unchecked")
public E get(NoiseSampler n, double x, double y, double z) {
public E get(NoiseSampler n, double x, double y, double z, long seed) {
if(array.length == 0) return null;
return (E) array[MathUtil.normalizeIndex(n.getNoise(x, y, z), array.length)];
return (E) array[MathUtil.normalizeIndex(n.getNoiseSeeded(seed, x, y, z), array.length)];
}
@SuppressWarnings("unchecked")
public E get(NoiseSampler n, double x, double z) {
public E get(NoiseSampler n, double x, double z, long seed) {
if(array.length == 0) return null;
return (E) array[MathUtil.normalizeIndex(n.getNoise(x, z), array.length)];
return (E) array[MathUtil.normalizeIndex(n.getNoiseSeeded(seed, x, z), array.length)];
}
@SuppressWarnings("unchecked")
@ -183,12 +183,12 @@ public class ProbabilityCollection<E> implements Collection<E> {
}
@Override
public T get(NoiseSampler n, double x, double y, double z) {
public T get(NoiseSampler n, double x, double y, double z, long seed) {
return single;
}
@Override
public T get(NoiseSampler n, double x, double z) {
public T get(NoiseSampler n, double x, double z, long seed) {
return single;
}

View File

@ -5,18 +5,13 @@ import com.dfsek.terra.api.vector.Vector3;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeProvider {
TerraBiome getBiome(int x, int z);
TerraBiome getBiome(int x, int z, long seed);
default TerraBiome getBiome(Vector2 vector2) {
return getBiome(vector2.getBlockX(), vector2.getBlockZ());
default TerraBiome getBiome(Vector2 vector2, long seed) {
return getBiome(vector2.getBlockX(), vector2.getBlockZ(), seed);
}
default TerraBiome getBiome(Vector3 vector3) {
return getBiome(vector3.getBlockX(), vector3.getBlockZ());
}
@Deprecated
enum Type {
IMAGE, PIPELINE, SINGLE
default TerraBiome getBiome(Vector3 vector3, long seed) {
return getBiome(vector3.getBlockX(), vector3.getBlockZ(), seed);
}
}

View File

@ -3,7 +3,7 @@ package com.dfsek.terra.api.world.biome.generation.pipeline;
import com.dfsek.terra.api.world.biome.TerraBiome;
public interface BiomeSource {
TerraBiome getBiome(double x, double z);
TerraBiome getBiome(double x, double z, long seed);
enum Type {
NOISE

View File

@ -15,7 +15,7 @@ public interface Palette {
* @param layer - The layer at which to fetch the material.
* @return BlockData - The material fetched.
*/
BlockState get(int layer, double x, double y, double z);
BlockState get(int layer, double x, double y, double z, long seed);
int getSize();
}

View File

@ -53,7 +53,7 @@ public class TerraBiomeSource extends BiomeSource {
@Override
public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) {
TerraBiome biome = grid.getBiome(biomeX << 2, biomeZ << 2);
TerraBiome biome = grid.getBiome(biomeX << 2, biomeZ << 2, seed);
return biomeRegistry.get(new Identifier("terra", FabricUtil.createBiomeID(pack, biome.getID())));
}
}