Summary
I would like to request exposing the internal state of Random through a read-only Product property (or equivalent), along with support for constructing a Random object from that value.
Example:
local rng = Random.new(12345)
local product = rng.Product
local restored = Random.new(product)
print(rng:NextInteger(1, 100))
print(restored:NextInteger(1, 100))
-- Always produces identical results.
Alternatively, if Product already represents the internal state after seed initialization, the constructor could simply accept either a seed or a previously generated product transparently.
Motivation
Currently, Random.new(seed) guarantees deterministic output only when starting from the beginning of the sequence.
However, once several random values have already been generated, there is no way to serialize the current state of the generator and resume from that exact point later.
Exposing the generator’s current state would make Random fully deterministic and resumable.
This would enable:
- Save/load systems for procedural generation.
- Network synchronization.
- Deterministic replay systems.
- Checkpointing simulations.
- Debugging by reproducing an exact random sequence.
- Serialization of generator state.
Example
Without this feature:
local rng = Random.new(42)
rng:NextNumber()
rng:NextNumber()
-- There is currently no way to recreate this exact state.
With this feature:
local rng = Random.new(42)
rng:NextNumber()
rng:NextNumber()
local product = rng.Product
-- Save product...
local restored = Random.new(product)
-- Continues from the exact same point.
Why not just store the seed?
A seed only represents the initial state.
After any random values are generated, the internal state changes.
Reconstructing the generator by using only the original seed requires replaying every previous random call, which is inefficient and often impossible if the exact history is unavailable.
Saving the current generator state avoids this entirely.
Proposed API
local rng = Random.new(seed)
local state = rng.Product -- read-only
local restored = Random.new(state)
or, if preferred,
local rng = Random.new(seed)
local state = rng.Product
local restored = Random.fromProduct(state)
Benefits
- Makes
Randomfully serializable. - Enables deterministic replay.
- Simplifies debugging.
- Improves procedural generation workflows.
- Eliminates the need to replay an entire sequence just to restore generator state.
- Minimal API surface: only a single read-only property (and optionally a dedicated constructor) is required.
I believe this would significantly improve the usability of Random while remaining backwards compatible.