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

forked from trevato/cs

A room is a link you send, and your friend lands on your side #378

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

A room is now a link you send, and the side you sit on is yours to pick. The second friend who asks for T sits on T, as long as a bot is still there to give up its seat.

shipped production is serving it deploy ae07c2d

opened this

A room is now a link you send, and the side you sit on is yours to pick. The second friend who asks for T sits on T, as long as a bot is still there to give up its seat.

The link. /?room=CODE fills in the menu's Room code field with the code, and the client moves the focus to Join once the game is ready. It never joins by itself, because pointer lock needs a press. The server reads ?room= with roomCodeFrom and escapes it on the way out. Anything it rejects (a script, the wrong length, a character outside the alphabet) is ignored: server.test.ts checks that each of those links returns exactly the same bytes as /. Copy this room's link sits beside the code field and appears only when the field holds a valid code. It works like the map's copy link: a real link first, the clipboard when the browser offers one. While you play, the link under the stage becomes Link to this room. The link is built in one place, src/roomlink.ts, because both the page and the client build it.

The side. Room side (Either, Counter-Terrorists, Terrorists) sits beside the code field. Like the other menu controls it is at least 44px, and it is remembered like the name (cs.roomside). The socket upgrade takes team=t|ct, and sideFrom in src/rooms/room.ts checks it both in src/server.ts and inside join. freeSeat(room, wanted) puts you in a bot's seat on the side you asked for. If that side is all people, you go to the other side and the room line says so in a sentence (sideFull). A missing or junk team falls back to the same balancing as today. Nobody who is already seated is moved, and five friends against five bots is allowed without being rebalanced.

Engine change to review. To get the side from the socket to the room, RoomGame.join and Hub.enter in src/engine/rooms.ts take an optional asked argument. The hub passes it through without reading it, and it is documented in GUIDE.md. This is a change to the shared engine interface rather than to the game alone.

Who is here. The client session now keeps the latest roster: who is here, their side, and your own side. roomLine turns it into text such as Room 8UTZQR — In the room. 2 here: ada (T), you (you, CT). That line appears on the menu's room line and in the pause panel, and it changes whenever the server sends a new roster.

Not done:

  • You cannot see who is in a room before joining it. That would need a new endpoint that lets anyone holding a code read the room's names.
  • There is no auto-join from the link.
  • The single-player Side select is left as it is.
  • The terminal gets nothing new, since it has never joined rooms.
  • The issue names src/rooms/rooms.test.ts, which does not exist, so the room tests went into src/rooms/room.test.ts.

Tests. Each test below would fail without this change:

  • room.test.ts: two joins asking for T both land on T; a join asking for a full side lands on the other; junk or no side matches the balanced seat.
  • hub.test.ts: the side reaches the room's join.
  • server.test.ts: team= over real sockets, and the byte-identical junk ?room= pages.
  • game.test.ts: the field prefilled, the link, the side control, and escaping.
  • session.test.ts: the room line and the full-side sentence.
  • main.test.ts: Join gets the focus with no join, team is in the socket URL, the side is remembered, and the link copies.

Two existing tests changed. session.test.ts compares the whole standing() object, so two expected values gained the new fields. stage.test-helper.ts lists the page's ids, so it gained roomside and copyroom. The README's rooms section now says a room is a link and a side. bun run test (typecheck, then 1526 tests) passes.

To try it in the preview: press Make a room, then Esc and Leave match, and copy the room's link from the menu. Open it in a second browser, pick Terrorists, and press Join.

🤖 Generated with Claude Code

Closes #315

commented

A room is now a link you send, and the side you sit on is yours to pick. The branch has main merged in: main added server-written room results (#377) and a remembered Side and Length for single-player, and both are kept alongside this change. bun run test (typecheck, then 1555 tests) passes.

The link. /?room=CODE fills in the menu's room code field, and the client moves the focus to Join once the game is ready. It never joins by itself, because pointer lock needs a press. The server reads ?room= with roomCodeFrom and escapes it on the way out. A code it rejects (a script, the wrong length, a character outside the alphabet) is ignored, and the page is byte for byte the one with no parameter. Copy this room's link sits beside the code field and shows only when the field holds a valid code. While you play, the link under the stage becomes Link to this room. The link is built in one place, src/roomlink.ts.

The side. Room side (Either, Counter-Terrorists, Terrorists) sits beside the code field and is remembered as cs.roomside. The socket upgrade takes team=t|ct, and sideFrom checks it both in src/server.ts and inside join. freeSeat(room, wanted) puts you in a bot's seat on the side you asked for. If that side is all people, you go to the other side and the room line says so. A missing or junk team keeps today's balancing, and nobody already seated moves. To get the side from the socket to the room, RoomGame.join and Hub.enter in src/engine/rooms.ts take an optional asked argument that the hub passes through without reading. It is documented in GUIDE.md.

Who is here. The room line and the pause panel list each person in the room and their side, from the roster the server sends. The line changes when somebody arrives or leaves.

Where the merge met main:

  • The socket's Joined type is now Seated & { team }, so it carries both the identity that #377 verifies at the upgrade and the side you asked for.
  • The menu's room paragraph keeps #377's sentence about who a finished match counts for, next to the text about the link and the side.
  • The room-side value read back from storage is savedRoomSide, so it does not clash with the single-player savedSide that main added.

Not done:

  • You cannot see a room's people before you join, because that would let anyone holding a code read the names.
  • There is no auto-join from the link.
  • The terminal gets nothing new.
  • The room tests went into src/rooms/room.test.ts, because the src/rooms/rooms.test.ts the issue names does not exist.

Tests changed rather than added. session.test.ts compares the whole standing() object, so two expected values gained the new fields. stage.test-helper.ts lists the page's ids and gained roomside and copyroom.

To try it in the preview: press Make a room, then Esc and Leave match, and copy the room's link. Open it in a second browser, pick Terrorists, and press Join.

🤖 Generated with Claude Code

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs