From 5e95ba8da5dd7a7210e2aa4452b3d81dbd8e081e Mon Sep 17 00:00:00 2001 From: scamiv <6170744+scamiv@users.noreply.github.com> Date: Wed, 10 Dec 2025 01:10:21 +0100 Subject: [PATCH] Lobby team size (#2591) ## Description: show team size in lobby ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: DISCORD_USERNAME --- resources/lang/en.json | 9 ++-- src/client/PublicLobby.ts | 104 ++++++++++++++++++++++++++++++++++---- 2 files changed, 98 insertions(+), 15 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index a737b52d8..f5a7cd7b4 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -236,11 +236,12 @@ "public_lobby": { "join": "Join next Game", "waiting": "players waiting", - "teams_Duos": "Duos (teams of 2)", - "teams_Trios": "Trios (teams of 3)", - "teams_Quads": "Quads (teams of 4)", + "teams_Duos": "of 2 (Duos)", + "teams_Trios": "of 3 (Trios)", + "teams_Quads": "of 4 (Quads)", "teams_hvn": "Humans Vs Nations", - "teams": "{num} teams" + "teams": "{num} teams", + "players_per_team": "of {num}" }, "matchmaking_modal": { "title": "Matchmaking", diff --git a/src/client/PublicLobby.ts b/src/client/PublicLobby.ts index cb2f68974..5f6cf628a 100644 --- a/src/client/PublicLobby.ts +++ b/src/client/PublicLobby.ts @@ -1,7 +1,14 @@ import { LitElement, html } from "lit"; import { customElement, state } from "lit/decorators.js"; import { renderDuration, translateText } from "../client/Utils"; -import { GameMapType, GameMode, HumansVsNations } from "../core/game/Game"; +import { + Duos, + GameMapType, + GameMode, + HumansVsNations, + Quads, + Trios, +} from "../core/game/Game"; import { GameID, GameInfo } from "../core/Schemas"; import { generateID } from "../core/Util"; import { JoinLobbyEvent } from "./Main"; @@ -122,6 +129,20 @@ export class PublicLobby extends LitElement { ? (lobby.gameConfig.playerTeams ?? 0) : null; + const maxPlayers = lobby.gameConfig.maxPlayers ?? 0; + const teamSize = this.getTeamSize(teamCount, maxPlayers); + const teamTotal = this.getTeamTotal(teamCount, teamSize, maxPlayers); + const modeLabel = this.getModeLabel( + lobby.gameConfig.gameMode, + teamCount, + teamTotal, + ); + const teamDetailLabel = this.getTeamDetailLabel( + lobby.gameConfig.gameMode, + teamCount, + teamTotal, + teamSize, + ); const mapImageSrc = this.mapImages.get(lobby.gameID); return html` @@ -158,17 +179,16 @@ export class PublicLobby extends LitElement { class="text-sm ${this.isLobbyHighlighted ? "text-green-600" : "text-blue-600"} bg-white rounded-sm px-1" + >${modeLabel} - ${lobby.gameConfig.gameMode === GameMode.Team - ? typeof teamCount === "string" - ? teamCount === HumansVsNations - ? translateText("public_lobby.teams_hvn") - : translateText(`public_lobby.teams_${teamCount}`) - : translateText("public_lobby.teams", { - num: teamCount ?? 0, - }) - : translateText("game_mode.ffa")} + ${teamDetailLabel + ? html`${teamDetailLabel}` + : ""} ${translateText( `map.${lobby.gameConfig.gameMap.toLowerCase().replace(/\s+/g, "")}`, @@ -193,6 +213,68 @@ export class PublicLobby extends LitElement { this.currLobby = null; } + private getTeamSize( + teamCount: number | string | null, + maxPlayers: number, + ): number | undefined { + if (typeof teamCount === "string") { + if (teamCount === Duos) return 2; + if (teamCount === Trios) return 3; + if (teamCount === Quads) return 4; + if (teamCount === HumansVsNations) return Math.floor(maxPlayers / 2); + return undefined; + } + if (typeof teamCount === "number" && teamCount > 0) { + return Math.floor(maxPlayers / teamCount); + } + return undefined; + } + + private getTeamTotal( + teamCount: number | string | null, + teamSize: number | undefined, + maxPlayers: number, + ): number | undefined { + if (typeof teamCount === "number") return teamCount; + if (teamCount === HumansVsNations) return 2; + if (teamSize && teamSize > 0) return Math.floor(maxPlayers / teamSize); + return undefined; + } + + private getModeLabel( + gameMode: GameMode, + teamCount: number | string | null, + teamTotal: number | undefined, + ): string { + if (gameMode !== GameMode.Team) return translateText("game_mode.ffa"); + if (teamCount === HumansVsNations) + return translateText("public_lobby.teams_hvn"); + const totalTeams = + teamTotal ?? (typeof teamCount === "number" ? teamCount : 0); + return translateText("public_lobby.teams", { num: totalTeams }); + } + + private getTeamDetailLabel( + gameMode: GameMode, + teamCount: number | string | null, + teamTotal: number | undefined, + teamSize: number | undefined, + ): string | null { + if (gameMode !== GameMode.Team) return null; + + if (typeof teamCount === "string" && teamCount !== HumansVsNations) { + const teamKey = `public_lobby.teams_${teamCount}`; + const maybeTranslated = translateText(teamKey); + if (maybeTranslated !== teamKey) return maybeTranslated; + } + + if (teamTotal !== undefined && teamSize !== undefined) { + return translateText("public_lobby.players_per_team", { num: teamSize }); + } + + return null; + } + private lobbyClicked(lobby: GameInfo) { if (this.isButtonDebounced) { return;