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

forked from trevato/cs

A pasted link plays the match it names: the Match id field takes a URL, and the page stops promising what a bare id cannot keep #277

Merged opened this

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

Merged

The **Match id** field now takes what people actually copy — a bare id or a whole link from this page — and the page stops promising what a bare id cannot keep.

shipped production is serving it deploy ae07c2d

opened this

The Match id field now takes what people actually copy — a bare id or a whole link from this page — and the page stops promising what a bare id cannot keep.

src/matchlink.ts is the new module (no dependency; URL is the platform's). It reads a pasted URL and never follows it: the parsed origin must be this app's and the scheme http:/https:, only match and map are read, and both are revalidated through src/matchid.ts and src/mapname.ts — the path, the fragment and every other parameter are dropped. Another origin, a javascript: string, or a URL of ours with neither parameter on it is null, and the field then gets exactly what a bad id already got: the NOT_AN_ID sentence and a fresh match. A link with no ?map= reports de_forge, because that is the map following it gives — pasting a link and opening it are the same match on the same layout.

In src/client/main.ts the link is absorbed in one place: absorbLink writes the bare id into the id field and the map into the Map control (select plus name field, written the way the server renders the same ?map=), and chosenMap() is untouched and still the only reader of those two fields. readIdField wraps it, sets the line under the field, and hands start the match — so the id field is read once, on the keystroke and at Play both (a value set in code fires no event). A bare id writes nothing to the Map control. One behaviour changed beyond the issue: the "that is not a match id" line now appears as you type rather than only at Play, matching how the map's line has always behaved.

Copy is unchanged and still complete — Link to this match and the clipboard both carry ?match=…&map=…. The id's paragraph now says an id keeps the spawns, the bots and the seed and that the link is what keeps the map too; the This match paragraph no longer promises the layout for a bare id. The field's maxlength comes from LONGEST_PASTE so the input and the parser cannot disagree; src/server.test.ts's two assertions that pinned it at 64 were updated for that reason (the test was right about the old field, not about this one).

Tests: src/matchlink.test.ts covers the refusals and the round trip; src/client/main.test.ts adds four — a pasted link setting both controls and Play giving that layout and that match's world, a link set without a keystroke, a bare id leaving the Map control where the player left it, and a foreign-origin/javascript: link refused with the existing sentence; src/pages/game.test.ts holds the new copy honest. bun run test is 1228 passing. What I left alone: the id's grammar (it still carries no map), and #150 — a result still does not record its map.

To try it in the preview: press Play on generated, copy Link to this match, go back to the menu, set Map to de_forge, and paste that link into Match id — the map name reappears above Play and that is the match you get.

🤖 Generated with Claude Code

Closes #215

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs