diff --git a/gradle.properties b/gradle.properties index 47fdf3e3e..fa23fe2bf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -22,7 +22,7 @@ mixin_version=0.8.5 neogradle.subsystems.parchment.minecraftVersion=1.21.1 neogradle.subsystems.parchment.mappingsVersion=2024.11.17 -kommons_version=3.1.3 +kommons_version=3.2.1 caffeine_cache_version=3.1.5 jei_version=19.16.4.171 diff --git a/src/main/java/ru/dbotthepony/mc/otm/mixin/LevelMixin.java b/src/main/java/ru/dbotthepony/mc/otm/mixin/LevelMixin.java index 8f60b5a71..e03b7aba2 100644 --- a/src/main/java/ru/dbotthepony/mc/otm/mixin/LevelMixin.java +++ b/src/main/java/ru/dbotthepony/mc/otm/mixin/LevelMixin.java @@ -5,11 +5,11 @@ import net.minecraft.world.level.Level; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import ru.dbotthepony.mc.otm.core.IMatteryLevel; -import ru.dbotthepony.mc.otm.core.util.Xoshiro256SSRandom; +import ru.dbotthepony.mc.otm.core.util.Xoshiro256Random; @Mixin(Level.class) public abstract class LevelMixin implements IMatteryLevel { - public final RandomSource otm_random = new Xoshiro256SSRandom(); + public final RandomSource otm_random = new Xoshiro256Random(); @Override public @NotNull RandomSource getOtmRandom() { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CMWCRandom.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CMWCRandom.kt index 16d885b7e..c2891df03 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CMWCRandom.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/CMWCRandom.kt @@ -5,6 +5,7 @@ import net.minecraft.util.RandomSource import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian import net.minecraft.world.level.levelgen.PositionalRandomFactory import net.minecraft.world.level.levelgen.RandomSupport +import ru.dbotthepony.kommons.random.LCG64Random import java.lang.StringBuilder import java.util.random.RandomGenerator diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IRandomSourceGenerator.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IRandomSourceGenerator.kt new file mode 100644 index 000000000..999e39cfd --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/IRandomSourceGenerator.kt @@ -0,0 +1,30 @@ +package ru.dbotthepony.mc.otm.core.util + +import net.minecraft.util.RandomSource +import java.util.random.RandomGenerator + +interface IRandomSourceGenerator : RandomSource, RandomGenerator { + override fun nextInt(): Int + + override fun nextInt(bound: Int): Int { + return super.nextInt(bound) + } + + override fun nextInt(origin: Int, bound: Int): Int { + return super.nextInt(origin, bound) + } + + override fun nextBoolean(): Boolean { + return super.nextBoolean() + } + + override fun nextFloat(): Float { + return super.nextFloat() + } + + override fun nextDouble(): Double { + return super.nextDouble() + } + + override fun nextGaussian(): Double +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/LCG64Random.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/LCG64RandomSource.kt similarity index 63% rename from src/main/kotlin/ru/dbotthepony/mc/otm/core/util/LCG64Random.kt rename to src/main/kotlin/ru/dbotthepony/mc/otm/core/util/LCG64RandomSource.kt index eb939ab0b..af4f1bdec 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/LCG64Random.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/LCG64RandomSource.kt @@ -6,8 +6,8 @@ import net.minecraft.world.level.levelgen.LegacyRandomSource import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian import net.minecraft.world.level.levelgen.PositionalRandomFactory import net.minecraft.world.level.levelgen.RandomSupport +import ru.dbotthepony.kommons.random.LCG64Random import java.lang.StringBuilder -import java.util.random.RandomGenerator /** * Simple and insanely fast random number generator, which can be used for seeding (initializing internal state) of other number generators. @@ -19,7 +19,7 @@ import java.util.random.RandomGenerator * * Always use upper 32 bits instead of implementing BitRandomSource and sampling some upper bits * * Uses all bits from provided seed */ -class LCG64Random(private var seed: Long = RandomSupport.generateUniqueSeed()) : RandomGenerator, RandomSource { +class LCG64RandomSource(seed: Long = RandomSupport.generateUniqueSeed()) : LCG64Random(seed), IRandomSourceGenerator { private val gaussian = MarsagliaPolarGaussian(this) override fun setSeed(seed: Long) { @@ -27,43 +27,12 @@ class LCG64Random(private var seed: Long = RandomSupport.generateUniqueSeed()) : gaussian.reset() } - override fun nextInt(): Int { - this.seed = MULTIPLIER * this.seed + INCREMENT - return this.seed.ushr(32).toInt() - } - - override fun nextLong(): Long { - val a = nextInt().toLong() - val b = nextInt().toLong() and 0xFFFFFFFFL - return a.shl(32) or b - } - - override fun nextInt(bound: Int): Int { - return super.nextInt(bound) - } - - override fun nextInt(origin: Int, bound: Int): Int { - return super.nextInt(origin, bound) - } - - override fun nextBoolean(): Boolean { - return super.nextBoolean() - } - - override fun nextFloat(): Float { - return super.nextFloat() - } - - override fun nextDouble(): Double { - return super.nextDouble() - } - override fun nextGaussian(): Double { return gaussian.nextGaussian() } override fun fork(): RandomSource { - return LCG64Random(nextLong()) + return LCG64RandomSource(nextLong()) } override fun forkPositional(): PositionalRandomFactory { @@ -72,15 +41,15 @@ class LCG64Random(private var seed: Long = RandomSupport.generateUniqueSeed()) : class Positional(val seed: Long) : PositionalRandomFactory { override fun at(x: Int, y: Int, z: Int): RandomSource { - return LCG64Random(Mth.getSeed(x, y, z).xor(seed)) + return LCG64RandomSource(Mth.getSeed(x, y, z).xor(seed)) } override fun fromHashOf(name: String): RandomSource { - return LCG64Random(name.hashCode().toLong().xor(seed)) + return LCG64RandomSource(name.hashCode().toLong().xor(seed)) } override fun fromSeed(seed: Long): RandomSource { - return LCG64Random(seed) + return LCG64RandomSource(seed) } override fun parityConfigString(builder: StringBuilder) { diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256Random.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256Random.kt new file mode 100644 index 000000000..5d1e2ee28 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256Random.kt @@ -0,0 +1,93 @@ +package ru.dbotthepony.mc.otm.core.util + +import it.unimi.dsi.fastutil.HashCommon +import net.minecraft.util.Mth +import net.minecraft.util.RandomSource +import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian +import net.minecraft.world.level.levelgen.PositionalRandomFactory +import net.minecraft.world.level.levelgen.RandomSupport +import ru.dbotthepony.kommons.random.LCG64Random +import ru.dbotthepony.kommons.random.Xoshiro256StarStarRandom + +/** + * Excellent number generator with guaranteed period of 2^255 + */ +class Xoshiro256Random : Xoshiro256StarStarRandom, IRandomSourceGenerator { + private val gaussian = MarsagliaPolarGaussian(this) + + // raw + private constructor(s0: Long, s1: Long, s2: Long, s3: Long, marker: Nothing?): super(s0, s1, s2, s3, null) + // normal + constructor(s0: Long, s1: Long, s2: Long, s3: Long) : super(s0, s1, s2, s3) + + // 64-bit seeded + constructor(seed: Long) : super(1L, 2L, 3L, 4L, null) { + setSeed(seed) + } + + // completely random + constructor() : super(RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), null) + + override fun setSeed(seed: Long) { + val rng = LCG64Random(seed) + s0 = rng.nextLong() + s1 = rng.nextLong() + s2 = rng.nextLong() + s3 = rng.nextLong() + gaussian.reset() + } + + override fun nextInt(): Int { + // sample upper bits + return nextLong().ushr(32).toInt() + } + + override fun nextGaussian(): Double { + return gaussian.nextGaussian() + } + + override fun fork(): RandomSource { + return Xoshiro256Random(nextLong(), nextLong(), nextLong(), nextLong(), null) + } + + override fun forkPositional(): PositionalRandomFactory { + return Positional(nextLong(), nextLong(), nextLong(), nextLong()) + } + + class Positional( + val s0: Long, + val s1: Long, + val s2: Long, + val s3: Long, + ) : PositionalRandomFactory { + override fun at(x: Int, y: Int, z: Int): RandomSource { + val rng = LCG64RandomSource(Mth.getSeed(x, y, z)) + + return Xoshiro256Random( + s0.rotateLeft(11).xor(rng.nextLong()), + s1.rotateLeft(22).xor(rng.nextLong()), + s2.rotateLeft(33).xor(rng.nextLong()), + s3.rotateLeft(44).xor(rng.nextLong()), + ) + } + + override fun fromHashOf(name: String): RandomSource { + return Xoshiro256Random(s0, HashCommon.murmurHash3(name.hashCode().toLong()).xor(s1), s2, s3) + } + + override fun fromSeed(seed: Long): RandomSource { + return Xoshiro256Random(seed) + } + + override fun parityConfigString(builder: StringBuilder) { + throw UnsupportedOperationException() + } + } + + companion object { + @JvmStatic + fun raw(s0: Long, s1: Long, s2: Long, s3: Long): Xoshiro256Random { + return Xoshiro256Random(s0, s1, s2, s3, null) + } + } +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256SSRandom.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256SSRandom.kt deleted file mode 100644 index a6c595115..000000000 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256SSRandom.kt +++ /dev/null @@ -1,138 +0,0 @@ -package ru.dbotthepony.mc.otm.core.util - -import it.unimi.dsi.fastutil.HashCommon -import net.minecraft.util.Mth -import net.minecraft.util.RandomSource -import net.minecraft.world.level.levelgen.MarsagliaPolarGaussian -import net.minecraft.world.level.levelgen.PositionalRandomFactory -import net.minecraft.world.level.levelgen.RandomSupport -import java.util.random.RandomGenerator - -/** - * Excellent number generator with guaranteed period of 2^255 - */ -class Xoshiro256SSRandom private constructor( - private var s0: Long, - private var s1: Long, - private var s2: Long, - private var s3: Long, - marker: Nothing? -) : RandomGenerator, RandomSource { - private val gaussian = MarsagliaPolarGaussian(this) - - init { - if (s0 or s1 or s2 or s3 == 0L) { - s0 = 0x73CF3D83FFF44FF3L - s1 = 0x6412312B70F3CD37L - s2 = -0X6BB4C4E1327BFDCFL - s3 = -0X4BE0F5BB5F3F5240L - } - } - - constructor(s0: Long, s1: Long, s2: Long, s3: Long) : this(s0, s1, s2, s3, null) { - // discard some values so generator can get going if provided seed was "weak" - for (i in 0 until 32) - nextLong() - } - - constructor(seed: Long) : this(1L, 2L, 3L, 4L, null) { - setSeed(seed) - } - - constructor() : this(RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed(), null) - - override fun setSeed(seed: Long) { - val rng = LCG64Random(seed) - s0 = rng.nextLong() - s1 = rng.nextLong() - s2 = rng.nextLong() - s3 = rng.nextLong() - gaussian.reset() - } - - override fun nextInt(): Int { - // sample upper bits - return nextLong().ushr(32).toInt() - } - - override fun nextLong(): Long { - val result = (s1 * 5).rotateLeft(7) * 9 - val t = s1.shl(17) - s2 = s2.xor(s0) - s3 = s3.xor(s1) - s1 = s1.xor(s2) - s0 = s0.xor(s3) - s2 = s2.xor(t) - s3 = s3.rotateLeft(45) - return result - } - - override fun nextInt(bound: Int): Int { - return super.nextInt(bound) - } - - override fun nextInt(origin: Int, bound: Int): Int { - return super.nextInt(origin, bound) - } - - override fun nextBoolean(): Boolean { - return super.nextBoolean() - } - - override fun nextFloat(): Float { - return super.nextFloat() - } - - override fun nextDouble(): Double { - return super.nextDouble() - } - - override fun nextGaussian(): Double { - return gaussian.nextGaussian() - } - - override fun fork(): RandomSource { - return Xoshiro256SSRandom(nextLong(), nextLong(), nextLong(), nextLong(), null) - } - - override fun forkPositional(): PositionalRandomFactory { - return Positional(nextLong(), nextLong(), nextLong(), nextLong()) - } - - class Positional( - val s0: Long, - val s1: Long, - val s2: Long, - val s3: Long, - ) : PositionalRandomFactory { - override fun at(x: Int, y: Int, z: Int): RandomSource { - val rng = LCG64Random(Mth.getSeed(x, y, z)) - - return Xoshiro256SSRandom( - s0.rotateLeft(11).xor(rng.nextLong()), - s1.rotateLeft(22).xor(rng.nextLong()), - s2.rotateLeft(33).xor(rng.nextLong()), - s3.rotateLeft(44).xor(rng.nextLong()), - ) - } - - override fun fromHashOf(name: String): RandomSource { - return Xoshiro256SSRandom(s0, HashCommon.murmurHash3(name.hashCode().toLong()).xor(s1), s2, s3) - } - - override fun fromSeed(seed: Long): RandomSource { - return Xoshiro256SSRandom(seed) - } - - override fun parityConfigString(builder: StringBuilder) { - throw UnsupportedOperationException() - } - } - - companion object { - @JvmStatic - fun raw(s0: Long, s1: Long, s2: Long, s3: Long): Xoshiro256SSRandom { - return Xoshiro256SSRandom(s0, s1, s2, s3, null) - } - } -}