WIP Random Changes

This commit is contained in:
Zoë Gidiere
2023-12-12 15:57:04 -07:00
parent 033181d7c8
commit a9f973cae9
28 changed files with 208 additions and 143 deletions
@@ -6,9 +6,10 @@ 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; import com.dfsek.terra.addons.manifest.api.MonadAddonInitializer;
import com.dfsek.terra.addons.manifest.api.monad.Do;
import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.addons.manifest.api.monad.Get;
import com.dfsek.terra.addons.manifest.api.monad.Init;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.addon.BaseAddon; import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.command.CommandSender; import com.dfsek.terra.api.command.CommandSender;
@@ -22,6 +23,8 @@ 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.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
public class StructureCommandAddon implements AddonInitializer { public class StructureCommandAddon implements AddonInitializer {
@Inject @Inject
@@ -1,6 +1,7 @@
package com.dfsek.terra.addons.feature.distributor.distributors; package com.dfsek.terra.addons.feature.distributor.distributors;
import java.util.Random; import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.structure.feature.Distributor; import com.dfsek.terra.api.structure.feature.Distributor;
import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.util.MathUtil;
@@ -24,7 +25,8 @@ public class PaddedGridDistributor implements Distributor {
int cellX = Math.floorDiv(x, cellWidth); int cellX = Math.floorDiv(x, cellWidth);
int cellZ = Math.floorDiv(z, cellWidth); int cellZ = Math.floorDiv(z, cellWidth);
Random random = new Random((MathUtil.murmur64(MathUtil.squash(cellX, cellZ)) ^ seed) + salt); RandomGenerator random = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(
(murmur64(MathUtil.squash(cellX, cellZ)) ^ seed) + salt);
int pointX = random.nextInt(width) + cellX * cellWidth; int pointX = random.nextInt(width) + cellX * cellWidth;
int pointZ = random.nextInt(width) + cellZ * cellWidth; int pointZ = random.nextInt(width) + cellZ * cellWidth;
@@ -10,7 +10,8 @@ package com.dfsek.terra.addons.flora.flora.gen;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.block.state.properties.enums.Direction; import com.dfsek.terra.api.block.state.properties.enums.Direction;
@@ -71,7 +72,7 @@ public class TerraFlora implements Structure {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, 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 +87,9 @@ public class TerraFlora implements Structure {
location.getZ(), world.getSeed()); location.getZ(), world.getSeed());
if(doRotation) { if(doRotation) {
Direction oneFace = new ArrayList<>(faces).get( Direction oneFace = new ArrayList<>(faces).get(
new Random(location.getX() ^ location.getZ()).nextInt(faces.size())); // Get random face. 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);
} }
@@ -7,7 +7,8 @@
package com.dfsek.terra.addons.feature.locator.locators; package com.dfsek.terra.addons.feature.locator.locators;
import java.util.Random; 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.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.structure.feature.Locator;
@@ -40,7 +41,7 @@ public class GaussianRandomLocator implements Locator {
seed = 31 * seed + column.getZ(); seed = 31 * seed + column.getZ();
seed += salt; seed += salt;
Random r = new Random(seed); RandomGenerator r = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(seed);
int size = points.get(r); int size = points.get(r);
@@ -7,7 +7,8 @@
package com.dfsek.terra.addons.feature.locator.locators; package com.dfsek.terra.addons.feature.locator.locators;
import java.util.Random; 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.BinaryColumn;
import com.dfsek.terra.api.structure.feature.Locator; import com.dfsek.terra.api.structure.feature.Locator;
@@ -36,7 +37,7 @@ public class RandomLocator implements Locator {
seed = 31 * seed + column.getZ(); seed = 31 * seed + column.getZ();
seed += salt; seed += salt;
Random r = new Random(seed); RandomGenerator r = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(seed);
int size = points.get(r); int size = points.get(r);
@@ -9,7 +9,7 @@ package com.dfsek.terra.addons.ore.ores;
import java.util.BitSet; import java.util.BitSet;
import java.util.Map; import java.util.Map;
import java.util.Random; 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;
@@ -12,7 +12,7 @@ import org.json.simple.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.addons.structure.structures.loot.functions.AmountFunction; import com.dfsek.terra.addons.structure.structures.loot.functions.AmountFunction;
import com.dfsek.terra.addons.structure.structures.loot.functions.DamageFunction; import com.dfsek.terra.addons.structure.structures.loot.functions.DamageFunction;
@@ -85,11 +85,11 @@ public class Entry {
/** /**
* Fetches a single ItemStack from the Entry, applying all functions to it. * Fetches a single ItemStack from the Entry, applying all functions to it.
* *
* @param r The Random instance to apply functions with * @param r The RandomGenerator instance to apply functions with
* *
* @return ItemStack - The ItemStack with all functions applied. * @return ItemStack - The ItemStack with all functions applied.
*/ */
public ItemStack getItem(Random r) { public ItemStack getItem(RandomGenerator r) {
ItemStack item = this.item.newItemStack(1); ItemStack item = this.item.newItemStack(1);
for(LootFunction f : functions) { for(LootFunction f : functions) {
item = f.apply(item, r); item = f.apply(item, r);
@@ -14,7 +14,7 @@ import org.json.simple.parser.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.inventory.Inventory; import com.dfsek.terra.api.inventory.Inventory;
@@ -44,7 +44,7 @@ public class LootTableImpl implements com.dfsek.terra.api.structure.LootTable {
} }
@Override @Override
public void fillInventory(Inventory i, Random r) { public void fillInventory(Inventory i, RandomGenerator r) {
List<ItemStack> loot = getLoot(r); List<ItemStack> loot = getLoot(r);
for(ItemStack stack : loot) { for(ItemStack stack : loot) {
int attempts = 0; int attempts = 0;
@@ -70,7 +70,7 @@ public class LootTableImpl implements com.dfsek.terra.api.structure.LootTable {
} }
@Override @Override
public List<ItemStack> getLoot(Random r) { public List<ItemStack> getLoot(RandomGenerator r) {
List<ItemStack> itemList = new ArrayList<>(); List<ItemStack> itemList = new ArrayList<>();
for(Pool pool : pools) { for(Pool pool : pools) {
itemList.addAll(pool.getItems(r)); itemList.addAll(pool.getItems(r));
@@ -12,7 +12,7 @@ import org.json.simple.JSONObject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
@@ -50,13 +50,13 @@ public class Pool {
} }
/** /**
* Fetches a list of items from the pool using the provided Random instance. * Fetches a list of items from the pool using the provided RandomGenerator instance.
* *
* @param r The Random instance to use. * @param r The RandomGenerator instance to use.
* *
* @return List&lt;ItemStack&gt; - The list of items fetched. * @return List&lt;ItemStack&gt; - The list of items fetched.
*/ */
public List<ItemStack> getItems(Random r) { public List<ItemStack> getItems(RandomGenerator r) {
int rolls = r.nextInt(max - min + 1) + min; int rolls = r.nextInt(max - min + 1) + min;
List<ItemStack> items = new ArrayList<>(); List<ItemStack> items = new ArrayList<>();
@@ -8,7 +8,7 @@
package com.dfsek.terra.addons.structure.structures.loot.functions; package com.dfsek.terra.addons.structure.structures.loot.functions;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
@@ -35,12 +35,12 @@ public class AmountFunction implements LootFunction {
* Applies the function to an ItemStack. * Applies the function to an ItemStack.
* *
* @param original The ItemStack on which to apply the function. * @param original The ItemStack on which to apply the function.
* @param r The Random instance to use. * @param r The RandomGenerator instance to use.
* *
* @return - ItemStack - The mutated ItemStack. * @return - ItemStack - The mutated ItemStack.
*/ */
@Override @Override
public ItemStack apply(ItemStack original, Random r) { public ItemStack apply(ItemStack original, RandomGenerator r) {
original.setAmount(r.nextInt(max - min + 1) + min); original.setAmount(r.nextInt(max - min + 1) + min);
return original; return original;
} }
@@ -7,7 +7,7 @@
package com.dfsek.terra.addons.structure.structures.loot.functions; package com.dfsek.terra.addons.structure.structures.loot.functions;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
import com.dfsek.terra.api.inventory.item.Damageable; import com.dfsek.terra.api.inventory.item.Damageable;
@@ -36,12 +36,12 @@ public class DamageFunction implements LootFunction {
* Applies the function to an ItemStack. * Applies the function to an ItemStack.
* *
* @param original The ItemStack on which to apply the function. * @param original The ItemStack on which to apply the function.
* @param r The Random instance to use. * @param r The RandomGenerator instance to use.
* *
* @return - ItemStack - The mutated ItemStack. * @return - ItemStack - The mutated ItemStack.
*/ */
@Override @Override
public ItemStack apply(ItemStack original, Random r) { public ItemStack apply(ItemStack original, RandomGenerator r) {
if(original == null) return null; if(original == null) return null;
if(!original.isDamageable()) return original; if(!original.isDamageable()) return original;
ItemMeta meta = original.getItemMeta(); ItemMeta meta = original.getItemMeta();
@@ -14,7 +14,7 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
@@ -41,12 +41,12 @@ public class EnchantFunction implements LootFunction {
* Applies the function to an ItemStack. * Applies the function to an ItemStack.
* *
* @param original The ItemStack on which to apply the function. * @param original The ItemStack on which to apply the function.
* @param r The Random instance to use. * @param r The RandomGenerator instance to use.
* *
* @return - ItemStack - The mutated ItemStack. * @return - ItemStack - The mutated ItemStack.
*/ */
@Override @Override
public ItemStack apply(ItemStack original, Random r) { public ItemStack apply(ItemStack original, RandomGenerator r) {
if(original.getItemMeta() == null) return original; if(original.getItemMeta() == null) return original;
double enchant = (r.nextDouble() * (max - min)) + min; double enchant = (r.nextDouble() * (max - min)) + min;
@@ -8,7 +8,7 @@
package com.dfsek.terra.addons.structure.structures.loot.functions; package com.dfsek.terra.addons.structure.structures.loot.functions;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
@@ -21,9 +21,9 @@ public interface LootFunction {
* Applies the function to an ItemStack. * Applies the function to an ItemStack.
* *
* @param original The ItemStack on which to apply the function. * @param original The ItemStack on which to apply the function.
* @param r The Random instance to use. * @param r The RandomGenerator instance to use.
* *
* @return - ItemStack - The mutated ItemStack. * @return - ItemStack - The mutated ItemStack.
*/ */
ItemStack apply(ItemStack original, Random r); ItemStack apply(ItemStack original, RandomGenerator r);
} }
@@ -8,7 +8,8 @@
package com.dfsek.terra.addons.generation.feature; package com.dfsek.terra.addons.generation.feature;
import java.util.Collections; import java.util.Collections;
import java.util.Random; import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures; import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
@@ -52,35 +53,37 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
int tx = cx + chunkX; int tx = cx + chunkX;
int tz = cz + chunkZ; int tz = cz + chunkZ;
world.getBiomeProvider() world.getBiomeProvider()
.getColumn(tx, tz, world) .getColumn(tx, tz, world)
.forRanges(resolution, (min, max, biome) -> { .forRanges(resolution, (min, max, biome) -> {
for(int subChunkX = 0; subChunkX < resolution; subChunkX++) { for(int subChunkX = 0; subChunkX < resolution; subChunkX++) {
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; 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)
.getFeatures() .getFeatures()
.getOrDefault(this, Collections.emptyList()) .getOrDefault(this, Collections.emptyList())
.forEach(feature -> { .forEach(feature -> {
platform.getProfiler().push(feature.getID()); platform.getProfiler().push(feature.getID());
if(feature.getDistributor().matches(x, z, seed)) { if(feature.getDistributor().matches(x, z, seed)) {
feature.getLocator() feature.getLocator()
.getSuitableCoordinates(column.clamp(min, max)) .getSuitableCoordinates(column.clamp(min, max))
.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,
new Random(coordinateSeed * 31 + y), RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of(
Rotation.NONE) "Xoroshiro128PlusPlus")
); .create(coordinateSeed * 31 + y),
} Rotation.NONE)
platform.getProfiler().pop(feature.getID()); );
}); }
} platform.getProfiler().pop(feature.getID());
} });
}); }
}
});
} }
} }
platform.getProfiler().pop(profile); platform.getProfiler().pop(profile);
@@ -1,6 +1,6 @@
package com.dfsek.terra.addons.palette.shortcut.block; package com.dfsek.terra.addons.palette.shortcut.block;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.structure.Structure; import com.dfsek.terra.api.structure.Structure;
@@ -17,7 +17,7 @@ public class SingletonStructure implements Structure {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) {
world.setBlockState(location, blockState); world.setBlockState(location, blockState);
return true; return true;
} }
@@ -1,6 +1,6 @@
package com.dfsek.terra.addons.structure.mutator; package com.dfsek.terra.addons.structure.mutator;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.registry.key.Keyed; import com.dfsek.terra.api.registry.key.Keyed;
import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.api.registry.key.RegistryKey;
@@ -32,7 +32,7 @@ public class MutatedStructure implements Structure, Keyed<MutatedStructure> {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) {
return base.generate(location, return base.generate(location,
world world
.buffer() .buffer()
@@ -7,7 +7,7 @@
package com.dfsek.terra.addons.sponge; package com.dfsek.terra.addons.sponge;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.registry.key.Keyed; import com.dfsek.terra.api.registry.key.Keyed;
@@ -36,7 +36,7 @@ public class SpongeStructure implements Structure, Keyed<SpongeStructure> {
} }
@Override @Override
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, 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();
@@ -14,7 +14,7 @@ import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.addons.terrascript.parser.Parser; import com.dfsek.terra.addons.terrascript.parser.Parser;
import com.dfsek.terra.addons.terrascript.parser.lang.Executable; import com.dfsek.terra.addons.terrascript.parser.lang.Executable;
@@ -131,14 +131,14 @@ public class StructureScript implements Structure, Keyed<StructureScript> {
@Override @Override
@SuppressWarnings("try") @SuppressWarnings("try")
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation) { public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation) {
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, random, world, 0));
platform.getProfiler().pop(profile); platform.getProfiler().pop(profile);
return result; return result;
} }
public boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation, int recursions) { public boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, 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, random, world, recursions));
platform.getProfiler().pop(profile); platform.getProfiler().pop(profile);
@@ -9,7 +9,7 @@ package com.dfsek.terra.addons.terrascript.script;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.api.util.Rotation; import com.dfsek.terra.api.util.Rotation;
@@ -20,14 +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 Random random; 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, Random random, WritableWorld world, int recursions) { public TerraImplementationArguments(Vector3Int origin, Rotation rotation, RandomGenerator random, WritableWorld world, int recursions) {
this.rotation = rotation; this.rotation = rotation;
this.random = random; this.random = random;
this.world = world; this.world = world;
@@ -39,7 +39,7 @@ public class TerraImplementationArguments implements ImplementationArguments {
return recursions; return recursions;
} }
public Random getRandom() { public RandomGenerator getRandom() {
return random; return random;
} }
@@ -10,8 +10,6 @@ package com.dfsek.terra.addons.terrascript.script.functions;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Random;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments; 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.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.Scope; import com.dfsek.terra.addons.terrascript.parser.lang.Scope;
@@ -30,6 +28,9 @@ import com.dfsek.terra.api.util.RotationUtil;
import com.dfsek.terra.api.util.vector.Vector2; import com.dfsek.terra.api.util.vector.Vector2;
import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3;
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
public class LootFunction implements Function<Void> { public class LootFunction implements Function<Void> {
private static final Logger LOGGER = LoggerFactory.getLogger(LootFunction.class); private static final Logger LOGGER = LoggerFactory.getLogger(LootFunction.class);
@@ -64,34 +65,35 @@ public class LootFunction implements Function<Void> {
registry.get(RegistryKey.parse(id)) registry.get(RegistryKey.parse(id))
.ifPresentOrElse(table -> { .ifPresentOrElse(table -> {
Vector3 apply = Vector3.of((int) Math.round(xz.getX()), Vector3 apply = Vector3.of(FastMath.roundToInt(xz.getX()),
y.apply(implementationArguments, scope) y.apply(implementationArguments, scope)
.intValue(), .intValue(),
(int) Math.round(xz.getZ())).mutable().add(arguments.getOrigin()).immutable(); FastMath.roundToInt(xz.getZ())).mutable().add(arguments.getOrigin()).immutable();
try { try {
BlockEntity data = arguments.getWorld().getBlockEntity(apply); BlockEntity data = arguments.getWorld().getBlockEntity(apply);
if(!(data instanceof Container container)) { if(!(data instanceof Container container)) {
LOGGER.error("Failed to place loot at {}; block {} is not a container", LOGGER.error("Failed to place loot at {}; block {} is not a container",
apply, data); apply, data);
return; return;
} }
LootPopulateEvent event = new LootPopulateEvent(container, table, LootPopulateEvent event = new LootPopulateEvent(container, table,
arguments.getWorld().getPack(), script); arguments.getWorld().getPack(), script);
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(),
new Random(apply.hashCode())); RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of(
data.update(false); "Xoroshiro128PlusPlus").create(apply.hashCode()));
} catch(Exception e) { data.update(false);
LOGGER.error("Could not apply loot at {}", apply, e); } catch(Exception e) {
e.printStackTrace(); LOGGER.error("Could not apply loot at {}", apply, e);
} e.printStackTrace();
}, }
() -> LOGGER.error("No such loot table {}", id)); },
() -> LOGGER.error("No such loot table {}", id));
return null; return null;
} }
@@ -10,7 +10,7 @@ package com.dfsek.terra.api.structure;
import org.jetbrains.annotations.ApiStatus.Experimental; import org.jetbrains.annotations.ApiStatus.Experimental;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import com.dfsek.terra.api.inventory.Inventory; import com.dfsek.terra.api.inventory.Inventory;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
@@ -22,16 +22,16 @@ 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 Random instance to use. * @param r The The RandomGenerator instance to use.
*/ */
void fillInventory(Inventory i, Random r); void fillInventory(Inventory i, RandomGenerator r);
/** /**
* Fetches a list of ItemStacks from the loot table using the given Random instance. * Fetches a list of ItemStacks from the loot table using the given RandomGenerator instance.
* *
* @param r The Random instance to use. * @param r The RandomGenerator instance to use.
* *
* @return List&lt;ItemStack&gt; - The list of loot fetched. * @return List&lt;ItemStack&gt; - The list of loot fetched.
*/ */
List<ItemStack> getLoot(Random r); List<ItemStack> getLoot(RandomGenerator r);
} }
@@ -7,7 +7,7 @@
package com.dfsek.terra.api.structure; package com.dfsek.terra.api.structure;
import java.util.Random; import java.util.random.RandomGenerator;
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;
@@ -15,5 +15,5 @@ import com.dfsek.terra.api.world.WritableWorld;
public interface Structure { public interface Structure {
boolean generate(Vector3Int location, WritableWorld world, Random random, Rotation rotation); boolean generate(Vector3Int location, WritableWorld world, RandomGenerator random, Rotation rotation);
} }
@@ -10,7 +10,7 @@ package com.dfsek.terra.api.util;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Iterator; import java.util.Iterator;
import java.util.Random; import java.util.random.RandomGenerator;
public class ConstantRange implements Range { public class ConstantRange implements Range {
@@ -36,7 +36,7 @@ public class ConstantRange implements Range {
} }
@Override @Override
public int get(Random r) { public int get(RandomGenerator r) {
return r.nextInt(min, max); return r.nextInt(min, max);
} }
@@ -7,18 +7,20 @@
package com.dfsek.terra.api.util; package com.dfsek.terra.api.util;
import java.util.Random; import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
import com.dfsek.terra.api.world.chunk.Chunk; import com.dfsek.terra.api.world.chunk.Chunk;
public final class PopulationUtil { public final class PopulationUtil {
public static Random getRandom(Chunk c) { public static RandomGenerator getRandom(Chunk c) {
return getRandom(c, 0); return getRandom(c, 0);
} }
public static Random getRandom(Chunk c, long salt) { public static RandomGenerator getRandom(Chunk c, long salt) {
return new Random(getCarverChunkSeed(c.getX(), c.getZ(), c.getWorld().getSeed() + salt)); return RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(
getCarverChunkSeed(c.getX(), c.getZ(), c.getWorld().getSeed() + salt));
} }
/** /**
@@ -31,7 +33,7 @@ public final class PopulationUtil {
* @return long - The carver seed. * @return long - The carver seed.
*/ */
public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) { public static long getCarverChunkSeed(int chunkX, int chunkZ, long seed) {
Random r = new Random(seed); RandomGenerator r = RandomGeneratorFactory.<RandomGenerator.SplittableGenerator>of("Xoroshiro128PlusPlus").create(seed);
return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed; return chunkX * r.nextLong() ^ chunkZ * r.nextLong() ^ seed;
} }
} }
@@ -10,8 +10,8 @@ package com.dfsek.terra.api.util;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Iterator; import java.util.Iterator;
import java.util.Random;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.random.RandomGenerator;
public interface Range extends Iterable<Integer> { public interface Range extends Iterable<Integer> {
@@ -19,7 +19,7 @@ public interface Range extends Iterable<Integer> {
Range reflect(int pt); Range reflect(int pt);
int get(Random r); int get(RandomGenerator r);
Range intersects(Range other); Range intersects(Range other);
@@ -15,9 +15,9 @@ import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.random.RandomGenerator;
import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.util.MathUtil; import com.dfsek.terra.api.util.MathUtil;
@@ -43,7 +43,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public E get(Random r) { public E get(RandomGenerator r) {
if(array.length == 0) return null; if(array.length == 0) return null;
return (E) array[r.nextInt(array.length)]; return (E) array[r.nextInt(array.length)];
} }
@@ -197,7 +197,7 @@ public class ProbabilityCollection<E> implements Collection<E> {
} }
@Override @Override
public T get(Random r) { public T get(RandomGenerator r) {
return single; return single;
} }
@@ -27,7 +27,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.random.RandomGenerator;
import java.util.stream.Collectors;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
@@ -62,7 +63,7 @@ public class BukkitChunkGeneratorWrapper extends org.bukkit.generator.ChunkGener
} }
@Override @Override
public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull Random random, int x, int z, @NotNull ChunkData chunkData) { public void generateNoise(@NotNull WorldInfo worldInfo, @NotNull RandomGenerator random, int x, int z, @NotNull ChunkData chunkData) {
BukkitWorldProperties properties = new BukkitWorldProperties(worldInfo); BukkitWorldProperties properties = new BukkitWorldProperties(worldInfo);
delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, pack.getBiomeProvider(), x, z); delegate.generateChunkData(new BukkitProtoChunk(chunkData), properties, pack.getBiomeProvider(), x, z);
} }
@@ -18,11 +18,14 @@
package com.dfsek.terra.mod.util; package com.dfsek.terra.mod.util;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.HeightLimitView; import net.minecraft.world.HeightLimitView;
import com.dfsek.terra.api.util.vector.Vector3; import com.dfsek.terra.api.util.vector.Vector3;
import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.api.world.info.WorldProperties;
import java.util.random.RandomGenerator;
public final class MinecraftAdapter { public final class MinecraftAdapter {
@@ -53,4 +56,48 @@ public final class MinecraftAdapter {
} }
}; };
} }
public static RandomGenerator adapt(Random random) {
return new RandomGenerator() {
@Override
public boolean nextBoolean() {
return random.nextBoolean();
}
@Override
public float nextFloat() {
return random.nextFloat();
}
@Override
public double nextDouble() {
return random.nextDouble();
}
@Override
public int nextInt() {
return random.nextInt();
}
@Override
public int nextInt(int bound) {
return random.nextInt(bound);
}
@Override
public long nextLong() {
return random.nextLong();
}
@Override
public double nextGaussian() {
return random.nextGaussian();
}
@Override
public int nextInt(int origin, int bound) {
return random.nextBetween(origin, bound);
}
};
}
} }