From 49f76c7bddad53dda407c3dfd577eafacdaa7061 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Wed, 5 Mar 2025 09:06:44 +0700 Subject: [PATCH] Provide Xoshiro256StarStar random --- .../mc/otm/core/util/Xoshiro256SSRandom.kt | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256SSRandom.kt 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 new file mode 100644 index 000000000..e14e7ed02 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/util/Xoshiro256SSRandom.kt @@ -0,0 +1,110 @@ +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 java.lang.StringBuilder +import java.util.random.RandomGenerator + +class Xoshiro256SSRandom( + private var s0: Long, + private var s1: Long, + private var s2: Long, + private var s3: Long, +) : RandomGenerator, RandomSource { + private val gaussian = MarsagliaPolarGaussian(this) + + constructor(seed: Long = System.nanoTime()) : this(1L, 2L, 3L, 4L) { + setSeed(seed) + } + + 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()) + } + + 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() + } + } +}