From 7c41993a8faefe0ab3d05df2e47068f26b0ccbd5 Mon Sep 17 00:00:00 2001
From: Veton Shabani <68129513+vetonshabani0@users.noreply.github.com>
Date: Wed, 8 Jul 2026 12:30:47 +0200
Subject: [PATCH] Mission log: P3 (control profiles + 9 games + scan-to-join)
done; P5 connectivity solved, public deploy pending
Reflect the control-profile system and 9 games with tailored phone controls, the scan-to-join QR, and the connectivity fixes (IPv4 bind, same-origin single-port signaling, public TURN). P5 now scopes what's left for an always-on public URL.
---
docs/todo.md | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/docs/todo.md b/docs/todo.md
index d0d0c2f..8b8ec0b 100644
--- a/docs/todo.md
+++ b/docs/todo.md
@@ -72,9 +72,9 @@ title: TODO / Backlog
P2 ✓
Persistent game shell. Done. The launcher now loads a game into a full-screen iframe shell instead of navigating away, so the page — and its live WebRTC controller links — survive launch. Controller intents are relayed into the running game over postMessage (sc:intent), injected through each game's shared Input layer with no per-game change; Back returns to the menu still connected. Verified with two clients on one machine. (Phone-over-LAN play depends on direct P2P succeeding — see P5.)
-
Controls.define({profile, buttons:[{id,label,hold?}]}) posts to the launcher shell, which relays the layout to every phone over the DataChannel; the controller renders it dynamically (d-pad, or labeled buttons, with hold for held controls), bottom-anchored for thumbs. 9 games got tailored controls: pinball (flippers), minesweeper (Flag), icy-tower & bubble-trouble (movement), blackjack, slots, video-poker, flappy-bird, space-tower — most as pure Controls.define with no game-logic change. Also added scan-to-join: the launcher shows a QR (encoding the controller URL + room code) the phone scans to auto-join. Remaining: Phase 2 pointer profile (phone as trackpad) for fruit-ninja / candy-crush, and richer card-game buttons (poker Fold/Call/Raise, uno, ludo, bridge).
ws://<host>:8080) for dev. Host it for non-LAN play (add wss:// + a public origin, and optional TURN for networks where direct P2P fails).
+ Public multiplayer deploy. Connectivity is solved for dev and verified with a real iPhone as controller. Three fixes made it work: (1) signaling binds IPv4 0.0.0.0 (the default was IPv6-only, unreachable by LAN phones); (2) web-api can serve the app and the WebSocket same-origin on one port (STATIC_DIR → npm run serve:app) — needed because iOS Safari only lets a page reach its own origin host:port, so cross-port signaling and a local TURN are unreachable from a phone; clients now default signaling to the page origin; (3) a public TURN (free-tier) relays when direct P2P fails (iOS mDNS / cross-network). Still needed for an always-on public URL a friend can use off-LAN: host web-api on a public host with wss:// (e.g. Render, or the college box) + our own coturn. GitHub Pages serves the static app but has no signaling/TURN, so Pages alone isn't playable; a dev cloudflared tunnel works only when the host network allows it. See web-api / transport architecture.