Compare commits

...

3 Commits

6 changed files with 70 additions and 7 deletions

View File

@ -2,19 +2,32 @@
Better Random
=======
Or Better PRNG, is a mod which replace Minecraft's default
[Linear congruential generator](https://en.wikipedia.org/wiki/Linear_congruential_generator) (LCG for short, used for generating most of random game events)
##### Disclaimer
This mod changes RNG, and as such, affects worldgen greatly, so with this mod alone installed vanilla world seeds will no longer
be reproducible. If you care about preserving vanilla worldgen parity in your modpack, **refrain** from installing this mod.
You were warned.
### About the mod
Better Random, or Better PRNG if you prefer, is a mod which replace Minecraft's default
[Linear congruential generator](https://en.wikipedia.org/wiki/Linear_congruential_generator)
(LCG for short, used for generating most of random game events, as well as generator used when generating world features)
and Xoshiro128PlusPlus (used to generate "sequences" aka random generator used for `LootPool`s)
with a better random number generator, [gjrand](https://gjrand.sourceforge.net).
### Features:
* Replaces `RandomSupport#create`, and subsequently, `Entity#random`, `Level#random`, countless other places including mods;
* Replaces `RandomSupport#create`, and subsequently, `Entity#random`, `Level#random`, worldgen (but not noise map, which means world will have same elevation, but different feature placement), countless other places including mods;
* Replaces `RandomSequence` and `RandomSequences` with versions which use gjrand;
* Replaces `Level#getBlockRandomPos` to use `Level#random`. Previously, `getBlockRandomPos` utilized LCG with even worse properties than one of `Level#random`.
### Caveats:
* Slime chunk function was patched to be hardwired to LegacyRandomSource so they don't change with this mod installed.
### Compatibility:
Should be compatible with everything that doesn't go around public interfaces vanilla code provide.
Existing `RandomSequence` saved data is left untouched (in meaning that nothing is done to it through code,
but Minecraft continue to load/create it upon server start), and removing Better Random mid-game won't have any side effects.
but Minecraft continue to load/create it upon server start), and removing Better Random mid-game won't have any
noticeable side effects (but world generation *may* look weird after installing/removing the mod, because
`RandomSupport#create` is used to determine how to place world features, such as ores and trees).

View File

@ -34,7 +34,7 @@ mod_name=Better Random
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=BSD 2 Clause
# The mod version. See https://semver.org/
mod_version=1.0.0
mod_version=1.2.0
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html

View File

@ -1,6 +1,5 @@
package ru.dbotthepony.mc.prng;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.fml.common.Mod;
@Mod(BetterRandom.MOD_ID)

View File

@ -0,0 +1,44 @@
package ru.dbotthepony.mc.prng.mixin;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.XoroshiroRandomSource;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import ru.dbotthepony.mc.prng.GJRAND64RandomSource;
@Mixin(WorldgenRandom.class)
public abstract class WorldgenRandomMixin {
@Shadow
protected RandomSource randomSource;
// quite lazy solution because if someone genuinely want to get lcg they wont be able to
@Inject(
method = "<init>(Lnet/minecraft/util/RandomSource;)V",
at = @At("TAIL")
)
public void constructorMix(RandomSource randomSource, CallbackInfo info) {
if (randomSource instanceof LegacyRandomSource rng) {
this.randomSource = new GJRAND64RandomSource(rng.seed.get());
} else if (randomSource instanceof XoroshiroRandomSource rng) {
this.randomSource = new GJRAND64RandomSource(rng.randomNumberGenerator.seedHi, rng.randomNumberGenerator.seedLo);
}
}
@Overwrite
public static RandomSource seedSlimeChunk(int chunkX, int chunkZ, long levelSeed, long salt) {
return new LegacyRandomSource(
levelSeed
+ (long)(chunkX * chunkX * 4987142)
+ (long)(chunkX * 5947611)
+ (long)(chunkZ * chunkZ) * 4392871L
+ (long)(chunkZ * 389711)
^ salt
);
}
}

View File

@ -5,3 +5,9 @@ protected net.minecraft.world.RandomSequences includeWorldSeed
protected net.minecraft.world.RandomSequences includeSequenceId
public net.minecraft.world.RandomSequences$DirtyMarkingRandomSource
public net.minecraft.world.RandomSequences$DirtyMarkingRandomSource <init>(Lnet/minecraft/world/RandomSequences;Lnet/minecraft/util/RandomSource;)V
protected-f net.minecraft.world.level.levelgen.WorldgenRandom randomSource
public net.minecraft.world.level.levelgen.LegacyRandomSource seed
public net.minecraft.world.level.levelgen.XoroshiroRandomSource randomNumberGenerator
public net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus seedLo
public net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus seedHi

View File

@ -7,7 +7,8 @@
"mixins": [
"RandomSourceMixin",
"LevelMixin",
"ServerLevelMixin"
"ServerLevelMixin",
"WorldgenRandomMixin"
],
"client": []
}