Class DeterministicRNG
A fast, deterministic, thread-safe pseudo-random number generator. Drop-in replacement for Random in all game code.
Algorithm: xoshiro128** (Blackman & Vigna, 2018). Period: 2^128 − 1. Passes BigCrush. Thread safety: no shared mutable state — each instance is independent.
API surface matches the subset of Random used in
this codebase: Next(), Next(int), Next(int,int),
NextDouble(), NextFloat(), Range(int,int),
Range(float,float).
A static Shared instance is provided for fire-and-forget
usage that does not require determinism (replaces UnityEngine.Random).
public sealed class DeterministicRNG
- Inheritance
-
DeterministicRNG
- Inherited Members
Constructors
DeterministicRNG()
Creates a new unseeded RNG using TickCount for a non-deterministic seed. Use this only for server-side cases where determinism is not required (e.g., loot rolls, shuffle).
public DeterministicRNG()
DeterministicRNG(int)
Creates a new RNG seeded from an integer. Uses a Murmur3-finalizer counter mix to expand the single int seed into 128 bits of state.
public DeterministicRNG(int seed)
Parameters
seedintDeterministic seed value.
DeterministicRNG(uint, uint, uint, uint)
Creates a DeterministicRNG from raw xoshiro128** state words. Used to restore the exact generator position during reconcile, since the 128-bit state cannot be reconstructed from a single 32-bit output.
public DeterministicRNG(uint state0, uint state1, uint state2, uint state3)
Parameters
state0uintFirst state word.
state1uintSecond state word.
state2uintThird state word.
state3uintFourth state word.
Fields
Shared
Global shared instance for non-deterministic / fire-and-forget usage.
Replaces UnityEngine.Random for all game code.
NOT thread-safe — use only from the main thread (same contract as UnityEngine.Random).
public static readonly DeterministicRNG Shared
Field Value
Methods
CaptureState(out uint, out uint, out uint, out uint)
Captures the full 128-bit xoshiro128** state for serialization. Must be included in reconcile data alongside or instead of the single-int seed — storing only the seed causes permanent desync after any prediction mismatch because the 128-bit generator state cannot be reconstructed from a 32-bit output.
public void CaptureState(out uint state0, out uint state1, out uint state2, out uint state3)
Parameters
state0uintFirst state word.
state1uintSecond state word.
state2uintThird state word.
state3uintFourth state word.
Next()
public int Next()
Returns
Next(int)
Returns a non-negative random integer less than maxValue.
Equivalent to Next(int).
When maxValue is a power of two (including 1), a single
bitmask replaces the rejection loop — Next(1) costs exactly one
FishMMO.Shared.DeterministicRNG.NextRaw() call. The rejection-sampling path for non-power-of-two
values is unchanged, preserving the same output sequence.
public int Next(int maxValue)
Parameters
maxValueintExclusive upper bound (must be > 0).
Returns
Next(int, int)
Returns a random integer in the range [minValue, maxValue).
Equivalent to Next(int, int).
The range is computed as long to avoid overflow when
maxValue − minValue > MaxValue.
public int Next(int minValue, int maxValue)
Parameters
Returns
NextDouble()
Returns a random double in the range [0.0, 1.0). Equivalent to NextDouble(). Uses 32 bits of entropy (sufficient for float/game use). All game code should prefer NextFloat() or Range(float, float) which avoid double-promotion overhead.
public double NextDouble()
Returns
NextFloat()
Returns a random float in the range [0.0f, 1.0f).
Drop-in replacement for UnityEngine.Random.value.
Computed entirely in float — no double promotion.
public float NextFloat()
Returns
Range(int, int)
Returns a random integer in the range [min, max).
Drop-in replacement for UnityEngine.Random.Range(int, int).
Alias for Next(int, int).
public int Range(int min, int max)
Parameters
Returns
Range(float, float)
Returns a random float in the range [min, max).
Drop-in replacement for UnityEngine.Random.Range(float, float).
public float Range(float min, float max)
Parameters
Returns
RestoreState(uint, uint, uint, uint)
Restores the full 128-bit xoshiro128** state from previously captured values. Call this instead of allocating a new instance during reconcile to avoid per-tick heap allocation.
public void RestoreState(uint state0, uint state1, uint state2, uint state3)