From f0ff31f95a22df6ff84fcdcbbaeb8ac90dc824af Mon Sep 17 00:00:00 2001 From: Trajkov Dimitar Date: Sat, 1 Nov 2025 17:29:39 +0100 Subject: [PATCH] fixed duplication of maps config and prettier format --- src/client/RankedQueue.ts | 32 ++++++++++++------ src/core/configuration/DefaultConfig.ts | 4 ++- src/server/MapSelection.ts | 43 +++++-------------------- src/server/MatchmakingPoller.ts | 5 +-- src/server/RankedGameConfig.ts | 4 +-- src/server/Worker.ts | 3 +- 6 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/client/RankedQueue.ts b/src/client/RankedQueue.ts index fecd4340d..80467302b 100644 --- a/src/client/RankedQueue.ts +++ b/src/client/RankedQueue.ts @@ -279,15 +279,29 @@ export class RankedQueue extends LitElement { // Connect WebSocket if not connected await this.connectWebSocket(); - // Send join queue message - if (this.ws && this.ws.readyState === WebSocket.OPEN) { - this.ws.send( - JSON.stringify({ - type: "join_queue", - queueType: this.queueType, - gameMode: this.gameMode, - }), - ); + // Function to send join queue message + const sendJoinMessage = () => { + if (this.ws && this.ws.readyState === WebSocket.OPEN) { + this.ws.send( + JSON.stringify({ + type: "join_queue", + queueType: this.queueType, + gameMode: this.gameMode, + }), + ); + } + }; + + // Send join queue message immediately if connected, or wait for connection + if (this.ws) { + if (this.ws.readyState === WebSocket.OPEN) { + sendJoinMessage(); + } else if (this.ws.readyState === WebSocket.CONNECTING) { + // Wait for connection to open before sending join message + this.ws.addEventListener("open", () => sendJoinMessage(), { + once: true, + }); + } } } diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index a6331df7a..1ff280533 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -46,7 +46,9 @@ const JwksSchema = z.object({ .min(1), }); -const numPlayersConfig = { +// Map capacity configuration: [large, medium, small] player counts +// Used by both lobby creation and ranked matchmaking +export const numPlayersConfig = { [GameMapType.Africa]: [100, 70, 50], [GameMapType.Asia]: [50, 40, 30], [GameMapType.Australia]: [70, 40, 30], diff --git a/src/server/MapSelection.ts b/src/server/MapSelection.ts index 59db81f1d..0a7c40ae2 100644 --- a/src/server/MapSelection.ts +++ b/src/server/MapSelection.ts @@ -1,38 +1,7 @@ +import { numPlayersConfig } from "../core/configuration/DefaultConfig"; import { GameMapType, GameMode } from "../core/game/Game"; -// import { TeamCountConfig } from "../core/Schemas"; -const MAP_CAPACITIES: Record = { - [GameMapType.Africa]: [100, 70, 50], - [GameMapType.Asia]: [50, 40, 30], - [GameMapType.Australia]: [70, 40, 30], - [GameMapType.Baikal]: [100, 70, 50], - [GameMapType.BetweenTwoSeas]: [70, 50, 40], - [GameMapType.BlackSea]: [50, 30, 30], - [GameMapType.Britannia]: [50, 30, 20], - [GameMapType.DeglaciatedAntarctica]: [50, 40, 30], - [GameMapType.EastAsia]: [50, 30, 20], - [GameMapType.Europe]: [100, 70, 50], - [GameMapType.EuropeClassic]: [50, 30, 30], - [GameMapType.FalklandIslands]: [50, 30, 20], - [GameMapType.FaroeIslands]: [20, 15, 10], - [GameMapType.GatewayToTheAtlantic]: [100, 70, 50], - [GameMapType.GiantWorldMap]: [100, 70, 50], - [GameMapType.Halkidiki]: [100, 50, 40], - [GameMapType.Iceland]: [50, 40, 30], - [GameMapType.Italia]: [50, 30, 20], - [GameMapType.Japan]: [20, 15, 10], - [GameMapType.Mars]: [70, 40, 30], - [GameMapType.Mena]: [70, 50, 40], - [GameMapType.Montreal]: [60, 40, 30], - [GameMapType.NorthAmerica]: [70, 40, 30], - [GameMapType.Oceania]: [10, 10, 10], - [GameMapType.Pangaea]: [20, 15, 10], - [GameMapType.Pluto]: [100, 70, 50], - [GameMapType.SouthAmerica]: [70, 50, 40], - [GameMapType.StraitOfGibraltar]: [100, 70, 50], - [GameMapType.World]: [50, 30, 20], - [GameMapType.Yenisei]: [150, 100, 70], -}; +const MAP_CAPACITIES = numPlayersConfig; export interface MapSelectionCriteria { playerCount: number; @@ -68,8 +37,11 @@ export function selectMapForRanked( // Find intersection const viableMaps = suitableMaps.filter((map) => rankedMaps.includes(map)); + // Use ranked maps if available, otherwise fall back to all suitable maps + const candidates = viableMaps.length > 0 ? viableMaps : suitableMaps; + // Pick best fit (prefer maps closest to player count) - return pickBestFit(viableMaps, playerCount); + return pickBestFit(candidates, playerCount); } /** @@ -95,8 +67,9 @@ function getSuitableMaps(playerCount: number): GameMapType[] { * Selects map where player count is closest to the middle of its capacity range */ function pickBestFit(maps: GameMapType[], playerCount: number): GameMapType { + // This should never happen now due to fallback in selectMapForRanked, + // but keep a safe fallback just in case if (maps.length === 0) { - // Fallback to World if no perfect match return GameMapType.World; } diff --git a/src/server/MatchmakingPoller.ts b/src/server/MatchmakingPoller.ts index 3c6e3b87e..e77bd2da3 100644 --- a/src/server/MatchmakingPoller.ts +++ b/src/server/MatchmakingPoller.ts @@ -1,5 +1,6 @@ import { Logger } from "winston"; import { ServerConfig } from "../core/configuration/Config"; +import { TeamCountConfig } from "../core/Schemas"; import { generateID, simpleHash } from "../core/Util"; export interface MatchAssignment { @@ -8,7 +9,7 @@ export interface MatchAssignment { queueType: "ranked" | "unranked"; gameMode: "ffa" | "team"; playerCount: number; - teamConfig?: unknown; // TODO: define team config + teamConfig?: TeamCountConfig; }; } @@ -79,7 +80,7 @@ export class MatchmakingPoller { method: "POST", headers: { "Content-Type": "application/json", - "X-API-Key": process.env.GAME_SERVER_API_KEY ?? "", + "X-API-Key": process.env.API_KEY ?? "", }, body: JSON.stringify({ id: workerId, diff --git a/src/server/RankedGameConfig.ts b/src/server/RankedGameConfig.ts index 73093574e..ebde6ca68 100644 --- a/src/server/RankedGameConfig.ts +++ b/src/server/RankedGameConfig.ts @@ -11,7 +11,7 @@ export interface RankedMatchConfig { queueType: "ranked" | "unranked"; gameMode: "ffa" | "team"; playerCount: number; - teamConfig?: unknown; + teamConfig?: TeamCountConfig; } /** @@ -51,7 +51,7 @@ export function buildRankedGameConfig( disabledUnits: [], // Team configuration - playerTeams: matchConfig.teamConfig as TeamCountConfig | undefined, + playerTeams: matchConfig.teamConfig, }; } diff --git a/src/server/Worker.ts b/src/server/Worker.ts index 03b8848ad..fd7256e51 100644 --- a/src/server/Worker.ts +++ b/src/server/Worker.ts @@ -8,7 +8,7 @@ import { fileURLToPath } from "url"; import { WebSocket, WebSocketServer } from "ws"; import { z } from "zod"; import { getServerConfigFromServer } from "../core/configuration/ConfigLoader"; -import { GameType } from "../core/game/Game"; +import { GameMode, GameType } from "../core/game/Game"; import { ClientMessageSchema, GameID, @@ -25,7 +25,6 @@ import { getUserMe, verifyClientToken } from "./jwt"; import { logger } from "./Logger"; import { GameEnv } from "../core/configuration/Config"; -import { GameMode } from "../core/game/Game"; import { MapPlaylist } from "./MapPlaylist"; import { selectMapForRanked } from "./MapSelection"; import { MatchmakingPoller } from "./MatchmakingPoller";