Unsynchronized deposit clump random

- Draw deposit clump randomness from a single-owner generator with the java.util.Random sequence
This commit is contained in:
Brian Neumann-Fopiano committed 2026-10-21 19:37:27 -04:00
1 parent 1821fedb24
commit e3135d8b01
2 files changed
+49 -1

No files matched your search

@@ -227,7 +227,7 @@ public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState
int engineHeight = getEngine().getHeight();
List<PreparedClump> clumps = new ArrayList<>(limit - first);
for (int l = first; l < limit; l++) {
RNG clumpRng = new RNG(clumpSeed(plan.seed(), l));
RNG clumpRng = new ClumpRandom(clumpSeed(plan.seed(), l));
if (k.getPerClumpSpawnChance() < clumpRng.d()) {
continue;
}
@@ -635,6 +635,30 @@ public class IrisDepositModifier extends EngineAssignedModifier<NativeBlockState
private record PackScan(IrisData data, boolean variants, boolean oreScaling) {
}
static final class ClumpRandom extends RNG {
private static final long MULTIPLIER = 0x5DEECE66DL;
private static final long ADDEND = 0xBL;
private static final long MASK = (1L << 48) - 1;
private long state;
ClumpRandom(long seed) {
super(seed);
}
@Override
public synchronized void setSeed(long seed) {
super.setSeed(seed);
state = (seed ^ MULTIPLIER) & MASK;
}
@Override
protected int next(int bits) {
state = (state * MULTIPLIER + ADDEND) & MASK;
return (int) (state >>> (48 - bits));
}
}
private record PreparedDeposit(IrisDepositGenerator generator, boolean ore, List<PreparedClump> clumps) {
}
@@ -19,6 +19,30 @@ public class IrisDepositModifierProbabilityTest {
assertEquals(0.04D, accepted / (double) samples, 0.003D);
}
@Test
public void clumpRandomMatchesRngDrawForDraw() {
RNG seeds = new RNG(-90181L);
for (int trial = 0; trial < 2_000; trial++) {
long seed = trial < 4 ? new long[]{0L, -1L, Long.MIN_VALUE, Long.MAX_VALUE}[trial] : seeds.nextLong();
RNG expected = new RNG(seed);
RNG actual = new IrisDepositModifier.ClumpRandom(seed);
for (int draw = 0; draw < 48; draw++) {
String label = "seed " + seed + " draw " + draw;
switch (draw % 8) {
case 0 -> assertEquals(label, Float.floatToIntBits(expected.nextFloat()), Float.floatToIntBits(actual.nextFloat()));
case 1 -> assertEquals(label, expected.nextInt(3), actual.nextInt(3));
case 2 -> assertEquals(label, Double.doubleToLongBits(expected.nextDouble()), Double.doubleToLongBits(actual.nextDouble()));
case 3 -> assertEquals(label, Double.doubleToLongBits(expected.d()), Double.doubleToLongBits(actual.d()));
case 4 -> assertEquals(label, expected.i(-5, 17), actual.i(-5, 17));
case 5 -> assertEquals(label, expected.nextInt(1_000_000_007), actual.nextInt(1_000_000_007));
case 6 -> assertEquals(label, expected.nextLong(), actual.nextLong());
default -> assertEquals(label, expected.nextBoolean(), actual.nextBoolean());
}
}
assertEquals(expected.getSeed(), actual.getSeed());
}
}
@Test
public void neighboringClumpChancesRemainIndependentAcrossBatchBoundaries() {
int samples = 100_000;