terraScript random is no more

This commit is contained in:
Zoë
2022-08-19 23:18:42 -05:00
parent e658a5d917
commit 5d5408e142
22 changed files with 84 additions and 176 deletions
@@ -7,6 +7,9 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation;
import com.dfsek.terra.api.util.MathUtil;
/** /**
* Class for bilinear interpolation of values arranged on a unit square. * Class for bilinear interpolation of values arranged on a unit square.
*/ */
@@ -28,19 +31,6 @@ public class Interpolator {
this.v3 = v3; this.v3 = v3;
} }
/**
* 1D Linear interpolation between 2 points 1 unit apart.
*
* @param t - Distance from v0. Total distance between v0 and v1 is 1 unit.
* @param v0 - Value at v0.
* @param v1 - Value at v1.
*
* @return double - The interpolated value.
*/
public static double lerp(double t, double v0, double v1) {
return v0 + t * (v1 - v0);
}
/** /**
* 2D Bilinear interpolation between 4 points on a unit square. * 2D Bilinear interpolation between 4 points on a unit square.
* *
@@ -50,8 +40,8 @@ public class Interpolator {
* @return double - The interpolated value. * @return double - The interpolated value.
*/ */
public double bilerp(double s, double t) { public double bilerp(double s, double t) {
double v01 = lerp(s, v0, v1); double v01 = MathUtil.lerp(s, v0, v1);
double v23 = lerp(s, v2, v3); double v23 = MathUtil.lerp(s, v2, v3);
return lerp(t, v01, v23); return MathUtil.lerp(t, v01, v23);
} }
} }
@@ -7,6 +7,9 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation;
import com.dfsek.terra.api.util.MathUtil;
/** /**
* Class for bilinear interpolation of values arranged on a unit square. * Class for bilinear interpolation of values arranged on a unit square.
*/ */
@@ -34,6 +37,6 @@ public class Interpolator3 {
} }
public double trilerp(double x, double y, double z) { public double trilerp(double x, double y, double z) {
return Interpolator.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z)); return MathUtil.lerp(x, top.bilerp(y, z), bottom.bilerp(y, z));
} }
} }
@@ -1,13 +1,13 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation; package com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation;
import com.dfsek.terra.api.util.MathUtil;
import net.jafama.FastMath; import net.jafama.FastMath;
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.properties.PropertyKey;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import static com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.Interpolator.lerp;
public class LazilyEvaluatedInterpolator { public class LazilyEvaluatedInterpolator {
private final Double[] samples; // private final Double[] samples; //
@@ -84,10 +84,10 @@ public class LazilyEvaluatedInterpolator {
double xFrac = (double) (x % horizontalRes) / horizontalRes; double xFrac = (double) (x % horizontalRes) / horizontalRes;
double zFrac = (double) (z % horizontalRes) / horizontalRes; double zFrac = (double) (z % horizontalRes) / horizontalRes;
double lerp_bottom_0 = lerp(zFrac, sample_0_0_0, sample_0_0_1); double lerp_bottom_0 = MathUtil.lerp(zFrac, sample_0_0_0, sample_0_0_1);
double lerp_bottom_1 = lerp(zFrac, sample_1_0_0, sample_1_0_1); double lerp_bottom_1 = MathUtil.lerp(zFrac, sample_1_0_0, sample_1_0_1);
double lerp_bottom = lerp(xFrac, lerp_bottom_0, lerp_bottom_1); double lerp_bottom = MathUtil.lerp(xFrac, lerp_bottom_0, lerp_bottom_1);
if(yRange) { // we can do bilerp if(yRange) { // we can do bilerp
return lerp_bottom; return lerp_bottom;
@@ -103,11 +103,11 @@ public class LazilyEvaluatedInterpolator {
double sample_1_1_0 = sample(xIndex + 1, yIndex + 1, zIndex, x + horizontalRes, y + verticalRes, z); double sample_1_1_0 = sample(xIndex + 1, yIndex + 1, zIndex, x + horizontalRes, y + verticalRes, z);
double sample_1_1_1 = sample(xIndex + 1, yIndex + 1, zIndex + 1, x + horizontalRes, y + verticalRes, z + horizontalRes); double sample_1_1_1 = sample(xIndex + 1, yIndex + 1, zIndex + 1, x + horizontalRes, y + verticalRes, z + horizontalRes);
double lerp_top_0 = lerp(zFrac, sample_0_1_0, sample_0_1_1); double lerp_top_0 = MathUtil.lerp(zFrac, sample_0_1_0, sample_0_1_1);
double lerp_top_1 = lerp(zFrac, sample_1_1_0, sample_1_1_1); double lerp_top_1 = MathUtil.lerp(zFrac, sample_1_1_0, sample_1_1_1);
double lerp_top = lerp(xFrac, lerp_top_0, lerp_top_1); double lerp_top = MathUtil.lerp(xFrac, lerp_top_0, lerp_top_1);
return lerp(yFrac, lerp_bottom, lerp_top); return MathUtil.lerp(yFrac, lerp_bottom, lerp_top);
} }
} }
@@ -6,27 +6,24 @@ import cloud.commandframework.arguments.standard.EnumArgument;
import cloud.commandframework.arguments.standard.LongArgument; import cloud.commandframework.arguments.standard.LongArgument;
import cloud.commandframework.context.CommandContext; import cloud.commandframework.context.CommandContext;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.addons.manifest.api.MonadAddonInitializer; 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.command.CommandSender; import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.command.arguments.RegistryArgument; import com.dfsek.terra.api.command.arguments.RegistryArgument;
import com.dfsek.terra.api.entity.Entity; import com.dfsek.terra.api.entity.Entity;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent;
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.Registry; import com.dfsek.terra.api.registry.Registry;
import com.dfsek.terra.api.structure.Structure; import com.dfsek.terra.api.structure.Structure;
import com.dfsek.terra.api.util.Rotation; import com.dfsek.terra.api.util.Rotation;
import com.dfsek.terra.api.util.function.monad.Monad; import com.dfsek.terra.api.util.function.monad.Monad;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
public class StructureCommandAddon implements MonadAddonInitializer { public class StructureCommandAddon implements MonadAddonInitializer {
private static Registry<Structure> getStructureRegistry(CommandContext<CommandSender> sender) { private static Registry<Structure> getStructureRegistry(CommandContext<CommandSender> sender) {
@@ -57,12 +54,7 @@ public class StructureCommandAddon implements MonadAddonInitializer {
structure.generate( structure.generate(
sender.position().toInt(), sender.position().toInt(),
sender.world(), sender.world(),
((Long) context.get("seed") == 0) context.get("rotation"), sender.world().getSeed()
? RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus")
.create()
: RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus")
.create(context.get("seed")),
context.get("rotation")
); );
}) })
.permission("terra.structures.generate") .permission("terra.structures.generate")
@@ -74,7 +74,7 @@ public class TerraFlora implements Structure {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) {
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,13 +86,8 @@ 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(), world.getSeed()); location.getZ(), seed);
if(doRotation) {
Direction oneFace = new ArrayList<>(faces).get(
RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus")
.create(location.getX() ^ location.getZ())
.nextInt(faces.size())); // Get RandomGenerator face.
}
world.setBlockState(location.mutable().add(0, i + c, 0).immutable(), data, physics); world.setBlockState(location.mutable().add(0, i + c, 0).immutable(), data, physics);
} }
return true; return true;
@@ -4,6 +4,7 @@ dependencies {
compileOnlyApi(project(":common:addons:manifest-addon-loader")) compileOnlyApi(project(":common:addons:manifest-addon-loader"))
implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) implementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama)
testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama) testImplementation("net.jafama", "jafama", Versions.Libraries.Internal.jafama)
compileOnlyApi(project(":common:addons:config-noise-function"))
} }
tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") { tasks.named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
@@ -7,6 +7,7 @@
package com.dfsek.terra.addons.ore; package com.dfsek.terra.addons.ore;
import com.dfsek.terra.addons.noise.samplers.noise.random.WhiteNoiseSampler;
import com.dfsek.terra.addons.ore.ores.VanillaOre; import com.dfsek.terra.addons.ore.ores.VanillaOre;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
@@ -19,6 +20,6 @@ public class OreFactory implements ConfigFactory<OreTemplate, Structure> {
public VanillaOre build(OreTemplate config, Platform platform) { public VanillaOre build(OreTemplate config, Platform platform) {
BlockState m = config.getMaterial(); BlockState m = config.getMaterial();
return new VanillaOre(m, config.getSize(), config.getReplaceable(), config.doPhysics(), config.isExposed(), return new VanillaOre(m, config.getSize(), config.getReplaceable(), config.doPhysics(), config.isExposed(),
config.getMaterialOverrides()); config.getMaterialOverrides(), new WhiteNoiseSampler());
} }
} }
@@ -7,10 +7,13 @@
package com.dfsek.terra.addons.ore.ores; package com.dfsek.terra.addons.ore.ores;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.MathUtil;
import net.jafama.FastMath; import net.jafama.FastMath;
import java.util.Map; import java.util.Map;
import java.util.random.RandomGenerator;
import com.dfsek.terra.api.block.BlockType; import com.dfsek.terra.api.block.BlockType;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
@@ -30,38 +33,40 @@ public class VanillaOre implements Structure {
private final boolean applyGravity; private final boolean applyGravity;
private final double exposed; private final double exposed;
private final Map<BlockType, BlockState> materials; private final Map<BlockType, BlockState> materials;
private final NoiseSampler sampler;
public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity, public VanillaOre(BlockState material, double size, MaterialSet replaceable, boolean applyGravity,
double exposed, Map<BlockType, BlockState> materials) { double exposed, Map<BlockType, BlockState> materials, NoiseSampler sampler) {
this.material = material; this.material = material;
this.size = size; this.size = size;
this.replaceable = replaceable; this.replaceable = replaceable;
this.applyGravity = applyGravity; this.applyGravity = applyGravity;
this.exposed = exposed; this.exposed = exposed;
this.materials = materials; this.materials = materials;
this.sampler = sampler;
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed){
int centerX = location.getX(); int centerX = location.getX();
int centerZ = location.getZ(); int centerZ = location.getZ();
int centerY = location.getY(); int centerY = location.getY();
float f = random.nextFloat() * (float) Math.PI; double f = sampler.noise(centerX, centerY, centerZ, seed) * (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 + random.nextInt(3) - 2D; double d5 = centerY + (Math.round(sampler.noise(centerX, centerY, centerZ, seed + 1) + 1)) - 2D;
double d6 = centerY + random.nextInt(3) - 2D; double d6 = centerY + (Math.round(sampler.noise(centerX, centerY, centerZ, seed + 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 = random.nextDouble() * size / 16.0D; double d10 = MathUtil.inverseLerp(sampler.noise(centerX, centerY, centerZ, seed + 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;
@@ -85,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 > random.nextDouble() || !(world.getBlockState(x, y, z - 1).isAir() || if(exposed > MathUtil.inverseLerp(sampler.noise(centerX, centerY, centerZ, seed + 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() ||
@@ -10,3 +10,5 @@ website:
source: https://github.com/PolyhedralDev/Terra source: https://github.com/PolyhedralDev/Terra
docs: https://terra.polydev.org docs: https://terra.polydev.org
license: MIT License license: MIT License
depends:
config-noise-function: "1.+"
@@ -73,10 +73,8 @@ 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,
RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of( Rotation.NONE,
"Xoroshiro128PlusPlus") coordinateSeed * 31 + y)
.create(coordinateSeed * 31 + y),
Rotation.NONE)
); );
} }
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, RandomGenerator random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) {
world.setBlockState(location, blockState); world.setBlockState(location, blockState);
return true; return true;
} }
@@ -32,13 +32,12 @@ public class MutatedStructure implements Structure, Keyed<MutatedStructure> {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) {
return base.generate(location, return base.generate(location,
world world
.buffer() .buffer()
.read(readInterceptor) .read(readInterceptor)
.write(writeInterceptor) .write(writeInterceptor)
.build(), .build(), rotation, seed);
random, rotation);
} }
} }
@@ -31,7 +31,7 @@ public class SpongeStructure implements Structure, Keyed<SpongeStructure> {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) {
int bX = location.getX(); int bX = location.getX();
int bY = location.getY(); int bY = location.getY();
int bZ = location.getZ(); int bZ = location.getZ();
@@ -29,7 +29,6 @@ import com.dfsek.terra.addons.terrascript.script.builders.EntityFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.GetMarkFunctionBuilder; import com.dfsek.terra.addons.terrascript.script.builders.GetMarkFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.LootFunctionBuilder; import com.dfsek.terra.addons.terrascript.script.builders.LootFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.PullFunctionBuilder; import com.dfsek.terra.addons.terrascript.script.builders.PullFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.RandomFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.RecursionsFunctionBuilder; import com.dfsek.terra.addons.terrascript.script.builders.RecursionsFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.SetMarkFunctionBuilder; import com.dfsek.terra.addons.terrascript.script.builders.SetMarkFunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.builders.StateFunctionBuilder; import com.dfsek.terra.addons.terrascript.script.builders.StateFunctionBuilder;
@@ -77,7 +76,6 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
.registerFunction("block", new BlockFunctionBuilder(platform)) .registerFunction("block", new BlockFunctionBuilder(platform))
.registerFunction("debugBlock", new BlockFunctionBuilder(platform)) .registerFunction("debugBlock", new BlockFunctionBuilder(platform))
.registerFunction("structure", new StructureFunctionBuilder(registry, platform)) .registerFunction("structure", new StructureFunctionBuilder(registry, platform))
.registerFunction("randomInt", new RandomFunctionBuilder())
.registerFunction("recursions", new RecursionsFunctionBuilder()) .registerFunction("recursions", new RecursionsFunctionBuilder())
.registerFunction("setMark", new SetMarkFunctionBuilder()) .registerFunction("setMark", new SetMarkFunctionBuilder())
.registerFunction("getMark", new GetMarkFunctionBuilder()) .registerFunction("getMark", new GetMarkFunctionBuilder())
@@ -130,16 +128,16 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
@Override @Override
@SuppressWarnings("try") @SuppressWarnings("try")
public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long seed) {
platform.getProfiler().push(profile); platform.getProfiler().push(profile);
boolean result = applyBlock(new TerraImplementationArguments(location, rotation, random, world, 0)); boolean result = applyBlock(new TerraImplementationArguments(location, rotation, world, 0));
platform.getProfiler().pop(profile); platform.getProfiler().pop(profile);
return result; return result;
} }
public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation, int recursions) { public boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, int recursions) {
platform.getProfiler().push(profile); platform.getProfiler().push(profile);
boolean result = applyBlock(new TerraImplementationArguments(location, rotation, random, world, recursions)); boolean result = applyBlock(new TerraImplementationArguments(location, rotation, world, recursions));
platform.getProfiler().pop(profile); platform.getProfiler().pop(profile);
return result; return result;
} }
@@ -20,16 +20,14 @@ import com.dfsek.terra.api.world.WritableWorld;
public class TerraImplementationArguments implements ImplementationArguments { public class TerraImplementationArguments implements ImplementationArguments {
private final Rotation rotation; private final Rotation rotation;
private final RandomGenerator random;
private final WritableWorld world; private final WritableWorld world;
private final Map<Vector3, String> marks = new HashMap<>(); private final Map<Vector3, String> marks = new HashMap<>();
private final int recursions; private final int recursions;
private final Vector3Int origin; private final Vector3Int origin;
private boolean waterlog = false; private boolean waterlog = false;
public TerraImplementationArguments(Vector3Int origin, Rotation rotation, RandomGenerator random, WritableWorld world, int recursions) { public TerraImplementationArguments(Vector3Int origin, Rotation rotation, WritableWorld world, int recursions) {
this.rotation = rotation; this.rotation = rotation;
this.random = random;
this.world = world; this.world = world;
this.recursions = recursions; this.recursions = recursions;
this.origin = origin; this.origin = origin;
@@ -39,10 +37,6 @@ public class TerraImplementationArguments implements ImplementationArguments {
return recursions; return recursions;
} }
public RandomGenerator getRandom() {
return random;
}
public Rotation getRotation() { public Rotation getRotation() {
return rotation; return rotation;
} }
@@ -1,35 +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.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.RandomFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class RandomFunctionBuilder implements FunctionBuilder<RandomFunction> {
@SuppressWarnings("unchecked")
@Override
public RandomFunction build(List<Returnable<?>> argumentList, Position position) {
return new RandomFunction((Returnable<Number>) argumentList.get(0), position);
}
@Override
public int argNumber() {
return 1;
}
@Override
public Returnable.ReturnType getArgument(int position) {
if(position == 0) return Returnable.ReturnType.NUMBER;
return null;
}
}
@@ -1,43 +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.terrascript.script.functions;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.Scope;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.Function;
import com.dfsek.terra.addons.terrascript.script.TerraImplementationArguments;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
public class RandomFunction implements Function<Integer> {
private final Returnable<Number> numberReturnable;
private final Position position;
public RandomFunction(Returnable<Number> numberReturnable, Position position) {
this.numberReturnable = numberReturnable;
this.position = position;
}
@Override
public ReturnType returnType() {
return ReturnType.NUMBER;
}
@Override
public Integer apply(ImplementationArguments implementationArguments, Scope scope) {
return ((TerraImplementationArguments) implementationArguments).getRandom().nextInt(
numberReturnable.apply(implementationArguments, scope).intValue());
}
@Override
public Position getPosition() {
return position;
}
}
@@ -67,31 +67,20 @@ public class StructureFunction implements Function<Boolean> {
String app = id.apply(implementationArguments, scope); String app = id.apply(implementationArguments, scope);
return registry.getByID(app).map(script -> { return registry.getByID(app).map(script -> {
Rotation rotation1;
String rotString = rotations.get(arguments.getRandom().nextInt(rotations.size())).apply(implementationArguments, scope);
try {
rotation1 = Rotation.valueOf(rotString);
} catch(IllegalArgumentException e) {
LOGGER.warn("Invalid rotation {}", rotString);
return false;
}
if(script instanceof StructureScript structureScript) { if(script instanceof StructureScript structureScript) {
return structureScript.generate(arguments.getOrigin(), return structureScript.generate(arguments.getOrigin(),
arguments.getWorld() arguments.getWorld()
.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.getRandom(), arguments.getRotation(), arguments.getRecursions() + 1);
arguments.getRotation().rotate(rotation1), arguments.getRecursions() + 1);
} }
return script.generate(arguments.getOrigin(), return script.generate(arguments.getOrigin(),
arguments.getWorld() arguments.getWorld()
.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.getRandom(), arguments.getRotation(), arguments.getWorld().getSeed());
arguments.getRotation().rotate(rotation1));
}).orElseGet(() -> { }).orElseGet(() -> {
LOGGER.error("No such structure {}", app); LOGGER.error("No such structure {}", app);
return false; return false;
@@ -9,11 +9,12 @@ package com.dfsek.terra.api.structure;
import java.util.random.RandomGenerator; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.Rotation; import com.dfsek.terra.api.util.Rotation;
import com.dfsek.terra.api.util.vector.Vector3Int; import com.dfsek.terra.api.util.vector.Vector3Int;
import com.dfsek.terra.api.world.WritableWorld; import com.dfsek.terra.api.world.WritableWorld;
public interface Structure { public interface Structure {
boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation); boolean generate(Vector3Int location, WritableWorld world, Rotation rotation, Long Seed);
} }
@@ -173,4 +173,21 @@ public final class MathUtil {
return mu + sigma * val; return mu + sigma * val;
} }
/**
* 1D Linear interpolation between 2 points 1 unit apart.
*
* @param t - Distance from v0. Total distance between v0 and v1 is 1 unit.
* @param v0 - Value at v0.
* @param v1 - Value at v1.
*
* @return double - The interpolated value.
*/
public static double lerp(double t, double v0, double v1) {
return v0 + t * (v1 - v0);
}
public static double inverseLerp(double t, double v0, double v1) {
return (t - v0) / (v1 - v0);
}
} }
@@ -1,6 +1,8 @@
package com.dfsek.terra.mod.mixin.gameplay; package com.dfsek.terra.mod.mixin.gameplay;
import com.dfsek.terra.api.world.World;
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;
@@ -43,14 +45,13 @@ 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, random, Rotation.NONE)); Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, Rotation.NONE, world.getSeed() + random.nextLong(Long.MAX_VALUE)));
return; return;
} }
cir.setReturnValue(true); cir.setReturnValue(true);
return; return;
} }
cir.setReturnValue(false); cir.setReturnValue(false);
return;
} }
} }
} }
@@ -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, random, Rotation.NONE)) { Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, Rotation.NONE, world.getSeed() + random.nextLong(Long.MAX_VALUE))) {
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, random, Rotation.NONE); Vector3Int.of(pos.getX(), pos.getY(), pos.getZ()), (WritableWorld) world, Rotation.NONE, world.getSeed() + random.nextLong(Long.MAX_VALUE));
return true; return true;
} }
} }