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;