From dba04027df723880c096f0d3b975e831425f63fd Mon Sep 17 00:00:00 2001 From: FloPinguin <25036848+FloPinguin@users.noreply.github.com> Date: Sat, 17 Jan 2026 15:35:26 +0100 Subject: [PATCH] Merge pull request #2933 from FloPinguin/fix-nation-loading Fix for v29: Add nation count loading for JoinPrivateLobbyModal; change HvN difficulty --- src/client/HostLobbyModal.ts | 69 ++++++------------- src/client/JoinPrivateLobbyModal.ts | 66 ++++++++++++------ .../{LobbyTeamView.ts => LobbyPlayerView.ts} | 57 ++++++++++++--- src/client/styles.css | 1 - src/server/MapPlaylist.ts | 4 +- 5 files changed, 115 insertions(+), 82 deletions(-) rename src/client/components/{LobbyTeamView.ts => LobbyPlayerView.ts} (83%) diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index e7d709c12..2401c6d3a 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -14,7 +14,6 @@ import { UnitType, mapCategories, } from "../core/game/Game"; -import { getCompactMapNationCount } from "../core/game/NationCreation"; import { UserSettings } from "../core/game/UserSettings"; import { ClientInfo, @@ -28,7 +27,7 @@ import "./components/baseComponents/Modal"; import { BaseModal } from "./components/BaseModal"; import "./components/Difficulties"; import "./components/FluentSlider"; -import "./components/LobbyTeamView"; +import "./components/LobbyPlayerView"; import "./components/Maps"; import { modalHeader } from "./components/ui/ModalHeader"; import { crazyGamesSDK } from "./CrazyGamesSDK"; @@ -934,33 +933,16 @@ export class HostLobbyModal extends BaseModal { -
-
-
- ${this.clients.length} - ${this.clients.length === 1 - ? translateText("host_modal.player") - : translateText("host_modal.players")} - - ${this.getEffectiveNationCount()} - ${this.getEffectiveNationCount() === 1 - ? translateText("host_modal.nation_player") - : translateText("host_modal.nation_players")} -
-
- - this.kickPlayer(clientID)} - > -
+ this.kickPlayer(clientID)} + > @@ -1438,31 +1420,22 @@ export class HostLobbyModal extends BaseModal { } private async loadNationCount() { + const currentMap = this.selectedMap; try { - const mapData = this.mapLoader.getMapData(this.selectedMap); + const mapData = this.mapLoader.getMapData(currentMap); const manifest = await mapData.manifest(); - this.nationCount = manifest.nations.length; + // Only update if the map hasn't changed + if (this.selectedMap === currentMap) { + this.nationCount = manifest.nations.length; + } } catch (error) { console.warn("Failed to load nation count", error); - this.nationCount = 0; + // Only update if the map hasn't changed + if (this.selectedMap === currentMap) { + this.nationCount = 0; + } } } - - /** - * Returns the effective nation count for display purposes. - * In HumansVsNations mode, this equals the number of human players. - * For compact maps, only 25% of nations are used. - * Otherwise, it uses the manifest nation count (or 0 if nations are disabled). - */ - private getEffectiveNationCount(): number { - if (this.disableNations) { - return 0; - } - if (this.gameMode === GameMode.Team && this.teamCount === HumansVsNations) { - return this.clients.length; - } - return getCompactMapNationCount(this.nationCount, this.compactMap); - } } async function createLobby(creatorClientID: string): Promise { diff --git a/src/client/JoinPrivateLobbyModal.ts b/src/client/JoinPrivateLobbyModal.ts index cb65b428f..a618a9ccc 100644 --- a/src/client/JoinPrivateLobbyModal.ts +++ b/src/client/JoinPrivateLobbyModal.ts @@ -10,13 +10,14 @@ import { } from "../core/Schemas"; import { generateID } from "../core/Util"; import { getServerConfigFromClient } from "../core/configuration/ConfigLoader"; -import { GameMode } from "../core/game/Game"; +import { GameMapSize, GameMode } from "../core/game/Game"; import { UserSettings } from "../core/game/UserSettings"; import { getApiBase } from "./Api"; import { JoinLobbyEvent } from "./Main"; +import { terrainMapFileLoader } from "./TerrainMapFileLoader"; import { BaseModal } from "./components/BaseModal"; import "./components/Difficulties"; -import "./components/LobbyTeamView"; +import "./components/LobbyPlayerView"; import { modalHeader } from "./components/ui/ModalHeader"; @customElement("join-private-lobby-modal") export class JoinPrivateLobbyModal extends BaseModal { @@ -29,9 +30,11 @@ export class JoinPrivateLobbyModal extends BaseModal { @state() private lobbyIdVisible: boolean = true; @state() private copySuccess: boolean = false; @state() private currentLobbyId: string = ""; + @state() private nationCount: number = 0; private playersInterval: NodeJS.Timeout | null = null; private userSettings: UserSettings = new UserSettings(); + private mapLoader = terrainMapFileLoader; private leaveLobbyOnClose = true; @@ -180,26 +183,17 @@ export class JoinPrivateLobbyModal extends BaseModal { ${this.renderGameConfig()} ${this.hasJoined && this.players.length > 0 ? html` -
-
-
- ${this.players.length} - ${this.players.length === 1 - ? translateText("private_lobby.player") - : translateText("private_lobby.players")} -
-
- - -
+ ` : ""} @@ -387,6 +381,7 @@ export class JoinPrivateLobbyModal extends BaseModal { this.hasJoined = false; this.message = ""; this.currentLobbyId = ""; + this.nationCount = 0; this.leaveLobbyOnClose = true; } @@ -612,11 +607,38 @@ export class JoinPrivateLobbyModal extends BaseModal { this.lobbyCreatorClientID = data.clients?.[0]?.clientID ?? null; this.players = data.clients ?? []; if (data.gameConfig) { + const mapChanged = + this.gameConfig?.gameMap !== data.gameConfig.gameMap; this.gameConfig = data.gameConfig; + if (mapChanged) { + this.loadNationCount(); + } } }) .catch((error) => { console.error("Error polling players:", error); }); } + + private async loadNationCount() { + if (!this.gameConfig) { + this.nationCount = 0; + return; + } + const currentMap = this.gameConfig.gameMap; + try { + const mapData = this.mapLoader.getMapData(currentMap); + const manifest = await mapData.manifest(); + // Only update if the map hasn't changed + if (this.gameConfig?.gameMap === currentMap) { + this.nationCount = manifest.nations.length; + } + } catch (error) { + console.warn("Failed to load nation count", error); + // Only update if the map hasn't changed + if (this.gameConfig?.gameMap === currentMap) { + this.nationCount = 0; + } + } + } } diff --git a/src/client/components/LobbyTeamView.ts b/src/client/components/LobbyPlayerView.ts similarity index 83% rename from src/client/components/LobbyTeamView.ts rename to src/client/components/LobbyPlayerView.ts index d85105c4b..2bcac3108 100644 --- a/src/client/components/LobbyTeamView.ts +++ b/src/client/components/LobbyPlayerView.ts @@ -13,6 +13,7 @@ import { Team, Trios, } from "../../core/game/Game"; +import { getCompactMapNationCount } from "../../core/game/NationCreation"; import { assignTeamsLobbyPreview } from "../../core/game/TeamAssignment"; import { ClientInfo, TeamCountConfig } from "../../core/Schemas"; import { translateText } from "../Utils"; @@ -22,7 +23,7 @@ export interface TeamPreviewData { players: ClientInfo[]; } -@customElement("lobby-team-view") +@customElement("lobby-player-view") export class LobbyTeamView extends LitElement { @property({ type: String }) gameMode: GameMode = GameMode.FFA; @property({ type: Array }) clients: ClientInfo[] = []; @@ -32,6 +33,8 @@ 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 }) disableNations: boolean = false; + @property({ type: Boolean }) isCompactMap: boolean = false; private theme: PastelTheme = new PastelTheme(); @state() private showTeamColors: boolean = false; @@ -52,11 +55,32 @@ export class LobbyTeamView extends LitElement { } render() { - return html`
- ${this.gameMode === GameMode.Team - ? this.renderTeamMode() - : this.renderFreeForAll()} -
`; + return html` +
+
+
+ ${this.clients.length} + ${this.clients.length === 1 + ? translateText("host_modal.player") + : translateText("host_modal.players")} + + ${this.getEffectiveNationCount()} + ${this.getEffectiveNationCount() === 1 + ? translateText("host_modal.nation_player") + : translateText("host_modal.nation_players")} +
+
+
+ ${this.gameMode === GameMode.Team + ? this.renderTeamMode() + : this.renderFreeForAll()} +
+
+ `; } createRenderRoot() { @@ -148,14 +172,15 @@ export class LobbyTeamView extends LitElement { } private renderTeamCard(preview: TeamPreviewData, isEmpty: boolean = false) { + const effectiveNationCount = this.getEffectiveNationCount(); const displayCount = preview.team === ColoredTeams.Nations - ? this.nationCount + ? effectiveNationCount : preview.players.length; const maxTeamSize = preview.team === ColoredTeams.Nations - ? this.nationCount + ? effectiveNationCount : this.teamMaxSize; return html` @@ -308,4 +333,20 @@ export class LobbyTeamView extends LitElement { players: buckets.get(t) ?? [], })); } + + /** + * Returns the effective nation count for display purposes. + * In HumansVsNations mode, this equals the number of human players. + * For compact maps, only 25% of nations are used. + * Otherwise, it uses the manifest nation count (or 0 if nations are disabled). + */ + private getEffectiveNationCount(): number { + if (this.disableNations) { + return 0; + } + if (this.gameMode === GameMode.Team && this.teamCount === HumansVsNations) { + return this.clients.length; + } + return getCompactMapNationCount(this.nationCount, this.isCompactMap); + } } diff --git a/src/client/styles.css b/src/client/styles.css index 9873cd4f0..7023676e8 100644 --- a/src/client/styles.css +++ b/src/client/styles.css @@ -546,7 +546,6 @@ label.option-card:hover { flex-wrap: wrap; gap: 8px; justify-content: center; - padding: 0 16px; } /* News Button Notification */ diff --git a/src/server/MapPlaylist.ts b/src/server/MapPlaylist.ts index c4430e332..97b23f0e4 100644 --- a/src/server/MapPlaylist.ts +++ b/src/server/MapPlaylist.ts @@ -127,9 +127,7 @@ export class MapPlaylist { publicGameModifiers: { isCompact, isRandomSpawn, startingGold }, startingGold, difficulty: - playerTeams === HumansVsNations - ? Difficulty.Impossible - : Difficulty.Easy, + playerTeams === HumansVsNations ? Difficulty.Hard : Difficulty.Easy, infiniteGold: false, infiniteTroops: false, maxTimerValue: undefined,