diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index 2401c6d3a..e7d709c12 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -14,6 +14,7 @@ import { UnitType, mapCategories, } from "../core/game/Game"; +import { getCompactMapNationCount } from "../core/game/NationCreation"; import { UserSettings } from "../core/game/UserSettings"; import { ClientInfo, @@ -27,7 +28,7 @@ import "./components/baseComponents/Modal"; import { BaseModal } from "./components/BaseModal"; import "./components/Difficulties"; import "./components/FluentSlider"; -import "./components/LobbyPlayerView"; +import "./components/LobbyTeamView"; import "./components/Maps"; import { modalHeader } from "./components/ui/ModalHeader"; import { crazyGamesSDK } from "./CrazyGamesSDK"; @@ -933,16 +934,33 @@ export class HostLobbyModal extends BaseModal { - this.kickPlayer(clientID)} - > +
+
+
+ ${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)} + > +
@@ -1420,22 +1438,31 @@ export class HostLobbyModal extends BaseModal { } private async loadNationCount() { - const currentMap = this.selectedMap; try { - const mapData = this.mapLoader.getMapData(currentMap); + const mapData = this.mapLoader.getMapData(this.selectedMap); const manifest = await mapData.manifest(); - // Only update if the map hasn't changed - if (this.selectedMap === currentMap) { - this.nationCount = manifest.nations.length; - } + 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.selectedMap === currentMap) { - this.nationCount = 0; - } + 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 a618a9ccc..cb65b428f 100644 --- a/src/client/JoinPrivateLobbyModal.ts +++ b/src/client/JoinPrivateLobbyModal.ts @@ -10,14 +10,13 @@ import { } from "../core/Schemas"; import { generateID } from "../core/Util"; import { getServerConfigFromClient } from "../core/configuration/ConfigLoader"; -import { GameMapSize, GameMode } from "../core/game/Game"; +import { 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/LobbyPlayerView"; +import "./components/LobbyTeamView"; import { modalHeader } from "./components/ui/ModalHeader"; @customElement("join-private-lobby-modal") export class JoinPrivateLobbyModal extends BaseModal { @@ -30,11 +29,9 @@ 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; @@ -183,17 +180,26 @@ 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")} +
+
+ + +
` : ""} @@ -381,7 +387,6 @@ export class JoinPrivateLobbyModal extends BaseModal { this.hasJoined = false; this.message = ""; this.currentLobbyId = ""; - this.nationCount = 0; this.leaveLobbyOnClose = true; } @@ -607,38 +612,11 @@ 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/LobbyPlayerView.ts b/src/client/components/LobbyTeamView.ts similarity index 83% rename from src/client/components/LobbyPlayerView.ts rename to src/client/components/LobbyTeamView.ts index 2bcac3108..d85105c4b 100644 --- a/src/client/components/LobbyPlayerView.ts +++ b/src/client/components/LobbyTeamView.ts @@ -13,7 +13,6 @@ 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"; @@ -23,7 +22,7 @@ export interface TeamPreviewData { players: ClientInfo[]; } -@customElement("lobby-player-view") +@customElement("lobby-team-view") export class LobbyTeamView extends LitElement { @property({ type: String }) gameMode: GameMode = GameMode.FFA; @property({ type: Array }) clients: ClientInfo[] = []; @@ -33,8 +32,6 @@ 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; @@ -55,32 +52,11 @@ export class LobbyTeamView extends LitElement { } render() { - 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()} -
-
- `; + return html`
+ ${this.gameMode === GameMode.Team + ? this.renderTeamMode() + : this.renderFreeForAll()} +
`; } createRenderRoot() { @@ -172,15 +148,14 @@ export class LobbyTeamView extends LitElement { } private renderTeamCard(preview: TeamPreviewData, isEmpty: boolean = false) { - const effectiveNationCount = this.getEffectiveNationCount(); const displayCount = preview.team === ColoredTeams.Nations - ? effectiveNationCount + ? this.nationCount : preview.players.length; const maxTeamSize = preview.team === ColoredTeams.Nations - ? effectiveNationCount + ? this.nationCount : this.teamMaxSize; return html` @@ -333,20 +308,4 @@ 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 7023676e8..9873cd4f0 100644 --- a/src/client/styles.css +++ b/src/client/styles.css @@ -546,6 +546,7 @@ 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 97b23f0e4..c4430e332 100644 --- a/src/server/MapPlaylist.ts +++ b/src/server/MapPlaylist.ts @@ -127,7 +127,9 @@ export class MapPlaylist { publicGameModifiers: { isCompact, isRandomSpawn, startingGold }, startingGold, difficulty: - playerTeams === HumansVsNations ? Difficulty.Hard : Difficulty.Easy, + playerTeams === HumansVsNations + ? Difficulty.Impossible + : Difficulty.Easy, infiniteGold: false, infiniteTroops: false, maxTimerValue: undefined,