Files
tactical-shooter/docs/netfox.extras/guides/rewindable-random-number-generator.md
T
shawn b0c83af092 Fresh start: replace with naxIO/netfox-cs-sample foundation
Complete replacement of the tactical-shooter project with the
netfox-cs-sample (MIT) — a CS 1.6 inspired multiplayer FPS built
with Godot 4 and netfox.

## What's new
- Full CS-style gameplay: teams (T/CT), rounds, economy, buy menu
- 6 weapons: Knife, Glock, USP, AK-47, M4A1, AWP
- Bomb plant/defuse with 2 bombsites
- Flashbang & smoke grenades
- Proper netfox rollback netcode at 64 tick
- Network popup UI for host/join
- HUD, crosshair, round timer, scoreboard
- All netfox singletons registered as autoloads (works in exported builds)

## Architecture
- Listen-server (host from client, no dedicated server binary)
- Multiplayer-fps game lives at examples/multiplayer-fps/
- Netfox addons registered as autoloads for exported build compat
- Godot 4.7 with Forward+ renderer

## Removed
- Old headless-server architecture (client_main, server_main, player.gd, etc.)
- Custom netfox bootstrap with ENet fallback
- Old ChaffGames FPS template (2,420 lines, 844 KB)
- SimulationServer GDExtension stub
- Godot-jolt physics (netfox sample uses default Godot physics)
- Duplicate weapon_data.gd, anti_cheat.gd, round_manager.gd, etc.
- Server browser API Python venv (87 MB)
- test_range map and modular assets

## Preserved
- Git history
- Server config at config/default_server_config.cfg
- Windows export preset
- Build directory (gitignored)

Co-authored-by: naxIO <naxIO@users.noreply.github.com>
2026-07-02 20:55:20 -04:00

67 lines
2.1 KiB
Markdown

# RewindableRandomNumberGenerator
A random number generator that can be used inside the [rollback tick loop].
An important point for writing code that works well in rollback is that it
behaves the same given the same circumstances, no matter how many times it's
run. It also must behave the same no matter which peer is running it.
Godot's built-in [RandomNumberGenerator] is not aware of rollback, so it will
consistently return different numbers for each tick, and potentially on each
peer.
To fix that, the *RewindableRandomNumberGenerator* generates the same random
sequences on each peer, and for each tick.
It implements most of the same methods, so it's close to a drop-in replacement.
## Creating the generator
The *RewindableRandomNumberGenerator* requires a seed upon initialization. This
seed must be the same on all peers.
!!!warning
If two *different* RNGs use the *same* seed, they will also generate the
same random numbers. Make sure that you use different seeds for different
objects.
For RNG's used by singletons, hard-coding different seed values is a very
simple approach:
```gd
var rng := RewindableRandomNumberGenerator.new(15)
```
If these objects also have names or similar, consistent identifiers, a simple
hash works well too:
```gd
var rng := RewindableRandomNumberGenerator.new(hash("Exit beacon"))
```
For dynamically spawned objects, or just to avoid the possibility of a human
error, the node path can be hashed:
```gd
var rng := RewindableRandomNumberGenerator.new(hash(get_path()))
```
This assumes that the same node will be spawned under the same path on all
peers, which is also a requirement for RPCs to work.
## Generating random numbers
The *RewindableRandomNumberGenerator* can be used in the same way as Godot's
built-in [RandomNumberGenerator]. All the per-peer and per-tick consistency is
ensured under the hood:
```gd
var rng := RewindableRandomNumberGenerator.new(0)
var dice_roll := rng.randi_range(1, 6)
```
[rollback tick loop]: ../../netfox/guides/network-rollback.md
[RandomNumberGenerator]: https://docs.godotengine.org/en/stable/classes/class_randomnumbergenerator.html