A room you can share by link, a code you can type, and a name to be called
Multiplayer setup moves out of a canvas modal and a prompt() dialog into one menu screen: your name, the two ways to host, and the friend's code. The socket opens from the menu and the game stays parked behind the overlay until the room fills — netHooks.paired takes the court one line before netStart writes to it — so the room code can carry a real SHARE button and a wrong code is a typo you fix rather than a CONNECTION LOST card over a match that never began. The name is the world board's name (stats.saveName), crosses on the existing look message, and the scoreboard finally names the person instead of CPU. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
ad258ace97
commit
425c18dcb6
7 files changed
+255
-75
No files matched your search
+42
-2
@@ -414,6 +414,46 @@ zombie (now an occasional opponent, `TUNE.racketEvery`, not the every-game fixtu
|
||||
`RETURNED`, `DOUBLE KILL`) is a footnote to something you already watched happen. Sharing the loud
|
||||
FACE with the milestone cards is right; sharing their SIZE made every footnote read as a milestone.
|
||||
|
||||
## Session log: THE NETPLAY LOBBY — a link to send, a code to type, a name to be (2026-08-15)
|
||||
|
||||
Oliver: *"multiplayer should be easier to setup — a share with link next to the code; also entering
|
||||
the code is done in some plain js confirm dialog thingy, this could be embedded more nicely;
|
||||
somewhere when hosting or also when joining the player should name themselves."* All three are one
|
||||
screen (`#vs`, `index.html` + THE LOBBY in `main.js`); the protocol underneath is untouched.
|
||||
|
||||
- **THE LOBBY IS A MENU SCREEN, and that is the whole structural change.** Hosting used to call
|
||||
`start('classic')` first and show the room code in a CANVAS modal over an empty court — which
|
||||
cannot carry a share button, cannot be typed into, and turned a mistyped code into a CONNECTION
|
||||
LOST card over a match that never began. The socket is opened from the menu now and the game
|
||||
stays parked behind the overlay until the room actually fills. **`netHooks.paired` is what takes
|
||||
the court**, called at the top of `netStart` — one line before everything that writes to it, so
|
||||
the kit/tour selection `start()` performs is already done when the `look` message reads it.
|
||||
Two more hooks join `intoSplatter`: `room` (the code landed) and `lost` (returns true when the
|
||||
lobby said so itself, which is what suppresses the card). Headless leaves them null.
|
||||
- **SHARE THE LINK, then the code.** `navigator.share` is the phone's own sheet — the friend is in
|
||||
WhatsApp, not in a room reading letters aloud — with `clipboard.writeText` as the desktop
|
||||
fallback and the four letters still big on screen for when they are in the same room. The link is
|
||||
the URL door that already existed (`#net-ABCD`): it opens the lobby with the code prefilled,
|
||||
ONE tap from the court. Deliberately not an auto-join — that tap is where the joiner sees, and
|
||||
can change, the name the other phone will call them.
|
||||
- **ONE NAME PER PLAYER.** The field is prefilled from `stats.savedName()` and written back through
|
||||
the new `stats.saveName` (which `submit` now shares), so the world board's name and the netplay
|
||||
name cannot become two things. It crosses on the EXISTING `look` message as `n` — no new message
|
||||
type, and an older build simply sends none. **The scoreboard names the person** (`render`, the
|
||||
names block) in both netplay modes: FRIEND until the look lands, never CPU. A stranger's string
|
||||
lands in an 8-character slot, so it is normalised at the RECEIVING end through the same
|
||||
`tidyName` the board and `server.py`'s `clean()` agree on.
|
||||
- **Failure is a typo now, not a card.** A short code never opens a socket; `gone` puts
|
||||
NO SUCH ROOM — CHECK THE CODE over the picker with the field still there. CANCEL and the header
|
||||
chevron both `endNetVs`, so a room you walked out of gives its socket back.
|
||||
- Verified through the real relay in two panes: host → share link → join → both take the court,
|
||||
host serves, the board reads YOU / GUEST, and the death-match room rebuilds both courts the same
|
||||
way (blood pips, the friend as the living opponent, no roster body). 96 tests.
|
||||
- Smaller: the JOIN button is the crimson plate stretched to the field's own height (`#vs .joinrow
|
||||
.btn` — a bare `.joinrow .btn` loses to `#vs .btn`'s margin, and a margin on a stretched flex
|
||||
item is exactly the 8px it was coming up short by); `.tin` is now the one typed-field look, worn
|
||||
by the name prompt and both lobby fields.
|
||||
|
||||
## Session log: gore opens in the gore, the theme comes back, three boards (2026-08-15, same day)
|
||||
|
||||
Oliver's finetuning pass on the batch below.
|
||||
@@ -678,8 +718,8 @@ agree on the same point from opposite perspectives). 73 tests.
|
||||
serve and rally AI are gated off, `restartRun` closes the socket.
|
||||
- **Honest limits, all deliberate (ponytail)**: NO reconnect-and-resume — a dropped radio is a
|
||||
CONNECTION LOST card and a reload (the recorded plan calls reconnection "the bulk of the real
|
||||
work"; a prototype must not start there). prompt() is the join UI. The scoreboard still says
|
||||
CPU. A return snaps the ball to the mirrored strike (~latency of drift eaten in one hop; the
|
||||
work"; a prototype must not start there). ~~prompt() is the join UI. The scoreboard still says
|
||||
CPU.~~ *(both gone — see THE NETPLAY LOBBY above.)* A return snaps the ball to the mirrored strike (~latency of drift eaten in one hop; the
|
||||
flight swallows it). Runs bank as classic runs. The wound-decay hook (losing IS zombification)
|
||||
is the recorded next step once the feel survives a two-phone playtest.
|
||||
- **Test on staging with two phones** — the relay deploys with the ordinary push, nothing to
|
||||
|
||||
Reference in new issue
Block a user