remove more random

This commit is contained in:
Zoë
2022-08-21 14:29:57 -05:00
parent b044b2c48e
commit b5d081fde4
25 changed files with 236 additions and 318 deletions
@@ -54,8 +54,7 @@ public class StructureCommandAddon implements MonadAddonInitializer {
structure.generate( structure.generate(
sender.position().toInt(), sender.position().toInt(),
sender.world(), sender.world(),
context.get("rotation"), sender.world().getSeed() context.get("rotation"));
);
}) })
.permission("terra.structures.generate") .permission("terra.structures.generate")
); );
@@ -14,7 +14,7 @@ import java.util.function.Supplier;
import com.dfsek.terra.addons.feature.distributor.config.AndDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.AndDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.NoDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.NoDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.OrDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.OrDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.PaddedGridDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.PaddedGridSamplerDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.PointSetDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.PointSetDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.SamplerDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.SamplerDistributorTemplate;
import com.dfsek.terra.addons.feature.distributor.config.XorDistributorTemplate; import com.dfsek.terra.addons.feature.distributor.config.XorDistributorTemplate;
@@ -25,11 +25,8 @@ import com.dfsek.terra.addons.manifest.api.MonadAddonInitializer;
import com.dfsek.terra.addons.manifest.api.monad.Do; import com.dfsek.terra.addons.manifest.api.monad.Do;
import com.dfsek.terra.addons.manifest.api.monad.Get; import com.dfsek.terra.addons.manifest.api.monad.Get;
import com.dfsek.terra.addons.manifest.api.monad.Init; import com.dfsek.terra.addons.manifest.api.monad.Init;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.inject.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structure.feature.Distributor; import com.dfsek.terra.api.structure.feature.Distributor;
import com.dfsek.terra.api.util.function.monad.Monad; import com.dfsek.terra.api.util.function.monad.Monad;
@@ -54,7 +51,7 @@ public class DistributorAddon implements MonadAddonInitializer {
distributorRegistry.register(base.key("SAMPLER"), SamplerDistributorTemplate::new); distributorRegistry.register(base.key("SAMPLER"), SamplerDistributorTemplate::new);
distributorRegistry.register(base.key("POINTS"), PointSetDistributorTemplate::new); distributorRegistry.register(base.key("POINTS"), PointSetDistributorTemplate::new);
distributorRegistry.register(base.key("PADDED_GRID"), PaddedGridDistributorTemplate::new); distributorRegistry.register(base.key("PADDED_GRID_SAMPLER"), PaddedGridSamplerDistributorTemplate::new);
distributorRegistry.register(base.key("AND"), AndDistributorTemplate::new); distributorRegistry.register(base.key("AND"), AndDistributorTemplate::new);
distributorRegistry.register(base.key("OR"), OrDistributorTemplate::new); distributorRegistry.register(base.key("OR"), OrDistributorTemplate::new);
distributorRegistry.register(base.key("XOR"), XorDistributorTemplate::new); distributorRegistry.register(base.key("XOR"), XorDistributorTemplate::new);
@@ -3,23 +3,24 @@ package com.dfsek.terra.addons.feature.distributor.config;
import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.distributor.distributors.PaddedGridDistributor; import com.dfsek.terra.addons.feature.distributor.distributors.PaddedGridSamplerDistributor;
import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.structure.feature.Distributor; import com.dfsek.terra.api.structure.feature.Distributor;
public class PaddedGridDistributorTemplate implements ObjectTemplate<Distributor> { public class PaddedGridSamplerDistributorTemplate implements ObjectTemplate<Distributor> {
@Value("width") @Value("width")
private @Meta int width; private @Meta int width;
@Value("padding") @Value("padding")
private @Meta int padding; private @Meta int padding;
@Value("salt") @Value("sampler")
private @Meta int salt; private @Meta NoiseSampler noise;
@Override @Override
public Distributor get() { public Distributor get() {
return new PaddedGridDistributor(width, padding, salt); return new PaddedGridSamplerDistributor(noise, width, padding);
} }
} }
@@ -1,47 +0,0 @@
package com.dfsek.terra.addons.feature.distributor.distributors;
import net.jafama.FastMath;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.structure.feature.Distributor;
import com.dfsek.terra.api.util.MathUtil;
public class PaddedGridDistributor implements Distributor {
private final int width;
private final int cellWidth;
private final int salt;
public PaddedGridDistributor(int width, int padding, int salt) {
this.width = width;
this.salt = salt;
this.cellWidth = width + padding;
}
private static long murmur64(long h) {
h ^= h >>> 33;
h *= 0xff51afd7ed558ccdL;
h ^= h >>> 33;
h *= 0xc4ceb9fe1a85ec53L;
h ^= h >>> 33;
return h;
}
@Override
public boolean matches(int x, int z, long seed) {
int cellX = FastMath.floorDiv(x, cellWidth);
int cellZ = FastMath.floorDiv(z, cellWidth);
RandomGenerator random = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(
(murmur64(MathUtil.squash(cellX, cellZ)) ^ seed) + salt);
int pointX = random.nextInt(width) + cellX * cellWidth;
int pointZ = random.nextInt(width) + cellZ * cellWidth;
return x == pointX && z == pointZ;
}
}
@@ -0,0 +1,36 @@
package com.dfsek.terra.addons.feature.distributor.distributors;
import com.dfsek.terra.api.noise.NoiseSampler;
import net.jafama.FastMath;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.structure.feature.Distributor;
import com.dfsek.terra.api.util.MathUtil;
public class PaddedGridSamplerDistributor implements Distributor {
private final NoiseSampler sampler;
private final int width;
private final int cellWidth;
public PaddedGridSamplerDistributor(NoiseSampler sampler, int width, int padding) {
this.sampler = sampler;
this.width = width;
this.cellWidth = width + padding;
}
@Override
public boolean matches(int x, int z, long seed) {
int cellX = FastMath.floorDiv(x, cellWidth);
int cellZ = FastMath.floorDiv(z, cellWidth);
int pointX = (int) (FastMath.round(MathUtil.lerp(MathUtil.inverseLerp(sampler.noise(x, z, seed), -1, 1), 0, width)) + cellX * cellWidth);
int pointZ = (int) (FastMath.round(MathUtil.lerp(MathUtil.inverseLerp(sampler.noise(x, z, seed + 1), -1, 1), 0, width)) + cellZ * cellWidth);
return x == pointX && z == pointZ;
}
}
@@ -74,7 +74,7 @@ public class TerraFlora implements Structure {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation) {
boolean doRotation = testRotation.size() > 0; boolean doRotation = testRotation.size() > 0;
int size = layers.size(); int size = layers.size();
int c = ceiling ? -1 : 1; int c = ceiling ? -1 : 1;
@@ -86,7 +86,7 @@ public class TerraFlora implements Structure {
for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor
int lvl = (FastMath.abs(i)); int lvl = (FastMath.abs(i));
BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(), BlockState data = getStateCollection((ceiling ? lvl : size - lvl - 1)).get(distribution, location.getX(), location.getY(),
location.getZ(), seed); location.getZ(), world.getSeed());
world.setBlockState(location.mutable().add(0, i + c, 0).immutable(), data, physics); world.setBlockState(location.mutable().add(0, i + c, 0).immutable(), data, physics);
} }
@@ -13,10 +13,8 @@ import java.util.function.Supplier;
import com.dfsek.terra.addons.feature.locator.config.AdjacentPatternLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.AdjacentPatternLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.AndLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.AndLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.GaussianRandomLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.OrLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.OrLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.PatternLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.PatternLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.RandomLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.Sampler3DLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.Sampler3DLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.SamplerLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.SamplerLocatorTemplate;
import com.dfsek.terra.addons.feature.locator.config.SurfaceLocatorTemplate; import com.dfsek.terra.addons.feature.locator.config.SurfaceLocatorTemplate;
@@ -35,11 +33,8 @@ import com.dfsek.terra.addons.manifest.api.MonadAddonInitializer;
import com.dfsek.terra.addons.manifest.api.monad.Do; import com.dfsek.terra.addons.manifest.api.monad.Do;
import com.dfsek.terra.addons.manifest.api.monad.Get; import com.dfsek.terra.addons.manifest.api.monad.Get;
import com.dfsek.terra.addons.manifest.api.monad.Init; import com.dfsek.terra.addons.manifest.api.monad.Init;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.inject.annotations.Inject;
import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.function.monad.Monad; import com.dfsek.terra.api.util.function.monad.Monad;
@@ -66,9 +61,6 @@ public class LocatorAddon implements MonadAddonInitializer {
locatorRegistry.register(base.key("SURFACE"), SurfaceLocatorTemplate::new); locatorRegistry.register(base.key("SURFACE"), SurfaceLocatorTemplate::new);
locatorRegistry.register(base.key("TOP"), TopLocatorTemplate::new); locatorRegistry.register(base.key("TOP"), TopLocatorTemplate::new);
locatorRegistry.register(base.key("RANDOM"), RandomLocatorTemplate::new);
locatorRegistry.register(base.key("GAUSSIAN_RANDOM"), GaussianRandomLocatorTemplate::new);
locatorRegistry.register(base.key("PATTERN"), PatternLocatorTemplate::new); locatorRegistry.register(base.key("PATTERN"), PatternLocatorTemplate::new);
locatorRegistry.register(base.key("ADJACENT_PATTERN"), AdjacentPatternLocatorTemplate::new); locatorRegistry.register(base.key("ADJACENT_PATTERN"), AdjacentPatternLocatorTemplate::new);
@@ -1,39 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in this module's root directory.
*/
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.locators.GaussianRandomLocator;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
@SuppressWarnings("FieldMayBeFinal")
public class GaussianRandomLocatorTemplate implements ObjectTemplate<Locator> {
@Value("height")
private @Meta Range height;
@Value("amount")
private @Meta Range amount;
@Value("standard-deviation")
private @Meta double standardDeviation;
@Value("salt")
@Default
private @Meta int salt = 0;
@Override
public Locator get() {
return new GaussianRandomLocator(height, amount, standardDeviation, salt);
}
}
@@ -1,36 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in this module's root directory.
*/
package com.dfsek.terra.addons.feature.locator.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.dfsek.terra.addons.feature.locator.locators.RandomLocator;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
@SuppressWarnings("FieldMayBeFinal")
public class RandomLocatorTemplate implements ObjectTemplate<Locator> {
@Value("height")
private @Meta Range height;
@Value("amount")
private @Meta Range amount;
@Value("salt")
@Default
private @Meta int salt = 0;
@Override
public Locator get() {
return new RandomLocator(height, amount, salt);
}
}
@@ -1,58 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in this module's root directory.
*/
package com.dfsek.terra.addons.feature.locator.locators;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.chunk.generation.util.Column;
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
public class GaussianRandomLocator implements Locator {
private final double mean;
private final Range points;
private final double standardDeviation;
private final int salt;
public GaussianRandomLocator(Range height, Range points, double standardDeviation, int salt) {
this.mean = (height.getMax() + height.getMin()) / 2.0;
this.points = points;
this.standardDeviation = standardDeviation;
this.salt = salt;
}
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
long seed = column.getWorld().getSeed();
seed = 31 * seed + column.getX();
seed = 31 * seed + column.getZ();
seed += salt;
RandomGenerator r = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(seed);
int size = points.get(r);
BinaryColumnBuilder results = column.newBinaryColumn();
for(int i = 0; i < size; i++) {
int h = (int) r.nextGaussian(mean, standardDeviation);
if(h >= column.getMaxY() || h < column.getMinY()) continue;
results.set(h);
}
return results.build();
}
}
@@ -1,53 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in this module's root directory.
*/
package com.dfsek.terra.addons.feature.locator.locators;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.structure.feature.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator;
import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.world.chunk.generation.util.Column;
import com.dfsek.terra.api.world.chunk.generation.util.Column.BinaryColumnBuilder;
public class RandomLocator implements Locator {
private final Range height;
private final Range points;
private final int salt;
public RandomLocator(Range height, Range points, int salt) {
this.height = height;
this.points = points;
this.salt = salt;
}
@Override
public BinaryColumn getSuitableCoordinates(Column<?> column) {
long seed = column.getWorld().getSeed();
seed = 31 * seed + column.getX();
seed = 31 * seed + column.getZ();
seed += salt;
RandomGenerator r = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(seed);
int size = points.get(r);
BinaryColumnBuilder results = column.newBinaryColumn();
for(int i = 0; i < size; i++) {
int h = height.get(r);
if(h >= column.getMaxY() || h < column.getMinY()) continue;
results.set(h);
}
return results.build();
}
}
@@ -47,26 +47,26 @@ public class VanillaOre implements Structure {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed){ public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation){
int centerX = location.getX(); int centerX = location.getX();
int centerZ = location.getZ(); int centerZ = location.getZ();
int centerY = location.getY(); int centerY = location.getY();
double f = sampler.noise(centerX, centerY, centerZ, seed) * (float) Math.PI; double f = sampler.noise(centerX, centerY, centerZ, world.getSeed()) * (float) Math.PI;
double d1 = centerX + 8 + FastMath.sin(f) * size / 8.0F; double d1 = centerX + 8 + FastMath.sin(f) * size / 8.0F;
double d2 = centerX + 8 - FastMath.sin(f) * size / 8.0F; double d2 = centerX + 8 - FastMath.sin(f) * size / 8.0F;
double d3 = centerZ + 8 + FastMath.cos(f) * size / 8.0F; double d3 = centerZ + 8 + FastMath.cos(f) * size / 8.0F;
double d4 = centerZ + 8 - FastMath.cos(f) * size / 8.0F; double d4 = centerZ + 8 - FastMath.cos(f) * size / 8.0F;
double d5 = centerY + (Math.round(sampler.noise(centerX, centerY, centerZ, seed + 1) + 1)) - 2D; double d5 = centerY + (Math.round(sampler.noise(centerX, centerY, centerZ, world.getSeed() + 1) + 1)) - 2D;
double d6 = centerY + (Math.round(sampler.noise(centerX, centerY, centerZ, seed + 2) + 1)) - 2D; double d6 = centerY + (Math.round(sampler.noise(centerX, centerY, centerZ, world.getSeed() + 2) + 1)) - 2D;
for(int i = 0; i < size; i++) { for(int i = 0; i < size; i++) {
float iFactor = (float) i / (float) size; float iFactor = (float) i / (float) size;
double d10 = MathUtil.inverseLerp(sampler.noise(centerX, centerY, centerZ, seed + 2 + (i * 2 - 1)), -1, 1) * size / 16.0D; double d10 = MathUtil.inverseLerp(sampler.noise(centerX, centerY, centerZ, world.getSeed() + 2 + (i * 2 - 1)), -1, 1) * size / 16.0D;
double d11 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; double d11 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0;
double d12 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0; double d12 = (FastMath.sin(Math.PI * iFactor) + 1.0) * d10 + 1.0;
@@ -90,7 +90,7 @@ public class VanillaOre implements Structure {
if(y >= world.getMaxHeight() || y < world.getMinHeight()) continue; if(y >= world.getMaxHeight() || y < world.getMinHeight()) continue;
BlockType block = world.getBlockState(x, y, z).getBlockType(); BlockType block = world.getBlockState(x, y, z).getBlockType();
if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(block)) { if((d13 * d13 + d14 * d14 + d15 * d15 < 1.0D) && getReplaceable().contains(block)) {
if(exposed > MathUtil.inverseLerp(sampler.noise(centerX, centerY, centerZ, seed + 2 + (i * 2)), -1, 1) || !(world.getBlockState(x, y, z - 1).isAir() || if(exposed > MathUtil.inverseLerp(sampler.noise(centerX, centerY, centerZ, world.getSeed() + 2 + (i * 2)), -1, 1) || !(world.getBlockState(x, y, z - 1).isAir() ||
world.getBlockState(x, y, z + 1).isAir() || world.getBlockState(x, y, z + 1).isAir() ||
world.getBlockState(x, y - 1, z).isAir() || world.getBlockState(x, y - 1, z).isAir() ||
world.getBlockState(x, y + 1, z).isAir() || world.getBlockState(x, y + 1, z).isAir() ||
@@ -59,7 +59,6 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) { for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) {
int x = subChunkX + tx; int x = subChunkX + tx;
int z = subChunkZ + tz; int z = subChunkZ + tz;
long coordinateSeed = (seed * 31 + x) * 31 + z;
Column<WritableWorld> column = world.column(x, z); Column<WritableWorld> column = world.column(x, z);
biome.getContext() biome.getContext()
.get(biomeFeaturesKey) .get(biomeFeaturesKey)
@@ -73,8 +72,7 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
.forEach(y -> feature.getStructure(world, x, y, z) .forEach(y -> feature.getStructure(world, x, y, z)
.generate(Vector3Int.of(x, y, z), .generate(Vector3Int.of(x, y, z),
world, world,
Rotation.NONE, Rotation.NONE)
coordinateSeed * 31 + y)
); );
} }
platform.getProfiler().pop(feature.getID()); platform.getProfiler().pop(feature.getID());
@@ -17,7 +17,7 @@ public class SingletonStructure implements Structure {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation) {
world.setBlockState(location, blockState); world.setBlockState(location, blockState);
return true; return true;
} }
@@ -32,12 +32,12 @@ public class MutatedStructure implements Structure, Keyed<MutatedStructure> {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation) {
return base.generate(location, return base.generate(location,
world world
.buffer() .buffer()
.read(readInterceptor) .read(readInterceptor)
.write(writeInterceptor) .write(writeInterceptor)
.build(), rotation, seed); .build(), rotation);
} }
} }
@@ -31,7 +31,7 @@ public class SpongeStructure implements Structure, Keyed<SpongeStructure> {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation) {
int bX = location.getX(); int bX = location.getX();
int bY = location.getY(); int bY = location.getY();
int bZ = location.getZ(); int bZ = location.getZ();
@@ -128,7 +128,7 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
@Override @Override
@SuppressWarnings("try") @SuppressWarnings("try")
public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation) {
platform.getProfiler().push(profile); platform.getProfiler().push(profile);
boolean result = applyBlock(new TerraImplementationArguments(location, rotation, world, 0)); boolean result = applyBlock(new TerraImplementationArguments(location, rotation, world, 0));
platform.getProfiler().pop(profile); platform.getProfiler().pop(profile);
@@ -85,9 +85,7 @@ public class LootFunction implements Function<Void> {
platform.getEventManager().callEvent(event); platform.getEventManager().callEvent(event);
if(event.isCancelled()) return; if(event.isCancelled()) return;
event.getTable().fillInventory(container.getInventory(), event.getTable().fillInventory(container.getInventory());
RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of(
"Xoroshiro128PlusPlus").create(apply.hashCode()));
data.update(false); data.update(false);
} catch(Exception e) { } catch(Exception e) {
LOGGER.error("Could not apply loot at {}", apply, e); LOGGER.error("Could not apply loot at {}", apply, e);
@@ -80,7 +80,7 @@ public class StructureFunction implements Function<Boolean> {
.buffer(FastMath.roundToInt(xz.getX()), .buffer(FastMath.roundToInt(xz.getX()),
y.apply(implementationArguments, scope).intValue(), y.apply(implementationArguments, scope).intValue(),
FastMath.roundToInt(xz.getZ())), FastMath.roundToInt(xz.getZ())),
arguments.getRotation(), arguments.getWorld().getSeed()); arguments.getRotation());
}).orElseGet(() -> { }).orElseGet(() -> {
LOGGER.error("No such structure {}", app); LOGGER.error("No such structure {}", app);
return false; return false;
@@ -22,9 +22,8 @@ public interface LootTable {
* Fills an Inventory with loot. * Fills an Inventory with loot.
* *
* @param i The Inventory to fill. * @param i The Inventory to fill.
* @param r The The RandomGenerator instance to use.
*/ */
void fillInventory(Inventory i, RandomGenerator r); void fillInventory(Inventory i);
/** /**
* Fetches a list of ItemStacks from the loot table using the given RandomGenerator instance. * Fetches a list of ItemStacks from the loot table using the given RandomGenerator instance.
@@ -16,5 +16,5 @@ import com.dfsek.terra.api.world.WritableWorld;
public interface Structure { public interface Structure {
boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long Seed); boolean generate(Vector3Int location, WritableWorld world, Rotation rotation);
} }
@@ -1,39 +0,0 @@
/*
* Copyright (c) 2020-2021 Polyhedral Development
*
* The Terra API is licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in the common/api directory.
*/
package com.dfsek.terra.api.util;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.world.chunk.Chunk;
public final class PopulationUtil {
public static RandomGenerator getRandom(Chunk c) {
return getRandom(c, 0);
}
public static RandomGenerator getRandom(Chunk c, long salt) {
return RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(
getCarverChunkSeed(c.getX(), c.getZ(), c.getWorld().getSeed() + salt));
}
/**
* Gets the carver seed for a chunk.
*
* @param chunkX Chunk's X coordinate
* @param chunkZ Chunk's Z coordinate
* @param seed World seed
*
* @return long - The carver seed.
*/
public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) {
RandomGenerator r = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(seed);
return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed;
}
}
@@ -3,6 +3,8 @@ package com.dfsek.terra.mod.mixin.gameplay;
import com.dfsek.terra.api.world.World; import com.dfsek.terra.api.world.World;
import com.dfsek.terra.mod.util.WritableWorldSeedRedirecter;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.ai.brain.task.BoneMealTask; import net.minecraft.entity.ai.brain.task.BoneMealTask;
@@ -45,7 +47,7 @@ public class BoneMealTaskMixin {
if(canGrow != null) { if(canGrow != null) {
RandomGenerator random = MinecraftAdapter.adapt(world.getRandom()); RandomGenerator random = MinecraftAdapter.adapt(world.getRandom());
cir.setReturnValue(canGrow.generate( cir.setReturnValue(canGrow.generate(
Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, Rotation.NONE, world.getSeed() + random.nextLong(Long.MAX_VALUE))); Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), new WritableWorldSeedRedirecter((WritableWorld) world, world.getSeed() + random.nextLong(Long.MAX_VALUE)), Rotation.NONE));
return; return;
} }
cir.setReturnValue(true); cir.setReturnValue(true);
@@ -27,7 +27,7 @@ public class FertilizableUtil {
Structure canGrow = config.getCanGrow(); Structure canGrow = config.getCanGrow();
if(canGrow != null) { if(canGrow != null) {
if(!canGrow.generate( if(!canGrow.generate(
Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, Rotation.NONE, world.getSeed() + random.nextLong(Long.MAX_VALUE))) { Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), new WritableWorldSeedRedirecter((WritableWorld) world, world.getSeed() + random.nextLong(Long.MAX_VALUE)), Rotation.NONE)) {
return false; return false;
} }
} }
@@ -38,7 +38,7 @@ public class FertilizableUtil {
} }
} }
config.getStructures().get(random).generate( config.getStructures().get(random).generate(
Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, Rotation.NONE, world.getSeed() + random.nextLong(Long.MAX_VALUE)); Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), new WritableWorldSeedRedirecter((WritableWorld) world, world.getSeed() + random.nextLong(Long.MAX_VALUE)), Rotation.NONE);
return true; return true;
} }
} }
@@ -0,0 +1,168 @@
package com.dfsek.terra.mod.util;
import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.util.vector.Vector3.Mutable;
import com.dfsek.terra.api.util.vector.Vector3Int;
import com.dfsek.terra.api.world.BufferedWorld;
import com.dfsek.terra.api.world.BufferedWorld.Builder;
import com.dfsek.terra.api.world.WritableWorld;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.util.Column;
public class WritableWorldSeedRedirecter implements WritableWorld {
private final WritableWorld delegate;
private final long seed;
public WritableWorldSeedRedirecter(WritableWorld delegate, long seed) {
this.delegate = delegate;
this.seed = seed;
}
@Override
public Object getHandle() {
return delegate.getHandle();
}
@Override
public BlockState getBlockState(int x, int y, int z) {
return delegate.getBlockState(x, y, z);
}
@Override
public BlockState getBlockState(Vector3 position) {
return delegate.getBlockState(position);
}
@Override
public BlockState getBlockState(Vector3Int position) {
return delegate.getBlockState(position);
}
@Override
public BlockEntity getBlockEntity(int x, int y, int z) {
return delegate.getBlockEntity(x, y, z);
}
@Override
public BlockEntity getBlockEntity(Vector3 position) {
return delegate.getBlockEntity(position);
}
@Override
public BlockEntity getBlockEntity(Vector3Int position) {
return delegate.getBlockEntity(position);
}
@Override
public ChunkGenerator getGenerator() {
return delegate.getGenerator();
}
@Override
public BiomeProvider getBiomeProvider() {
return delegate.getBiomeProvider();
}
@Override
public ConfigPack getPack() {
return delegate.getPack();
}
@Override
public void setBlockState(Vector3 position, BlockState data, boolean physics) {
delegate.setBlockState(position, data, physics);
}
@Override
public void setBlockState(Mutable position, BlockState data, boolean physics) {
delegate.setBlockState(position, data, physics);
}
@Override
public void setBlockState(Vector3Int position, BlockState data, boolean physics) {
delegate.setBlockState(position, data, physics);
}
@Override
public void setBlockState(Vector3Int.Mutable position, BlockState data, boolean physics) {
delegate.setBlockState(position, data, physics);
}
@Override
public void setBlockState(Vector3 position, BlockState data) {
delegate.setBlockState(position, data);
}
@Override
public void setBlockState(Mutable position, BlockState data) {
delegate.setBlockState(position, data);
}
@Override
public void setBlockState(Vector3Int position, BlockState data) {
delegate.setBlockState(position, data);
}
@Override
public void setBlockState(Vector3Int.Mutable position, BlockState data) {
delegate.setBlockState(position, data);
}
@Override
public void setBlockState(int x, int y, int z, BlockState data) {
delegate.setBlockState(x, y, z, data);
}
@Override
public void setBlockState(int x, int y, int z, BlockState data, boolean physics) {
delegate.setBlockState(x, y, z, data, physics);
}
@Override
public Entity spawnEntity(Vector3 location, EntityType entityType) {
return delegate.spawnEntity(location, entityType);
}
@Override
public Entity spawnEntity(double x, double y, double z, EntityType entityType) {
return delegate.spawnEntity(x, y, z, entityType);
}
@Override
public BufferedWorld buffer(int offsetX, int offsetY, int offsetZ) {
return delegate.buffer(offsetX, offsetY, offsetZ);
}
@Override
public Builder buffer() {
return delegate.buffer();
}
@Override
public Column<WritableWorld> column(int x, int z) {
return delegate.column(x, z);
}
@Override
public long getSeed() {
return seed;
}
@Override
public int getMaxHeight() {
return delegate.getMaxHeight();
}
@Override
public int getMinHeight() {
return delegate.getMinHeight();
}
}