3.8 KiB
Multiplayer rooms
Open a published map, select Multiplayer, enter your player name, and choose a limit from 2 to 16 players, including yourself. Create the room and copy its invite link. Friends open that link, enter a name, and join. The owner starts the match once at least two players are present and can remove players from the lobby.
Everyone plays the same five randomly selected locations with the selected difficulty. A round starts when active players have loaded its images, with a 30-second loading grace period. The timer and scoring run in PostgreSQL; refreshing the page restores the same player, guess, and deadline. Guesses and scores are revealed when everyone submits or the timer expires. Missing guesses score zero. The owner can advance from the round standings, or the next round starts automatically after 20 seconds. The final table ranks total points; equal totals share a place.
Choose one of the built-in difficulties or create a named custom difficulty with its own round time and zoom setting. Custom difficulties are saved in the shared MineGeo catalog and can be reused on any map. Multiplayer rooms snapshot the selected settings when created, so every invited player follows the same rules.
Players join without an account. A separate HttpOnly cookie identifies each browser, and the room link acts as the invitation. Only the server can access the room tables and functions. Clients receive the current round's signed images and completed results, never future locations or other players' guesses before a round closes. Leaving the lobby frees a place; leaving during a match retains the player's results and scores their remaining rounds as zero. If the owner leaves, ownership transfers to another remaining player.
Room state refreshes every two seconds, or every five seconds in a hidden tab. Unfinished rooms expire after 24 hours. Multiplayer results are separate from the solo leaderboard.
Room chat is available to current players in the lobby, during rounds, and at the final standings. Open Chat to send a plain-text message of up to 500 characters. A badge shows unread messages while it is collapsed. Messages refresh every two seconds and the latest 100 are restored after a refresh. Sending chat does not lock the guess controls or change the round clock. Removed players, players who left, and invite visitors cannot read or send messages. Closed rooms and rooms older than 24 hours cannot use chat. Retries are deduplicated; each player can send at most one new message per second and 30 per minute. Player names come from the room identity.
Database and verification
Apply supabase/migrations/20261007071259_multiplayer_rooms.sql to a new database
before deploying the web update. It has already been applied to MineGeo's
configured Supabase project. Deployments continue through npm run deploy
without a Git-provider connection.
Custom difficulty presets also require
supabase/migrations/20261013095201_custom_difficulty_presets.sql before the
web update. No additional environment variables are needed.
Chat additionally requires supabase/migrations/20261007155622_multiplayer_chat.sql.
npm test: validation and existing regression checks.npm run test:multiplayer: isolated PostgreSQL state, permission, and scoring checks, using the existing.data/sql-verificationPGlite installation.node scripts/test-multiplayer-http.mjs <site-origin>: real API and Storage verification, including five-round rankings and concurrent last-slot joins. Requires local Supabase configuration; creates and removes its own test rooms.node scripts/test-multiplayer-browser.mjs <site-origin>: desktop and mobile invite, reconnect, map interaction, and five-round standings checks. Requires Playwright Chromium; removes its own test room and saves screenshots locally.