better-random/src/main/java/ru/dbotthepony/mc/prng/GJRAND64RandomSource.java

143 lines
3.2 KiB
Java

package ru.dbotthepony.mc.prng;
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 org.jetbrains.annotations.NotNull;
import java.util.random.RandomGenerator;
public final class GJRAND64RandomSource implements RandomGenerator, RandomSource {
private long s0;
private long s1;
private long s2;
private long s3;
private final MarsagliaPolarGaussian gaussian = new MarsagliaPolarGaussian(this);
public GJRAND64RandomSource() {
reinitialize(RandomSupport.generateUniqueSeed(), RandomSupport.generateUniqueSeed());
}
public GJRAND64RandomSource(long seed) {
reinitialize(seed);
}
public GJRAND64RandomSource(long seed0, long seed1) {
reinitialize(seed0, seed1);
}
private void reinitialize(long seed) {
reinitialize(seed, 0L);
}
private void reinitialize(long seed0, long seed1) {
s0 = seed0;
s1 = seed1;
s2 = 2000001L;
s3 = 0L;
}
@Override
public @NotNull RandomSource fork() {
return new GJRAND64RandomSource(nextLong(), nextLong());
}
@Override
public @NotNull PositionalRandomFactory forkPositional() {
return new Positional(nextLong(), nextLong());
}
@Override
public void setSeed(long l) {
reinitialize(l);
gaussian.reset();
}
@Override
public int nextInt() {
return RandomGenerator.super.nextInt();
}
@Override
public int nextInt(int bound) {
return RandomGenerator.super.nextInt(bound);
}
@Override
public int nextInt(int origin, int bound) {
return RandomGenerator.super.nextInt(origin, bound);
}
@Override
public float nextFloat() {
return RandomGenerator.super.nextFloat();
}
@Override
public boolean nextBoolean() {
return RandomGenerator.super.nextBoolean();
}
@Override
public double nextDouble() {
return RandomGenerator.super.nextDouble();
}
@Override
public double nextGaussian() {
return gaussian.nextGaussian();
}
@Override
public long nextLong() {
s1 += s2;
s0 = Long.rotateLeft(s0, 32);
s2 ^= s1;
s3 += 0x55aa96a5L;
s0 += s1;
s2 = Long.rotateLeft(s2, 23);
s1 ^= s0;
s0 += s2;
s1 = Long.rotateLeft(s1, 19);
s2 += s0;
s1 += s3;
return s0;
}
public static class Positional implements PositionalRandomFactory {
private final long seed0;
private final long seed1;
public Positional(long seed0, long seed1) {
this.seed0 = seed0;
this.seed1 = seed1;
}
@Override
public @NotNull RandomSource fromHashOf(@NotNull String s) {
long seed = HashCommon.murmurHash3((long) s.hashCode() & 0xFFFFFFFFL);
return new GJRAND64RandomSource(seed0 ^ Long.rotateLeft(seed, 32), seed1 ^ seed);
}
@Override
public @NotNull RandomSource fromSeed(long l) {
return new GJRAND64RandomSource(l);
}
@Override
public @NotNull RandomSource at(int x, int y, int z) {
long seed = Mth.getSeed(x, y, z);
return new GJRAND64RandomSource(seed0 ^ Long.rotateLeft(seed, 32), seed1 ^ seed);
}
@Override
public void parityConfigString(@NotNull StringBuilder stringBuilder) {
throw new UnsupportedOperationException();
}
}
}