Network sync: rollback / lockstep (deterministic)
Synchronises peers by inputs only: they run the same deterministic simulation, either predicting remote inputs and re-simulating on a misprediction (rollback) or waiting for every input of a frame (lockstep).
Network sync: rollback / lockstep (deterministic) (net.rollback) #
What it is for #
Synchronises peers by inputs only: they run the same deterministic simulation, either predicting remote inputs and re-simulating on a misprediction (rollback) or waiting for every input of a frame (lockstep).
It needs net.transport, input.actions, game.engine; installing it brings them in.
Turn it on #
Install the kit in a project, then change a setting (the values shown are its defaults):
gripforge_gamekit_install { project_id: "gkp_…", id: "net.rollback" }
gripforge_gamekit_configure { project_id: "gkp_…", id: "net.rollback",
config: { "mode": "rollback", "players": 2 } }
First example #
<!-- test: kits/net_rollback/tests/net_rollback.rs::input_actions_feed_the_arena_bits_when_no_input_is_set --> This is the body of the passing test input_actions_feed_the_arena_bits_when_no_input_is_set; the helper functions it calls are defined at the top of the same test file.
#[test]
fn input_actions_feed_the_arena_bits_when_no_input_is_set() {
let mut s = online(json!({}));
commands(&mut s);
s.apply(&json!({ "op": "key", "code": "Space", "down": true }))
.unwrap();
step(&mut s, 1);
let sent = inputs(&mut s);
assert_eq!(
sent[0]["v"].as_u64().unwrap() & 16,
16,
"jump is bit 16: {sent:?}"
);
s.apply(&json!({ "op": "key", "code": "Space", "down": false }))
.unwrap();
step(&mut s, 1);
assert_eq!(
inputs(&mut s).last().unwrap()["v"].as_u64().unwrap() & 16,
0
);
}
Settings and defaults #
Descriptions come from the kit manifest and stay in English.
| Setting | Type | Default | Range or values | Meaning |
|---|---|---|---|---|
mode | string | "rollback" | rollback, lockstep | rollback = predict + re-simulate; lockstep = wait for every input. |
players | integer | 2 | 1–8 | Slots of a match; it starts when all are filled. |
frameHz | integer | 60 | 10–120 | Simulation frames per second. |
inputDelay | integer | 2 | 0–30 | Local inputs apply this many frames later (hides latency, fewer rollbacks). |
maxRollback | integer | 8 | 0–30 | Never predict further than this past the last confirmed frame (stall instead). |
maxBehindFrames | integer | 30 | 1–600 | A peer more than this many frames behind the match clock catches up without rendering the frames in between. |
hashEvery | integer | 60 | 0–6000 | Frames between state hash checks (0 = off). |
maxPendingHashes | integer | 64 | 1–4096 | State hashes waiting for comparison per peer. |
hashWindowFrames | integer | 600 | 60–100000 | Relay: frames of state hashes kept for comparison. |
inputLogFrames | integer | 36000 | 600–1000000 | Relay: frames of input kept for resumed peers. |
maxAheadFrames | integer | 120 | 10–6000 | Relay: inputs further ahead of the match clock are refused. |
relayMs | integer | 50 | 5–1000 | Relay: resend period of unacknowledged inputs. |
orderResendMs | integer | 30 | 5–1000 | Peer: pending orders are batched and sent at most every max(2 frames, orderResendMs) (orders ride the reliable channel). |
resyncGapMs | integer | 2000 | 100–60000 | A peer that received nothing for this long asks the relay for a resync. |
seed | integer | 0 | 0–2147483647 | Match seed (0 = random). |
game | string | "arena" | arena, physics | The deterministic game every peer runs inside the core: the integer arena, or the net.physics arena (needs physics: shared). |
physics | string | "none" | none, shared | none, or shared = net.physics (engine physics is not deterministic across machines, so native is not offered). |
inputTimeoutMs | integer | 0 | 0–600000 | Relay: a connected player that sends no input for this long is declared left and disconnected (0 = off). |
orders | boolean | true | Relay: offer the structured orders channel (RTS commands, r.ord); gfnet-core peers only. | |
maxOrderBytes | integer | 1024 | 64–1024 | Largest order (canonical JSON bytes). |
maxOrdersPerFrame | integer | 4 | 1–32 | Orders per player and per frame. |
orderDelay | integer | 0 | 0–120 | Orders apply at least this many frames ahead (never earlier than inputDelay). |
turnMs | 0 | Turn-based lockstep (RTS style): turn length in ms (typically 100–200; 50–1000), 0 = off. | ||
turnDelay | integer | 2 | 1–10 | Turns between issuing an order and running it. |
adaptiveTurn | boolean | false | Relay: stretch the turn to the slowest round trip (never below turnMs, at most adaptiveTurnMaxMs). | |
adaptiveTurnMaxMs | integer | 500 | 50–2000 | Adaptive turns never grow past this (ms). |
adaptiveTurnPeriodMs | integer | 1000 | 100–60000 | Relay: the adaptive turn is re-evaluated this often. |
adaptiveTurnRttFactor | number | 1.2 | 1–4 | Relay: the adaptive turn covers the slowest round trip × this. |
Services, events, variables #
- Service
net.sync: The project replication model (one per project: the net.* sync kits conflict with each other). - Service
net.rollback: register(game), setInput(bits), state(), frame(); rollback / desync events. - Service
net.lockstep: The same session in strict lockstep (mode: lockstep). - Events emitted:
net.match_started(slot,players,seed) — All slots filled; frame 0 starts.net.desync(frame) — State hashes differ between peers (non-deterministic game code).net.slot_left(slot,frame) — A player left; its input is neutral fromframe.net.connected(id,resumed,transport) — Welcome received on a session reopened by register(game) (the first session reports it through the shared session mirror, as net.transport declares).net.peer(id,on) — Another peer joined or left a session reopened by register(game).net.refused(code,msg) — 1.4: the handshake of a session reopened by register(game) was refused (the core's code; mods: the server runs other mods, net.transport 1.3).
- Variables:
net.status(string) — Network statusnet.rtt(number) — Ping (ms)net.peers(number) — Players onlinenet.frame(number) — Framenet.rollbacks(number) — Rollbacks
Hooks and modding #
This kit declares no hook and no collection to mod.
Engines #
Declared targets: web, godot, unity, unreal. gripforge kit api net.rollback lists the exact settings and services of your version.
Versions #
Kit version 1.4.0.