add generic stateful input streaming
All checks were successful
build / image (push) Successful in 50s

This commit is contained in:
Syncer Deploy
2026-08-28 11:27:53 -03:00
parent 0bf2b95755
commit 96b73922cc
15 changed files with 767 additions and 81 deletions

View File

@@ -91,6 +91,48 @@ const protocol = game.protocol;
Flux Relay in `packages/shared/src/flux-game.ts` is the compact reference implementation. Both games are mounted by the same `hostNetworkedGame()` transport adapter, demonstrating that the server loop has no shooter knowledge.
## Stream stateful input safely
`withInputStream()` turns edge-only input delivery into an acknowledged
latest-state stream. Changes receive a new sequence immediately; unchanged
heartbeats resend the exact same packet, so they refresh the authority timeout
without executing an action twice. If the stream goes silent, the server
applies one developer-defined neutral input instead of allowing stuck movement:
```ts
const streamedGame = withInputStream(game, {
heartbeatRateHz: 20,
timeoutMs: 400,
inputsEqual: (left, right) =>
left.forward === right.forward &&
left.fire === right.fire &&
left.reload === right.reload,
neutralize: (lastInput) => ({
...lastInput,
forward: 0,
fire: false,
reload: false,
}),
// A heartbeat after a timeout may restore persistent state, but must strip
// edge actions that are not allowed to execute again.
resume: (lastClientInput) => ({
...lastClientInput,
reload: false,
}),
});
const inputStream = createInputStateStream(streamedGame);
inputStream.update(currentInput);
const emission = inputStream.consume(performance.now());
```
`emission.kind === "state"` receives a new `engine.createInput()` packet.
`"heartbeat"` resends the previously encoded packet verbatim. This preserves
exactly-once sequence semantics while the generic authority owns timeout and
resume behavior. Stream state is part of deterministic checkpoints, so time
travel and branching reproduce the same dead-man-switch decisions. Apply this
HOF before authority wrappers such as lag compensation and time travel.
## Scale a game with spatial replication
`withSpatialReplication()` wraps any networked game with a deterministic grid index, per-viewer interest selection, priorities, and an explicit byte budget. The ordinary visibility callback still runs first, so this layer can reduce an already-safe projection but can never reveal private authority state:
@@ -292,6 +334,7 @@ Replication is perception-aware. A client snapshot includes itself, public picku
- Private authoritative snapshot history and developer-defined client-state validation.
- Client prediction and reconciliation from server snapshots.
- Ping/pong RTT, jitter, clock-offset estimation, and adaptive input lead.
- Latest-state input heartbeats, duplicate-safe sequence reuse, and deterministic authority timeouts.
- Per-viewer state projection and internal-event-to-perception filtering.
- Generic binary message framing around developer-provided input, visible-state, and perception codecs.
- Optional visibility grouping for sharing encoded snapshots without weakening privacy.