Summary
Build the versus/co-op seat-select navigator as a first-class overlay view (apps/overlay), reusing the controller-core slot lifecycle, and harden the WebHID paths it exercises in packages/core. This replaces the throwaway game-side mockup (tandemonium/tools/lobby-mockup) — the navigator becomes Tandemonium's real lobby and reaches the game via sync-controller-core.
Done (initial branch)
- New view:
apps/overlay/src/lobby.html + src/js/lobby-app.js (sibling to multi.html / multi-app.js).
- Launch:
npm run start:lobby (electron . --lobby; main.js stateKey lobby, LOBBY_WINDOW_SIZE).
- Interaction on the manager slot lifecycle: press any button → claim slot → seat player; A = ready; B / hold-PS = leave (
releaseSlotToPool); ◀▶ = switch team; Start = proceed. Join→ready gate on CHOOSE LEVEL.
- DualSense lightbar + rumble per seat/team via driver feedback (feature-detected; other pads no-op).
Next: WebHID hardening in packages/core
Surfaced while building the view (renderer jank + unreliable recognition):
Notes
Design/UX (independent per-controller join, ready gate, LED/haptic) proven in the game-side mockup and ported.
Summary
Build the versus/co-op seat-select navigator as a first-class overlay view (
apps/overlay), reusing the controller-core slot lifecycle, and harden the WebHID paths it exercises inpackages/core. This replaces the throwaway game-side mockup (tandemonium/tools/lobby-mockup) — the navigator becomes Tandemonium's real lobby and reaches the game viasync-controller-core.Done (initial branch)
apps/overlay/src/lobby.html+src/js/lobby-app.js(sibling tomulti.html/multi-app.js).npm run start:lobby(electron . --lobby;main.jsstateKeylobby,LOBBY_WINDOW_SIZE).releaseSlotToPool); ◀▶ = switch team; Start = proceed. Join→ready gate on CHOOSE LEVEL.Next: WebHID hardening in
packages/coreSurfaced while building the view (renderer jank + unreliable recognition):
NotAllowedError: Failed to write feature report, causing ~4s renderer jank. Cache the working interface / stop re-probing. (Direct USB-C pid0x1302avoids lizard mode.)0x31) handshake often needs several retries ("full report mode did not start after 5 attempts — gyro unavailable until reconnect").electronAutoRequestDevicefails without a user gesture ("Must be handling a user gesture"); rely on the per-slot pair button +autoPoolApprovedHid, or rework boot pairing.Notes
Design/UX (independent per-controller join, ready gate, LED/haptic) proven in the game-side mockup and ported.