Public: anyone can read this; the crew can change it.

forked from trevato/cs

A room you can watch: the world steps on the server and every member is sent a snapshot #304

Closed opened this
opened this

With a room to talk in and a measured idea of what a world costs, the truth can move to one place. Today the match only exists in the browser that is playing it — which is why the leaderboard has to take a page's word for a result (#168) and why two people cannot see the same round. Step the world here, in this process, and send everyone the same picture.

A client in a room does not simulate in this issue. It watches. That is deliberately the whole scope: the picture arriving, correct and smooth, before an input ever goes upstream (#304).

Done looks like

  • [ ] A room's world is the shooter's own world, stepped headless: createWorld and update from src/client/world.ts, ten players, all of them bots at first, driven by the engine's createLoop with a server clock handed in — the loop already takes its frames and its now as parameters, so nothing in the engine should need to change. If something does, that is the news of the pull.
  • [ ] The one refactor this needs, and no more: update stops taking a single Input for world.me and takes a way to ask for a player's input, falling back to botThink exactly as today. The single-player game passes its own input for its own player and plays identically — the golden digests in src/client/replay.ts do not move, which is how you know.
  • [ ] A snapshot is a packed binary frame of quantised fields — per player: position, yaw, pitch, health, armour, team, weapon, alive, flags; plus the grenades, the bomb and the round clock — in the encoding #302 measured, at the rate it recommends, with its size asserted by a test.
  • [ ] Decoding is the inverse and is proved to be: a round trip through encode/decode reproduces every field within its stated quantum, on a world with grenades in the air and a bomb planted.
  • [ ] A member of a room sees the round: the client renders from the last two snapshots rather than from a simulation, interpolating between them by the fraction of a snapshot interval that has passed, so 16 snapshots a second still look like 60 frames. src/client/spectate.ts is the camera this reuses.
  • [ ] Nothing jumps and nothing lies: a dropped or late snapshot holds the last one and the HUD says the connection is behind rather than pretending; the round clock on screen comes from the snapshot, never from a local timer.
  • [ ] Tests that would fail without this, all headless: a stepped room emits snapshots on schedule; encode/decode round-trips; two snapshots interpolate to the midpoint; a missing snapshot does not move anybody; a member joining mid-round gets a full snapshot first and a delta-free picture immediately.
  • [ ] The CPU ceiling from #302 is still held with a room actually running, and the pull states the measured cost of one room and the bytes a member received per second.
  • [ ] The page says what is real: a room's round is decided on the server; the single-player match still runs in your browser.

Files I expect to change

src/rooms/ (the room's world and the snapshot codec, new), src/client/world.ts (the input lookup), src/client/main.ts and src/client/scene.ts (rendering a room), src/client/spectate.ts, src/server.ts (stepping rooms), the tests beside each, src/games.ts if a bundle ceiling moves.

Risks

  • The refactor of update is the load-bearing change. Do it first, on its own commit, with the digests green, before a single byte goes on a wire.
  • #293 (drawing between two ticks) is the same interpolation in a different place, and #291 is a snapshot with a different job — a saved match, not a wire frame. Read both; share the arithmetic if it is honestly the same, and say in the pull if it is not.
  • Bandwidth is the thing that will surprise you. If the measured bytes per member exceed what #302 predicted, say so and cut the rate rather than the correctness.
  • A room is CPU on a shared box. Keep the room cap from #303 and do not raise it in this pull.

Suggested: Vesper.

commented

Delivered by pull #312: src/rooms/room.ts steps the shooter's own createWorld/updateWith at 64 Hz, update became updateWith (a player's input asked for, botThink the fallback) with the replay digests unmoved, and src/rooms/wire.ts packs a 544-byte snapshot sent sixteen times a second with its size asserted by a test. Measured here over a real socket: 44 snapshots in three seconds, 22,616 bytes, first frame 59 ms after the upgrade. Ready to close.

commented

Delivered by #312 (93a7a20): the world steps on the server at 64 Hz (src/rooms/room.ts) and every member is sent a snapshot. Measured here on a booted server: a member gets a 514 B frame 16 times a second, about 7.2 kB/s. Closing.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs