# Netcode

Multiplayer is not available to games yet; these notes are the rules scripts will run under once it is.

The networked-play notes that concern scripts and the engine host. Transport, rollback and sessions will be
documented here as they are built; this file starts with what the host side has settled.

## Mixed sessions

A match may have browser peers and desktop peers together.

1. **Physics agrees.** The browser build steps the same world bit for bit as the shipped desktop engine.
   - `crates/physics-digest` compares the two tick by tick, and both run Rapier's deterministic maths.
2. **Scripts agree** when every peer runs `HostConfig::networked().with_web_peers()`.
   - The preset counts calls, limits call depth to 256, refuses promise jobs, removes `SharedArrayBuffer` and gives
     scripts a `Math` that is the same bits on every engine and OS (`script_math.js`; `**` is refused, use `Math.pow`).
   - `with_web_peers()` gives desktop peers only the `ctx` members the browser serves.
   - Peers compare `determinism_digest()` in the handshake and refuse a mismatch.
3. **The cost is the browser's gap.** A behaviour that calls a member the browser does not serve throws
   `WebUnsupportedError` on every peer.
   - The members a desktop peer loses, and when each comes to the browser, are the generated table in `docs/API.md`
     (the networked-session section); `crates/host/src/web/served.json` is its source.
   - Every member the web host serves shrinks it.
4. **Sound is presentation.** `ctx.audio.play` gives the same voice numbers everywhere, and the browser plays it through
   WebAudio (kira's cpal backend). A browser holds sound until the player's first click, key or touch on the page, so a
   browser peer is silent until then; the voices and their numbers run all the same.
5. **Where it stands (20 Oct 2026).** Every sample (hop-lane, kart-starter, lantern-hollow, pebblewind-heights,
   twin-trail) and `games/duel-yard` runs in the browser with no script errors, on the web host the merge queue holds.
   - The browser serves 186 of the 270 handle members. The 84 left are in groups no sample's own code calls: joints,
     navigation, tilemaps, most of the camera's screen maths, the environment's readers, the audio mixer's bus and
     music controls, part of the animator, players and views, the world's spawn and grab queries, labels, render
     parameters, input rebinding and `entity.setParent`.
   - A behaviour that calls one of them still throws `WebUnsupportedError` on every peer of a mixed session.

