add online multiplayer via Cloudflare Workers and Durable Objects - #27
Open
kgregory wants to merge 8 commits into
Open
add online multiplayer via Cloudflare Workers and Durable Objects#27kgregory wants to merge 8 commits into
kgregory wants to merge 8 commits into
Conversation
Implements real-time two-player online mode using WebSockets. Players share a room code to connect; the server (Cloudflare Durable Object) is authoritative for all game state. Migrated from Partykit SDK to native Cloudflare Workers + WebSocket Hibernation API for deployment reliability. - New Cloudflare Worker in party/index.ts with GameRoom Durable Object - LobbyScreen for creating/joining rooms via room code or shareable link - useOnlineGame hook managing WebSocket lifecycle and server state sync - LocalPlayScreen extracted from index.tsx to isolate local game flow - PlayScreen for mode selection (local vs online) - EndScreen updated with online-specific messaging (quit/opponent left) - GameState context guards dimension resets in online mode (server is authoritative) - Shared partyTypes.ts for client/server message contracts - wrangler.toml replaces partykit.json; partykit devDependency removed Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
partysocket v1.x changed the default URL from /party/{room} to
/parties/{name}/{room} (name defaults to "main"). Update the Worker
regex to match the new format.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a player's socket drops and partysocket reconnects before the old socket is cleaned up, the server rejects the new connection as full. Previously this called socket.close(), permanently stopping reconnection. Now we only stop reconnecting if we never received a welcome (genuine rejection). If we already connected once, let partysocket retry — the old socket will be cleaned up and the reconnect will succeed. Also clear errorMessage on welcome so stale errors disappear after recovery. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
localPlayer was a live prop, not frozen in the EndSnapshot. When
navigating back to menu, useOnlineGame cleanup called setLocalPlayer(null)
before animating was set to true, causing one frame where winner was
set but localPlayer was null — hitting the "${winner} wins!" branch
instead of "You win!"/"You lose."
Fix: include localPlayer in the EndSnapshot so it stays stable through
the fade-out transition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two issues: (1) text-transform: capitalize applied to the whole string
capitalizes the letter after the apostrophe in some browsers, giving
"Red'S" instead of "Red's" — fixed by applying capitalize only to the
player name span. (2) gameMode flips to "local" in the same render
batch as setScreen("start"), so the local turn text flashed for one
frame before animating became true — fixed by guarding on
screen === "playing" so nothing renders during the transition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…line - Lobby phase replaces the auto-start 2-player flow: players join and wait until the host clicks Start Game (enabled at ≥2 players, max 4) - Player list shows all connected players with their chip, color name, host badge, and "(you)" marker - Server assigns colors in join order (red→yellow→purple→green); turn rotation uses gamePlayers recorded at game-start time - partyTypes: add lobbyPlayers/gamePlayers to RoomState, add start_game client message, replace "waiting" phase with "lobby" - Worker deployed to Cloudflare Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
kgregory
added a commit
that referenced
this pull request
Jul 30, 2026
- Consolidate BoardDisplay + BoardShell into a single Board component - Extract PlayingScreen to encapsulate the playing view alongside StartScreen/EndScreen - Move DecorativeBoard into StartScreen as a private implementation detail - Add Heading component shared across all three screens - Add PlayerChips component with active-player emphasis and opacity for inactive chips - Make QuitButton dumb (onQuit prop) and add expand/collapse confirmation pattern - Add reset-to-defaults to GameSettings settings expansion - Fix DecorativeBoard vertical centering (spanStart formula) - Add DEFAULT_PLAYERS and DEFAULT_DIFFICULTY constants - Add lint:fix, format, and format:fix npm scripts; include format in CI Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements real-time two-player online mode using WebSockets. Players share a room code to connect; the server (Cloudflare Durable Object) is authoritative for all game state. Migrated from Partykit SDK to native Cloudflare Workers + WebSocket Hibernation API for deployment reliability.