Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
import org.dreeam.leaf.config.EnumConfigCategory;
import org.dreeam.leaf.config.LeafConfig;

import java.util.random.RandomGeneratorFactory;

public class FastRNG extends ConfigModules {

public String getBasePath() {
Expand All @@ -14,11 +12,8 @@ public String getBasePath() {

public static boolean enabled = false;
public static boolean enableForWorldgen = false;
public static String randomGenerator = "Xoroshiro128PlusPlus";
public static boolean warnForSlimeChunk = true;
public static boolean useLegacyForSlimeChunk = false;
@Deprecated
public static boolean useDirectImpl = false;

public static boolean worldgen = false;
public static boolean worldgenEnabled() {
Expand All @@ -29,22 +24,14 @@ public static boolean worldgenEnabled() {
public void onLoaded() {
config.addCommentRegionBased(getBasePath(), """
Use faster random generator?
Requires a JVM that supports RandomGenerator.
Requires a JVM that supports Xoroshiro128PlusPlus.
Some JREs don't support this.""",
"""
是否使用更快的随机生成器?
需要支持 RandomGenerator 的 JVM.
需要支持 Xoroshiro128PlusPlus 的 JVM.
一些 JRE 不支持此功能.""");

enabled = config.getBoolean(getBasePath() + ".enabled", enabled);
randomGenerator = config.getString(getBasePath() + ".random-generator", randomGenerator,
config.pickStringRegionBased(
"""
Which random generator will be used?
See https://openjdk.org/jeps/356""",
"""
使用什么种类的随机生成器.
请参阅 https://openjdk.org/jeps/356"""));
enableForWorldgen = config.getBoolean(getBasePath() + ".enable-for-worldgen", enableForWorldgen,
config.pickStringRegionBased(
"""
Expand All @@ -63,21 +50,12 @@ public void onLoaded() {
to follow vanilla behavior.""",
"""
是否使用原版随机生成器来生成史莱姆区块."""));
useDirectImpl = config.getBoolean(getBasePath() + ".use-direct-implementation", useDirectImpl,
config.pickStringRegionBased(
"""
Use direct random implementation instead of delegating to Java's RandomGenerator.
This may improve performance but potentially changes RNG behavior.""",
"""
使用直接随机实现而不是委派给 RandomGenerator.
这可能会提高性能, 但可能会改变 RNG 行为."""));

if (enabled) {
try {
RandomGeneratorFactory.of(randomGenerator);
} catch (Exception e) {
LeafConfig.LOGGER.error("Faster random generator is enabled but {} is not supported by your JVM, " +
"falling back to legacy random source.", randomGenerator);
Class.forName("org.dreeam.leaf.util.math.random.FasterRandomSource");
} catch (Throwable ignored) {
LeafConfig.LOGGER.error("Faster random generator is enabled but Xoroshiro128PlusPlus is not supported by your JVM, " +
"falling back to legacy random source.");
enabled = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,45 +6,24 @@
import net.minecraft.world.level.levelgen.BitRandomSource;
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
import net.minecraft.world.level.levelgen.RandomSupport;
import org.dreeam.leaf.config.modules.opt.FastRNG;
import org.jspecify.annotations.NullMarked;

import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;

@NullMarked
public final class FasterRandomSource implements BitRandomSource {

private static final int INT_BITS = 48;
private static final long SEED_MASK = 0xFFFFFFFFFFFFL;
private static final long MULTIPLIER = 25214903917L;
private static final long INCREMENT = 11L;
private static final RandomGeneratorFactory<RandomGenerator> RANDOM_GENERATOR_FACTORY = RandomGeneratorFactory.of(FastRNG.randomGenerator);
private static final RandomGeneratorFactory<RandomGenerator> RANDOM_GENERATOR_FACTORY = RandomGeneratorFactory.of("Xoroshiro128PlusPlus");
private RandomGenerator delegate;
@Deprecated
private long seed;
public static final FasterRandomSource SHARED_INSTANCE = new FasterRandomSource(RandomSupport.generateUniqueSeed());
@Deprecated
private static final boolean useDirectImpl = FastRNG.useDirectImpl;

public FasterRandomSource(long seed) {
this.seed = seed;
this.delegate = RANDOM_GENERATOR_FACTORY.create(seed);
}

private FasterRandomSource(RandomGenerator.SplittableGenerator randomGenerator) {
this.seed = randomGenerator.nextLong();
this.delegate = randomGenerator;
}

@Override
public RandomSource fork() {
if (useDirectImpl) {
return new FasterRandomSource(this.nextLong());
}
return RANDOM_GENERATOR_FACTORY.isSplittable()
? new FasterRandomSource(((RandomGenerator.SplittableGenerator) this.delegate).split())
: new FasterRandomSource(this.nextLong());
return new FasterRandomSource(this.nextLong());
}

@Override
Expand All @@ -54,15 +33,11 @@ public PositionalRandomFactory forkPositional() {

@Override
public void setSeed(long seed) {
this.seed = seed;
this.delegate = RANDOM_GENERATOR_FACTORY.create(seed);
}

@Override
public int next(int bits) {
if (useDirectImpl) {
return (int) ((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> (INT_BITS - bits));
}
return (int) (nextLong() >>> (64 - bits));
}

Expand Down Expand Up @@ -98,73 +73,41 @@ public void parityConfigString(StringBuilder info) {

@Override
public int nextInt() {
if (useDirectImpl) {
return (int) (((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> 16) ^
((seed = seed * MULTIPLIER + INCREMENT & SEED_MASK) >>> 32));
}
return delegate.nextInt();
}

@Override
public int nextInt(int bound) {
if (useDirectImpl && bound > 0) {
if ((bound & -bound) == bound) {
return (int) ((bound * (long) next(31)) >> 31);
}
int bits, val;
do {
bits = next(31);
val = bits % bound;
} while (bits - val + (bound - 1) < 0);
return val;
}
return delegate.nextInt(bound);
}

@Override
public int nextInt(int origin, int bound) {
if (useDirectImpl && bound > 0) {
return origin + this.nextInt(bound - origin);
}
return delegate.nextInt(origin, bound);
}

@Override
public long nextLong() {
if (useDirectImpl) {
return ((long) next(32) << 32) + next(32);
}
return delegate.nextLong();
}

@Override
public boolean nextBoolean() {
if (useDirectImpl) {
return next(1) != 0;
}
return delegate.nextBoolean();
}

@Override
public float nextFloat() {
if (useDirectImpl) {
return next(24) / ((float) (1 << 24));
}
return delegate.nextFloat();
}

@Override
public double nextDouble() {
if (useDirectImpl) {
return (((long) next(26) << 27) + next(27)) / (double) (1L << 53);
}
return delegate.nextDouble();
}

@Override
public double nextGaussian() {
// delegate Gaussian distribution to RandomGenerator
// as direct implementation would be complex (i aint doin allat)
return delegate.nextGaussian();
}
}