Open custom lobbies to the public#3949
Conversation
- Hosts can open/close their custom lobby to the public from HostLobbyModal - Open lobbies appear in a new section in JoinLobbyModal with map thumbnail, player count, game mode label, and join button - Game mode (FFA/Teams) and map selection update in real time for viewers - Random map selection preserved as a flag (useRandomMap) so viewers see "Random" + random thumbnail instead of the resolved map - Fix tournament map names and thumbnails by resolving normaliseMapKey via enum key lookup - All user-visible strings go through translateText()
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughHosts can open custom lobbies to public discovery; clients browse, expand details, and join open custom lobbies. Changes update schemas/intents, client host/join modals, transport routing, server lobby state, IPC propagation, utilities sync, and English localization. ChangesOpen Custom Lobbies
Sequence Diagram(s) sequenceDiagram
participant Host as HostLobbyModal
participant Doc as Document
participant Main as Client.Main
participant Transport as Client.Transport
participant Server as GameServer
participant Worker as WorkerLobbyService
participant Master as MasterLobbyService
participant Join as JoinLobbyModal
Host->>Doc: dispatch "open-to-public" event (publicGameType)
Doc->>Main: document event triggers handleOpenToPublic
Main->>Transport: emit SendOpenToPublicIntentEvent(publicGameType)
Transport->>Server: sendIntent "open_to_public" with publicGameType
Server->>Server: authorize owner, set openCustomType, maybe set gameType=Custom
Server->>Worker: Worker collects openCustomLobbies()
Worker->>Master: sendMyLobbiesToMaster (lobbies + openLobbies)
Master->>Join: broadcast lobbiesBroadcast including openLobbies
Join->>Join: render openLobbies list/cards
🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/client/JoinLobbyModal.ts (1)
223-266:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winRun Prettier on this file before merge.
CI reports
Prettier --checkwarnings for this file, so formatting is currently out of sync.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/client/JoinLobbyModal.ts` around lines 223 - 266, The file formatting in JoinLobbyModal is out of sync with project style (Prettier) causing CI --check failures; run Prettier on this file (e.g., format src/client/JoinLobbyModal.ts) and ensure the JSX/template block and attributes (in the JoinLobbyModal render method around the input with id "lobbyIdInput", the o-button with `@click`=${this.pasteFromClipboard}, the form submit handler joinLobbyFromInput, and the renderOpenLobbies() insertion) are reformatted to match project Prettier config, then re-run lint/CI and commit the formatted file.
🧹 Nitpick comments (1)
src/server/WorkerLobbyService.ts (1)
98-116: 💤 Low valueConsider a fallback for
openCustomTypeto avoid potential runtime error.There is a small timing window where a lobby could close between the
openCustomLobbies()filter and callinggameInfo(). If that happens,gi.openCustomTypebecomesundefinedand the non-null assertion on line 108 would throw.This is unlikely in practice, but a simple guard would make it safer.
♻️ Suggested defensive filter
const openLobbies = this.gm .openCustomLobbies() .map((g) => g.gameInfo()) + .filter((gi) => gi.openCustomType !== undefined) .map((gi) => { return { gameID: gi.gameID, numClients: gi.clients?.length ?? 0, startsAt: gi.startsAt, gameConfig: gi.gameConfig, - publicGameType: gi.openCustomType!, + publicGameType: gi.openCustomType, } satisfies PublicGameInfo; });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/server/WorkerLobbyService.ts` around lines 98 - 116, The mapping that builds openLobbies uses gi.openCustomType! with a non-null assertion which can throw if a lobby closes between openCustomLobbies() and gameInfo(); update the transformation to defensively filter or default those entries: when mapping results from this.gm.openCustomLobbies().map(g => g.gameInfo()), skip any gi where gi.openCustomType is undefined (or provide a safe fallback value) before constructing the object that satisfies PublicGameInfo, ensuring the final openLobbies array only contains items with a defined openCustomType before sending the WorkerLobbyList.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/client/HostLobbyModal.ts`:
- Line 89: The modal-scoped field openToPublicType (type "ffa" | "team" |
"special" | null) is not being cleared when the modal is closed, causing stale
values to flash on reopen; update the HostLobbyModal.onClose method to reset
this.openToPublicType = null (ensure it's set whether onClose is sync or after
any async cleanup) so the modal always starts with a null public-type state when
reopened.
In `@src/client/JoinLobbyModal.ts`:
- Around line 452-467: The code emits hardcoded unit suffixes ("min", "s", "m",
"M") when building the tags array in JoinLobbyModal; replace those raw suffix
strings with translateText calls and new i18n keys so units are localizable:
update the logic around c.maxTimerValue display (currently using
translateText("private_lobby.game_length")), the spawnImmunityDuration block
that builds val (replace "s", "m", "min" with translateText keys like
"units.second_short", "units.minute_short", "units.minute" and keep using
Math.floor/Math.round as-is), and the startingGold formatting (replace "M" with
translateText("units.million_short")); add corresponding entries to
resources/lang/en.json (e.g. units.second_short, units.minute_short,
units.minute, units.million_short) and use those translateText keys in the
tags.push calls so all visible units are localized.
In `@src/client/Main.ts`:
- Line 229: The custom event "open-to-public" currently force-casts its payload
string to the allowed union, letting invalid values through; add a runtime
validation step instead: define an allowedPublicGameTypes set (or an
isValidPublicGameType type-guard) that lists the permitted string values and
null, use it wherever the event payload is read (the "open-to-public"
CustomEvent handling and the code paths around the previous casts) to check the
incoming value, and only accept/narrow the type when the guard passes; for
invalid values, reject or fallback to a safe default and log an error so
malformed intents cannot be emitted.
In `@src/core/Schemas.ts`:
- Line 171: The lobby schema's openCustomType currently uses
PublicGameTypeSchema.optional() which still rejects null; update the definition
(symbol: openCustomType in Schemas.ts) to accept null by using
PublicGameTypeSchema.nullable() or PublicGameTypeSchema.nullable().optional()
(if you want both null and undefined) so the lobby_info parsing accepts the
closed-state null for custom lobbies.
---
Outside diff comments:
In `@src/client/JoinLobbyModal.ts`:
- Around line 223-266: The file formatting in JoinLobbyModal is out of sync with
project style (Prettier) causing CI --check failures; run Prettier on this file
(e.g., format src/client/JoinLobbyModal.ts) and ensure the JSX/template block
and attributes (in the JoinLobbyModal render method around the input with id
"lobbyIdInput", the o-button with `@click`=${this.pasteFromClipboard}, the form
submit handler joinLobbyFromInput, and the renderOpenLobbies() insertion) are
reformatted to match project Prettier config, then re-run lint/CI and commit the
formatted file.
---
Nitpick comments:
In `@src/server/WorkerLobbyService.ts`:
- Around line 98-116: The mapping that builds openLobbies uses
gi.openCustomType! with a non-null assertion which can throw if a lobby closes
between openCustomLobbies() and gameInfo(); update the transformation to
defensively filter or default those entries: when mapping results from
this.gm.openCustomLobbies().map(g => g.gameInfo()), skip any gi where
gi.openCustomType is undefined (or provide a safe fallback value) before
constructing the object that satisfies PublicGameInfo, ensuring the final
openLobbies array only contains items with a defined openCustomType before
sending the WorkerLobbyList.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 1edada23-6e5b-4753-a241-d0f90f6a7548
📒 Files selected for processing (15)
resources/lang/en.jsonsrc/client/GameModeSelector.tssrc/client/HostLobbyModal.tssrc/client/JoinLobbyModal.tssrc/client/Main.tssrc/client/Transport.tssrc/client/Utils.tssrc/core/ApiSchemas.tssrc/core/Schemas.tssrc/core/game/Game.tssrc/server/GameManager.tssrc/server/GameServer.tssrc/server/IPCBridgeSchema.tssrc/server/MasterLobbyService.tssrc/server/WorkerLobbyService.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/client/JoinLobbyModal.ts`:
- Around line 556-567: joinOpenLobby can process stale async results; create and
use an AbortController (or a unique request token) tied to the lobby tracking so
late checkActiveLobby results are ignored. Modify startTrackingLobby to store
the current AbortController (or token) and call controller.abort() in
resetTrackingState and whenever starting a new tracking, pass controller.signal
into checkActiveLobby (or have checkActiveLobby accept the token) and before
dispatching any join logic ensure the controller.signal is not aborted (or the
token still matches the current tracked id). Update joinOpenLobby to create the
controller, pass it into checkActiveLobby, and bail out if the signal was
aborted or token mismatches before calling resetTrackingState/showMessage or
emitting any join event.
- Around line 474-479: The lobby tag rendering currently only handles c.nations
=== "disabled" and omits numeric nation caps; update the JoinLobbyModal tag
logic (near where c, isCompact and tags are used) to mirror renderGameConfig()
by adding a branch for numeric c.nations values that pushes a tag like
`${translateText("host_modal.nations")}: ${c.nations}` (or the same formatted
string used in renderGameConfig) so non-default numeric nation limits are shown
in the expanded details; keep the existing disabled branch and ensure the new
branch only runs when c.nations is not "disabled".
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 26a8d011-32ff-4b73-92ab-d87556aebc5e
📒 Files selected for processing (3)
src/client/JoinLobbyModal.tssrc/client/Main.tssrc/server/GameManager.ts
🚧 Files skipped from review as they are similar to previous changes (2)
- src/server/GameManager.ts
- src/client/Main.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/server/WorkerLobbyService.ts`:
- Line 102: Replace the non-strict null check in the filter callback
(.filter((gi) => gi.openCustomType != null)) with a strict null/undefined check
to satisfy eqeqeq; update the predicate to explicitly check both null and
undefined (e.g., .filter((gi) => gi.openCustomType !== null && gi.openCustomType
!== undefined)) so the filter uses strict comparisons.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 110b5a9b-42f3-41b9-8687-5a751bcc1eca
📒 Files selected for processing (6)
resources/lang/en.jsonsrc/client/HostLobbyModal.tssrc/client/JoinLobbyModal.tssrc/client/Main.tssrc/core/Schemas.tssrc/server/WorkerLobbyService.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- src/client/HostLobbyModal.ts
- src/client/Main.ts
- resources/lang/en.json
- src/core/Schemas.ts
- src/client/JoinLobbyModal.ts
Description:
Adds the ability for hosts to open their custom lobbies to the public, allowing other players to discover and join them without needing an invite link.
This PR eliminates "private" lobbies and they are now called CUSTOM LOBBIES, since they can be either private or public.
Host side (HostLobbyModal):
Player side (JoinLobbyModal):
Improvements:
The text, in general, about how the game is opened to the public, what appears in the public game list, etc. I leave it up to you what you want to include; if you want, tell me on Discord and we can discuss it further.
Please complete the following:
Please put your Discord username so you can be contacted if a bug or regression is found:
sardidefcon