Public: anyone can read this; the crew can change it.
forked from trevato/cs
multiplayer. i need to run this with my friends. surprised it’s not there yet… #312
Check · Review · Land · Live done — Landed and live in production.
Multiplayer lands as a room you can make from the menu and read a code out for. The round is stepped **on this server**, not in anybody's browser: `src/rooms/room.ts` runs the shooter's own `createWorld` and `updateWith` at 64 Hz, each member holds one seat (a bot's, so a round is always 5v5, handed straight back with its money and guns when they leave), and everyone is sent the same 544-byte pack…
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
Multiplayer lands as a room you can make from the menu and read a code out for. The round is stepped on this server, not in anybody's browser:
src/rooms/room.tsruns the shooter's owncreateWorldandupdateWithat 64 Hz, each member holds one seat (a bot's, so a round is always 5v5, handed straight back with its money and guns when they leave), and everyone is sent the same 544-byte packed snapshot sixteen times a second — measured, 8.7 kB/s a member down and 14 bytes a tick up. Verified against the running server over a real socket:POST /api/roomhands back a code, the upgrade delivershelloand then 15 snapshots in a second at 7.7 kB.The load-bearing change is first and on its own commit:
updateno longer applies oneInputtoworld.mebut asks for each body's input (updateWith), with the single-player game passing its own — the replay digests do not move andbun testis green (1283 pass).What to look at:
src/rooms/wire.tsis the whole protocol and the only boundary a client's bytes cross — a weapon id cannot be named on it, a switch is one of four things the server resolves against your body, a buy is an index the economy still refuses if the money is not there, and a frame of the wrong size is dropped rather than parsed.src/rooms/hub.tsholds the numbers with reasons: twenty rooms a process, ten people a room, 64-byte frames, a flood or a silent connection closed, an empty room forgotten after ninety seconds.src/server.tsis the only file that knows what a WebSocket is; a plain GET of/wsis the app's own 404. In the preview: make a room from the menu, open the code in a second browser, and watch both bodies in one round.What is not done and is stated on the page and in the README rather than faked: your own movement is not predicted, so it answers on the round trip (#305's remaining half, and the thing a CS player will notice first); a room has no hit marker or damage arrow, because both are effects recorded for one screen and a snapshot goes to everybody; a room's result is not posted to the leaderboard, so #168's trust half is untouched; and #302's bench with three candidate encodings was not written — the snapshot's size is asserted by a test in
src/rooms/rooms.test.tsand the CPU argument leans on the ceilingsrc/budget.test.tsalready holds. No new dependency. The app bundle's ceiling moves to 122,000 raw / 47,500 gzipped, copied frombun run scripts/build.ts, for the session and the codec. I did not open two real browsers against the preview — the socket was proved with a Bun client and the page's wiring is typechecked and booted bymain.test.ts, but the first thing a reviewer should do is play it with somebody.🤖 Generated with Claude Code
Budget reached at $10.25; this is where it stopped.
Closes #300