mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 09:30:45 +00:00
Fix 2 HvN UI bugs 🔧 (#3378)
## Description: I noticed two HvN bugs. 1. Private lobbies don't set `maxPlayers` in `GameConfig`, causing `getGameModeLabel()` to render "0 Humans vs 0 Nations". Fall back to the simple "Humans vs Nations" label when `maxPlayers` is unavailable. <img width="239" height="84" alt="Screenshot 2026-03-07 034150" src="https://github.com/user-attachments/assets/b2f01b96-674f-47dc-ae03-06bec71e3134" /> 2. In public HumansVsNations games, the server matches the nation count to the human player count at game start. The lobby team size preview wasn't reflecting this - it displayed the raw config value instead. Added `isPublicGame` prop to `LobbyPlayerView` and an `effectiveNationCount` getter that overrides the displayed nation count to match `clients.length` only for public HvN games. Private lobby hosts retain full slider control. (This bug got introduced with my "Configurable nation count" PR) ## 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: FloPinguin
This commit is contained in:
@@ -130,6 +130,8 @@ export class JoinLobbyModal extends BaseModal {
|
||||
.lobbyCreatorClientID=${hostClientID}
|
||||
.currentClientID=${this.currentClientID}
|
||||
.teamCount=${this.gameConfig?.playerTeams ?? 2}
|
||||
.isPublicGame=${this.gameConfig?.gameType ===
|
||||
GameType.Public}
|
||||
.nationCount=${nationsConfigToSlider(
|
||||
this.gameConfig?.nations ?? "default",
|
||||
this.nationCount,
|
||||
|
||||
+6
-3
@@ -36,9 +36,12 @@ export function getGameModeLabel(gameConfig: GameConfig): string {
|
||||
|
||||
// Humans vs Nations
|
||||
if (playerTeams === HumansVsNations) {
|
||||
return translateText("public_lobby.teams_hvn_detailed", {
|
||||
num: maxPlayers ?? 0,
|
||||
});
|
||||
if (maxPlayers) {
|
||||
return translateText("public_lobby.teams_hvn_detailed", {
|
||||
num: maxPlayers,
|
||||
});
|
||||
}
|
||||
return translateText("public_lobby.teams_hvn");
|
||||
}
|
||||
|
||||
// Named team types (Duos, Trios, Quads)
|
||||
|
||||
@@ -35,11 +35,24 @@ export class LobbyTeamView extends LitElement {
|
||||
@property({ attribute: "team-count" }) teamCount: TeamCountConfig = 2;
|
||||
@property({ type: Function }) onKickPlayer?: (clientID: string) => void;
|
||||
@property({ type: Number }) nationCount: number = 0;
|
||||
@property({ type: Boolean }) isPublicGame: boolean = false;
|
||||
|
||||
private theme: PastelTheme = new PastelTheme();
|
||||
@state() private showTeamColors: boolean = false;
|
||||
private userSettings: UserSettings = new UserSettings();
|
||||
|
||||
/**
|
||||
* For public HumansVsNations games, nation count always matches human count
|
||||
* (server enforces this in NationCreation). For private games, the host
|
||||
* controls the nation count via the slider.
|
||||
*/
|
||||
private get effectiveNationCount(): number {
|
||||
if (this.isPublicGame && this.teamCount === HumansVsNations) {
|
||||
return this.clients.length;
|
||||
}
|
||||
return this.nationCount;
|
||||
}
|
||||
|
||||
willUpdate(changedProperties: Map<string, any>) {
|
||||
// Recompute team preview when relevant properties change
|
||||
// clients is updated from WebSocket lobby_info events
|
||||
@@ -47,7 +60,8 @@ export class LobbyTeamView extends LitElement {
|
||||
changedProperties.has("gameMode") ||
|
||||
changedProperties.has("clients") ||
|
||||
changedProperties.has("teamCount") ||
|
||||
changedProperties.has("nationCount")
|
||||
changedProperties.has("nationCount") ||
|
||||
changedProperties.has("isPublicGame")
|
||||
) {
|
||||
const teamsList = this.getTeamList();
|
||||
this.computeTeamPreview(teamsList);
|
||||
@@ -67,8 +81,8 @@ export class LobbyTeamView extends LitElement {
|
||||
? translateText("host_modal.player")
|
||||
: translateText("host_modal.players")}
|
||||
<span style="margin: 0 8px;">•</span>
|
||||
${this.nationCount}
|
||||
${this.nationCount === 1
|
||||
${this.effectiveNationCount}
|
||||
${this.effectiveNationCount === 1
|
||||
? translateText("host_modal.nation_player")
|
||||
: translateText("host_modal.nation_players")}
|
||||
</div>
|
||||
@@ -179,12 +193,12 @@ export class LobbyTeamView extends LitElement {
|
||||
private renderTeamCard(preview: TeamPreviewData, isEmpty: boolean = false) {
|
||||
const displayCount =
|
||||
preview.team === ColoredTeams.Nations
|
||||
? this.nationCount
|
||||
? this.effectiveNationCount
|
||||
: preview.players.length;
|
||||
|
||||
const maxTeamSize =
|
||||
preview.team === ColoredTeams.Nations
|
||||
? this.nationCount
|
||||
? this.effectiveNationCount
|
||||
: this.teamMaxSize;
|
||||
|
||||
const teamLabel = getTranslatedPlayerTeamLabel(preview.team);
|
||||
@@ -245,7 +259,7 @@ export class LobbyTeamView extends LitElement {
|
||||
|
||||
private getTeamList(): Team[] {
|
||||
if (this.gameMode !== GameMode.Team) return [];
|
||||
const playerCount = this.clients.length + this.nationCount;
|
||||
const playerCount = this.clients.length + this.effectiveNationCount;
|
||||
const config = this.teamCount;
|
||||
|
||||
if (config === HumansVsNations) {
|
||||
@@ -309,7 +323,7 @@ export class LobbyTeamView extends LitElement {
|
||||
const assignment = assignTeamsLobbyPreview(
|
||||
players,
|
||||
teams,
|
||||
this.nationCount,
|
||||
this.effectiveNationCount,
|
||||
);
|
||||
const buckets = new Map<Team, ClientInfo[]>();
|
||||
for (const t of teams) buckets.set(t, []);
|
||||
@@ -333,7 +347,9 @@ export class LobbyTeamView extends LitElement {
|
||||
// Fallback: divide players across teams; guard against 0 and empty lobbies
|
||||
this.teamMaxSize = Math.max(
|
||||
1,
|
||||
Math.ceil((this.clients.length + this.nationCount) / teams.length),
|
||||
Math.ceil(
|
||||
(this.clients.length + this.effectiveNationCount) / teams.length,
|
||||
),
|
||||
);
|
||||
}
|
||||
this.teamPreview = teams.map((t) => ({
|
||||
|
||||
Reference in New Issue
Block a user