From 809d60ff586eadca7ebefe823b3cd374479354a0 Mon Sep 17 00:00:00 2001 From: Scott Anderson <662325+scottanderson@users.noreply.github.com> Date: Sun, 24 Aug 2025 21:32:32 -0400 Subject: [PATCH] format --- src/client/ClientGameRunner.ts | 8 +- src/client/Cosmetics.ts | 12 +- src/client/FlagInput.ts | 2 +- src/client/FlagInputModal.ts | 2 +- src/client/HostLobbyModal.ts | 46 +- src/client/InputHandler.ts | 18 +- src/client/JoinPrivateLobbyModal.ts | 26 +- src/client/LangSelector.ts | 36 +- src/client/LanguageModal.ts | 2 +- src/client/LocalPersistantStats.ts | 2 +- src/client/LocalServer.ts | 16 +- src/client/Main.ts | 14 +- src/client/NewsModal.ts | 2 +- src/client/PublicLobby.ts | 10 +- src/client/SinglePlayerModal.ts | 40 +- src/client/Transport.ts | 80 +-- src/client/UserSettingModal.ts | 2 +- src/client/UsernameInput.ts | 2 +- src/client/Utils.ts | 8 +- src/client/components/Maps.ts | 44 +- .../components/baseComponents/Button.ts | 2 +- .../baseComponents/setting/SettingKeybind.ts | 8 +- .../baseComponents/setting/SettingNumber.ts | 2 +- .../baseComponents/setting/SettingSlider.ts | 2 +- .../baseComponents/setting/SettingToggle.ts | 4 +- src/client/graphics/AnimatedSpriteLoader.ts | 44 +- src/client/graphics/NameBoxCalculator.ts | 22 +- src/client/graphics/SpriteLoader.ts | 2 +- src/client/graphics/fx/NukeFx.ts | 8 +- src/client/graphics/fx/TextFx.ts | 4 +- src/client/graphics/fx/Timeline.ts | 2 +- src/client/graphics/fx/UnitExplosionFx.ts | 6 +- src/client/graphics/layers/BuildMenu.ts | 64 +- src/client/graphics/layers/ChatDisplay.ts | 4 +- src/client/graphics/layers/ChatIntegration.ts | 32 +- src/client/graphics/layers/ChatModal.ts | 10 +- src/client/graphics/layers/EventsDisplay.ts | 178 ++--- src/client/graphics/layers/GutterAdModal.ts | 4 +- src/client/graphics/layers/Leaderboard.ts | 12 +- src/client/graphics/layers/MainRadialMenu.ts | 16 +- src/client/graphics/layers/OptionsMenu.ts | 36 +- src/client/graphics/layers/RadialMenu.ts | 14 +- .../graphics/layers/RadialMenuElements.ts | 357 +++++----- src/client/graphics/layers/RailroadLayer.ts | 6 +- src/client/graphics/layers/SpawnAd.ts | 2 +- .../graphics/layers/StructureIconsLayer.ts | 40 +- src/client/graphics/layers/StructureLayer.ts | 14 +- src/client/graphics/layers/TeamStats.ts | 12 +- src/client/graphics/layers/TerritoryLayer.ts | 2 +- src/client/graphics/layers/UILayer.ts | 4 +- src/client/graphics/layers/UnitLayer.ts | 2 +- src/client/jwt.ts | 6 +- src/client/utilities/RenderUnitTypeOptions.ts | 20 +- src/core/ApiSchemas.ts | 41 +- src/core/CosmeticSchemas.ts | 27 +- src/core/CustomFlag.ts | 4 +- src/core/Schemas.ts | 2 +- src/core/Util.ts | 3 +- src/core/configuration/Colors.ts | 637 +++++++++--------- src/core/configuration/DefaultConfig.ts | 28 +- src/core/configuration/PastelTheme.ts | 74 +- src/core/configuration/PastelThemeDark.ts | 64 +- src/core/execution/RailroadExecution.ts | 8 +- src/core/execution/SAMLauncherExecution.ts | 3 +- src/core/game/Game.ts | 30 +- src/core/game/PlayerImpl.ts | 85 ++- src/core/game/RailNetworkImpl.ts | 6 +- src/core/game/UnitGrid.ts | 4 +- src/core/game/UnitImpl.ts | 30 +- src/core/pathfinding/PathFinding.ts | 7 +- src/core/pathfinding/SerialAStar.ts | 10 +- src/core/validations/username.ts | 3 +- src/server/Archive.ts | 31 +- src/server/GameManager.ts | 2 +- src/server/Logger.ts | 17 +- src/server/MapPlaylist.ts | 2 +- src/server/OtelResource.ts | 13 +- src/server/WorkerMetrics.ts | 2 +- src/server/jwt.ts | 3 +- tests/AllianceExtensionExecution.test.ts | 2 +- tests/Attack.test.ts | 4 +- tests/BotBehavior.test.ts | 12 +- tests/Censor.test.ts | 34 +- tests/Colors.test.ts | 22 +- tests/DeleteUnitExecution.test.ts | 2 +- tests/Donate.test.ts | 8 +- .../graphics/RadialMenuElements.test.ts | 82 +-- tests/client/graphics/UILayer.test.ts | 50 +- .../executions/SAMLauncherExecution.test.ts | 30 +- .../executions/TradeShipExecution.test.ts | 54 +- tests/core/game/Cluster.test.ts | 2 +- tests/core/game/GameImpl.test.ts | 2 +- tests/core/game/RailNetwork.test.ts | 24 +- tests/core/game/TrainStation.test.ts | 18 +- tests/server/Privilege.customFlag.test.ts | 14 +- 95 files changed, 1385 insertions(+), 1424 deletions(-) diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 6ec54a2fe..6387df18d 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -213,10 +213,10 @@ export class ClientGameRunner { } const players: PlayerRecord[] = [ { - persistentID: getPersistentID(), - username: this.lobby.playerName, clientID: this.lobby.clientID, + persistentID: getPersistentID(), stats: update.allPlayersStats[this.lobby.clientID], + username: this.lobby.playerName, }, ]; @@ -312,8 +312,8 @@ export class ClientGameRunner { } while (turn.turnNumber - 1 > this.turnsSeen) { this.worker.sendTurn({ - turnNumber: this.turnsSeen, intents: [], + turnNumber: this.turnsSeen, }); this.turnsSeen++; } @@ -471,9 +471,9 @@ export class ClientGameRunner { ); upgradeUnits.push({ + distance, unitId: bu.canUpgrade, unitType: bu.type, - distance, }); } } diff --git a/src/client/Cosmetics.ts b/src/client/Cosmetics.ts index 6e65e8d9a..2d001ff27 100644 --- a/src/client/Cosmetics.ts +++ b/src/client/Cosmetics.ts @@ -38,16 +38,16 @@ export async function handlePurchase(priceId: string) { const response = await fetch( `${getApiBase()}/stripe/create-checkout-session`, { - method: "POST", - headers: { - "Content-Type": "application/json", - authorization: getAuthHeader(), - }, body: JSON.stringify({ + cancelUrl: `${window.location.origin}#purchase-completed=false`, priceId, successUrl: `${window.location.origin}#purchase-completed=true`, - cancelUrl: `${window.location.origin}#purchase-completed=false`, }), + headers: { + authorization: getAuthHeader(), + "Content-Type": "application/json", + }, + method: "POST", }, ); diff --git a/src/client/FlagInput.ts b/src/client/FlagInput.ts index 5ca313364..009d4ae98 100644 --- a/src/client/FlagInput.ts +++ b/src/client/FlagInput.ts @@ -36,9 +36,9 @@ export class FlagInput extends LitElement { private dispatchFlagEvent() { this.dispatchEvent( new CustomEvent("flag-change", { - detail: { flag: this.flag }, bubbles: true, composed: true, + detail: { flag: this.flag }, }), ); } diff --git a/src/client/FlagInputModal.ts b/src/client/FlagInputModal.ts index 7497eafbb..3af32557d 100644 --- a/src/client/FlagInputModal.ts +++ b/src/client/FlagInputModal.ts @@ -87,9 +87,9 @@ export class FlagInputModal extends LitElement { localStorage.setItem("flag", flag); this.dispatchEvent( new CustomEvent("flag-change", { - detail: { flag }, bubbles: true, composed: true, + detail: { flag }, }), ); } diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index b950ae375..3437ad3df 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -544,12 +544,12 @@ export class HostLobbyModal extends LitElement { .then(() => { this.dispatchEvent( new CustomEvent("join-lobby", { - detail: { - gameID: this.lobbyId, - clientID: this.lobbyCreatorClientID, - } as JoinLobbyEvent, bubbles: true, composed: true, + detail: { + clientID: this.lobbyCreatorClientID, + gameID: this.lobbyId, + } as JoinLobbyEvent, }), ); }); @@ -655,24 +655,24 @@ export class HostLobbyModal extends LitElement { const response = await fetch( `${window.location.origin}/${config.workerPath(this.lobbyId)}/api/game/${this.lobbyId}`, { - method: "PUT", + body: JSON.stringify({ + bots: this.bots, + difficulty: this.selectedDifficulty, + disabledUnits: this.disabledUnits, + disableNPCs: this.disableNPCs, + donateGold: this.donateGold, + donateTroops: this.donateTroops, + gameMap: this.selectedMap, + gameMode: this.gameMode, + infiniteGold: this.infiniteGold, + infiniteTroops: this.infiniteTroops, + instantBuild: this.instantBuild, + playerTeams: this.teamCount, + } satisfies Partial), headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - gameMap: this.selectedMap, - difficulty: this.selectedDifficulty, - disableNPCs: this.disableNPCs, - bots: this.bots, - infiniteGold: this.infiniteGold, - donateGold: this.donateGold, - infiniteTroops: this.infiniteTroops, - donateTroops: this.donateTroops, - instantBuild: this.instantBuild, - gameMode: this.gameMode, - disabledUnits: this.disabledUnits, - playerTeams: this.teamCount, - } satisfies Partial), + method: "PUT", }, ); return response; @@ -709,10 +709,10 @@ export class HostLobbyModal extends LitElement { const response = await fetch( `${window.location.origin}/${config.workerPath(this.lobbyId)}/api/start_game/${this.lobbyId}`, { - method: "POST", headers: { "Content-Type": "application/json", }, + method: "POST", }, ); return response; @@ -736,10 +736,10 @@ export class HostLobbyModal extends LitElement { private async pollPlayers() { const config = await getServerConfigFromClient(); fetch(`/${config.workerPath(this.lobbyId)}/api/game/${this.lobbyId}`, { - method: "GET", headers: { "Content-Type": "application/json", }, + method: "GET", }) .then((response) => response.json()) .then(GameInfoSchema.parse) @@ -754,9 +754,9 @@ export class HostLobbyModal extends LitElement { // Dispatch event to be handled by WebSocket instead of HTTP this.dispatchEvent( new CustomEvent("kick-player", { - detail: { target: clientID }, bubbles: true, composed: true, + detail: { target: clientID }, }), ); } @@ -769,10 +769,10 @@ async function createLobby(creatorClientID: string): Promise { const response = await fetch( `/${config.workerPath(id)}/api/create_game/${id}?creatorClientID=${encodeURIComponent(creatorClientID)}`, { - method: "POST", headers: { "Content-Type": "application/json", }, + method: "POST", // body: JSON.stringify(data), // Include this if you need to send data }, ); diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 563f934d6..67b865669 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -145,20 +145,20 @@ export class InputHandler { initialize() { this.keybinds = { - toggleView: "Space", - centerCamera: "KeyC", - moveUp: "KeyW", - moveDown: "KeyS", - moveLeft: "KeyA", - moveRight: "KeyD", - zoomOut: "KeyQ", - zoomIn: "KeyE", + altKey: "AltLeft", attackRatioDown: "Digit1", attackRatioUp: "Digit2", boatAttack: "KeyB", + centerCamera: "KeyC", groundAttack: "KeyG", modifierKey: "ControlLeft", - altKey: "AltLeft", + moveDown: "KeyS", + moveLeft: "KeyA", + moveRight: "KeyD", + moveUp: "KeyW", + toggleView: "Space", + zoomIn: "KeyE", + zoomOut: "KeyQ", ...(JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}") ?? {}), }; diff --git a/src/client/JoinPrivateLobbyModal.ts b/src/client/JoinPrivateLobbyModal.ts index f16e3806f..fdabfd47d 100644 --- a/src/client/JoinPrivateLobbyModal.ts +++ b/src/client/JoinPrivateLobbyModal.ts @@ -145,9 +145,9 @@ export class JoinPrivateLobbyModal extends LitElement { this.message = ""; this.dispatchEvent( new CustomEvent("leave-lobby", { - detail: { lobby: this.lobbyIdInput.value }, bubbles: true, composed: true, + detail: { lobby: this.lobbyIdInput.value }, }), ); } @@ -211,8 +211,8 @@ export class JoinPrivateLobbyModal extends LitElement { const url = `/${config.workerPath(lobbyId)}/api/game/${lobbyId}/exists`; const response = await fetch(url, { - method: "GET", headers: { "Content-Type": "application/json" }, + method: "GET", }); const json = await response.json(); @@ -224,12 +224,12 @@ export class JoinPrivateLobbyModal extends LitElement { this.dispatchEvent( new CustomEvent("join-lobby", { - detail: { - gameID: lobbyId, - clientID: getClientID(lobbyId), - } as JoinLobbyEvent, bubbles: true, composed: true, + detail: { + clientID: getClientID(lobbyId), + gameID: lobbyId, + } as JoinLobbyEvent, }), ); @@ -245,8 +245,8 @@ export class JoinPrivateLobbyModal extends LitElement { const archiveUrl = `/${config.workerPath(lobbyId)}/api/archived_game/${lobbyId}`; const archiveResponse = await fetch(archiveUrl, { - method: "GET", headers: { "Content-Type": "application/json" }, + method: "GET", }); const json = await archiveResponse.json(); @@ -268,13 +268,13 @@ export class JoinPrivateLobbyModal extends LitElement { if (archiveData.exists) { this.dispatchEvent( new CustomEvent("join-lobby", { - detail: { - gameID: lobbyId, - gameRecord: archiveData.gameRecord, - clientID: getClientID(lobbyId), - } as JoinLobbyEvent, bubbles: true, composed: true, + detail: { + clientID: getClientID(lobbyId), + gameID: lobbyId, + gameRecord: archiveData.gameRecord, + } as JoinLobbyEvent, }), ); @@ -291,10 +291,10 @@ export class JoinPrivateLobbyModal extends LitElement { fetch( `/${config.workerPath(this.lobbyIdInput.value)}/api/game/${this.lobbyIdInput.value}`, { - method: "GET", headers: { "Content-Type": "application/json", }, + method: "GET", }, ) .then((response) => response.json()) diff --git a/src/client/LangSelector.ts b/src/client/LangSelector.ts index fe2e9a98a..49efb33b8 100644 --- a/src/client/LangSelector.ts +++ b/src/client/LangSelector.ts @@ -51,32 +51,32 @@ export class LangSelector extends LitElement { ar, bg, bn, + cs, + da, de, en, - es, eo, + es, + fi, fr, - it, + gl, + he, hi, + it, ja, + ko, nl, pl, "pt-BR": pt_BR, ru, sh, - tr, - tp, - uk, - cs, - he, - da, - fi, - "sv-SE": sv_SE, - "zh-CN": zh_CN, - ko, - gl, - sl, sk, + sl, + "sv-SE": sv_SE, + tp, + tr, + uk, + "zh-CN": zh_CN, }; createRenderRoot() { @@ -148,8 +148,8 @@ export class LangSelector extends LitElement { list.push({ code: langData.lang_code ?? langCode, - native: langData.native ?? langCode, en: langData.en ?? langCode, + native: langData.native ?? langCode, svg: langData.svg ?? langCode, }); } @@ -159,8 +159,8 @@ export class LangSelector extends LitElement { if (this.debugKeyPressed) { debugLang = { code: "debug", - native: "Debug", en: "Debug", + native: "Debug", svg: "xx", }; this.debugMode = true; @@ -290,13 +290,13 @@ export class LangSelector extends LitElement { (this.currentLang === "debug" ? { code: "debug", - native: "Debug", en: "Debug", + native: "Debug", svg: "xx", } : { - native: "English", en: "English", + native: "English", svg: "uk_us_flag", }); diff --git a/src/client/LanguageModal.ts b/src/client/LanguageModal.ts index f9c1b2503..98333fc01 100644 --- a/src/client/LanguageModal.ts +++ b/src/client/LanguageModal.ts @@ -54,9 +54,9 @@ export class LanguageModal extends LitElement { private readonly selectLanguage = (lang: string) => { this.dispatchEvent( new CustomEvent("language-selected", { - detail: { lang }, bubbles: true, composed: true, + detail: { lang }, }), ); }; diff --git a/src/client/LocalPersistantStats.ts b/src/client/LocalPersistantStats.ts index 0ddee187b..06d7d5ca0 100644 --- a/src/client/LocalPersistantStats.ts +++ b/src/client/LocalPersistantStats.ts @@ -12,9 +12,9 @@ import { replacer } from "../core/Util"; const LocalStatsDataSchema = z.record( ID, z.object({ - lobby: GameConfigSchema.partial(), // Only once the game is over gameRecord: GameRecordSchema.optional(), + lobby: GameConfigSchema.partial(), }), ); type LocalStatsData = z.infer; diff --git a/src/client/LocalServer.ts b/src/client/LocalServer.ts index 121f0196f..d5bc46640 100644 --- a/src/client/LocalServer.ts +++ b/src/client/LocalServer.ts @@ -76,9 +76,9 @@ export class LocalServer { throw new Error("missing gameStartInfo"); } this.clientMessage({ - type: "start", gameStartInfo: this.lobbyConfig.gameStartInfo, turns: [], + type: "start", } satisfies ServerStartGameMessage); } @@ -122,11 +122,11 @@ export class LocalServer { }, server hash: ${archivedHash}`, ); this.clientMessage({ - type: "desync", - turn: clientMsg.turnNumber, - correctHash: archivedHash, clientsWithCorrectHash: 0, + correctHash: archivedHash, totalActiveClients: 1, + turn: clientMsg.turnNumber, + type: "desync", yourHash: clientMsg.hash, }); } else { @@ -160,14 +160,14 @@ export class LocalServer { this.intents = this.replayTurns[this.turns.length].intents; } const pastTurn: Turn = { - turnNumber: this.turns.length, intents: this.intents, + turnNumber: this.turns.length, }; this.turns.push(pastTurn); this.intents = []; this.clientMessage({ - type: "turn", turn: pastTurn, + type: "turn", }); } @@ -179,10 +179,10 @@ export class LocalServer { } const players: PlayerRecord[] = [ { - persistentID: getPersistentID(), - username: this.lobbyConfig.playerName, clientID: this.lobbyConfig.clientID, + persistentID: getPersistentID(), stats: this.allPlayersStats[this.lobbyConfig.clientID], + username: this.lobbyConfig.playerName, }, ]; if (this.lobbyConfig.gameStartInfo === undefined) { diff --git a/src/client/Main.ts b/src/client/Main.ts index da9378fdc..fbab2b439 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -471,18 +471,18 @@ class Client { this.gameStop = joinLobby( this.eventBus, { - gameID: lobby.gameID, - serverConfig: config, - pattern: this.userSettings.getSelectedPattern(), + clientID: getClientID(lobby.gameID), flag: this.flagInput === null || this.flagInput.getCurrentFlag() === "xx" ? "" : this.flagInput.getCurrentFlag(), - playerName: this.usernameInput?.getCurrentUsername() ?? "", - token: getPlayToken(), - clientID: getClientID(lobby.gameID), - gameStartInfo: lobby.gameStartInfo ?? lobby.gameRecord?.info, + gameID: lobby.gameID, gameRecord: lobby.gameRecord, + gameStartInfo: lobby.gameStartInfo ?? lobby.gameRecord?.info, + pattern: this.userSettings.getSelectedPattern(), + playerName: this.usernameInput?.getCurrentUsername() ?? "", + serverConfig: config, + token: getPlayToken(), }, () => { console.log("Closing modals"); diff --git a/src/client/NewsModal.ts b/src/client/NewsModal.ts index 75df2ddb3..8b4005975 100644 --- a/src/client/NewsModal.ts +++ b/src/client/NewsModal.ts @@ -74,8 +74,8 @@ export class NewsModal extends LitElement {
${resolveMarkdown(this.markdown, { - includeImages: true, includeCodeBlockClassNames: true, + includeImages: true, })}
diff --git a/src/client/PublicLobby.ts b/src/client/PublicLobby.ts index fb72f5b63..1f0f30d28 100644 --- a/src/client/PublicLobby.ts +++ b/src/client/PublicLobby.ts @@ -206,20 +206,20 @@ export class PublicLobby extends LitElement { this.currLobby = lobby; this.dispatchEvent( new CustomEvent("join-lobby", { - detail: { - gameID: lobby.gameID, - clientID: getClientID(lobby.gameID), - } as JoinLobbyEvent, bubbles: true, composed: true, + detail: { + clientID: getClientID(lobby.gameID), + gameID: lobby.gameID, + } as JoinLobbyEvent, }), ); } else { this.dispatchEvent( new CustomEvent("leave-lobby", { - detail: { lobby: this.currLobby }, bubbles: true, composed: true, + detail: { lobby: this.currLobby }, }), ); this.leaveLobby(); diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index 25a70195d..405a95afd 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -439,43 +439,43 @@ export class SinglePlayerModal extends LitElement { } this.dispatchEvent( new CustomEvent("join-lobby", { + bubbles: true, + composed: true, detail: { clientID, gameID, gameStartInfo: { + config: { + bots: this.bots, + difficulty: this.selectedDifficulty, + disabledUnits: this.disabledUnits + .map((u) => Object.values(UnitType).find((ut) => ut === u)) + .filter((ut): ut is UnitType => ut !== undefined), + disableNPCs: this.disableNPCs, + donateGold: this.donateGold, + donateTroops: this.donateTroops, + gameMap: this.selectedMap, + gameMode: this.gameMode, + gameType: GameType.Singleplayer, + infiniteGold: this.infiniteGold, + infiniteTroops: this.infiniteTroops, + instantBuild: this.instantBuild, + playerTeams: this.teamCount, + }, gameID, players: [ { clientID, - username: usernameInput.getCurrentUsername(), flag: flagInput.getCurrentFlag() === "xx" ? "" : flagInput.getCurrentFlag(), pattern: this.userSettings.getSelectedPattern(), + username: usernameInput.getCurrentUsername(), }, ], - config: { - gameMap: this.selectedMap, - gameType: GameType.Singleplayer, - gameMode: this.gameMode, - playerTeams: this.teamCount, - difficulty: this.selectedDifficulty, - disableNPCs: this.disableNPCs, - bots: this.bots, - infiniteGold: this.infiniteGold, - donateGold: this.donateGold, - infiniteTroops: this.infiniteTroops, - donateTroops: this.donateTroops, - instantBuild: this.instantBuild, - disabledUnits: this.disabledUnits - .map((u) => Object.values(UnitType).find((ut) => ut === u)) - .filter((ut): ut is UnitType => ut !== undefined), - }, }, } satisfies JoinLobbyEvent, - bubbles: true, - composed: true, }), ); this.close(); diff --git a/src/client/Transport.ts b/src/client/Transport.ts index 20f506ab6..3c0b60118 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -375,14 +375,14 @@ export class Transport { joinGame(numTurns: number) { this.sendMsg({ - type: "join", - gameID: this.lobbyConfig.gameID, clientID: this.lobbyConfig.clientID, - lastTurn: numTurns, - token: this.lobbyConfig.token, - username: this.lobbyConfig.playerName, flag: this.lobbyConfig.flag, + gameID: this.lobbyConfig.gameID, + lastTurn: numTurns, pattern: this.lobbyConfig.pattern, + token: this.lobbyConfig.token, + type: "join", + username: this.lobbyConfig.playerName, } satisfies ClientJoinMessage); } @@ -408,26 +408,26 @@ export class Transport { private onSendAllianceRequest(event: SendAllianceRequestIntentEvent) { this.sendIntent({ - type: "allianceRequest", clientID: this.lobbyConfig.clientID, recipient: event.recipient.id(), + type: "allianceRequest", }); } private onAllianceRequestReplyUIEvent(event: SendAllianceReplyIntentEvent) { this.sendIntent({ - type: "allianceRequestReply", + accept: event.accepted, clientID: this.lobbyConfig.clientID, requestor: event.requestor.id(), - accept: event.accepted, + type: "allianceRequestReply", }); } private onBreakAllianceRequestUIEvent(event: SendBreakAllianceIntentEvent) { this.sendIntent({ - type: "breakAlliance", clientID: this.lobbyConfig.clientID, recipient: event.recipient.id(), + type: "breakAlliance", }); } @@ -435,114 +435,114 @@ export class Transport { event: SendAllianceExtensionIntentEvent, ) { this.sendIntent({ - type: "allianceExtension", clientID: this.lobbyConfig.clientID, recipient: event.recipient.id(), + type: "allianceExtension", }); } private onSendSpawnIntentEvent(event: SendSpawnIntentEvent) { this.sendIntent({ - type: "spawn", clientID: this.lobbyConfig.clientID, flag: this.lobbyConfig.flag, - pattern: this.lobbyConfig.pattern, name: this.lobbyConfig.playerName, + pattern: this.lobbyConfig.pattern, playerType: PlayerType.Human, tile: event.tile, + type: "spawn", }); } private onSendAttackIntent(event: SendAttackIntentEvent) { this.sendIntent({ - type: "attack", clientID: this.lobbyConfig.clientID, targetID: event.targetID, troops: event.troops, + type: "attack", }); } private onSendBoatAttackIntent(event: SendBoatAttackIntentEvent) { this.sendIntent({ - type: "boat", clientID: this.lobbyConfig.clientID, - targetID: event.targetID, - troops: event.troops, dst: event.dst, src: event.src, + targetID: event.targetID, + troops: event.troops, + type: "boat", }); } private onSendUpgradeStructureIntent(event: SendUpgradeStructureIntentEvent) { this.sendIntent({ + clientID: this.lobbyConfig.clientID, type: "upgrade_structure", unit: event.unitType, - clientID: this.lobbyConfig.clientID, unitId: event.unitId, }); } private onSendTargetPlayerIntent(event: SendTargetPlayerIntentEvent) { this.sendIntent({ - type: "targetPlayer", clientID: this.lobbyConfig.clientID, target: event.targetID, + type: "targetPlayer", }); } private onSendEmojiIntent(event: SendEmojiIntentEvent) { this.sendIntent({ - type: "emoji", clientID: this.lobbyConfig.clientID, + emoji: event.emoji, recipient: event.recipient === AllPlayers ? AllPlayers : event.recipient.id(), - emoji: event.emoji, + type: "emoji", }); } private onSendDonateGoldIntent(event: SendDonateGoldIntentEvent) { this.sendIntent({ - type: "donate_gold", clientID: this.lobbyConfig.clientID, - recipient: event.recipient.id(), gold: event.gold, + recipient: event.recipient.id(), + type: "donate_gold", }); } private onSendDonateTroopIntent(event: SendDonateTroopsIntentEvent) { this.sendIntent({ - type: "donate_troops", clientID: this.lobbyConfig.clientID, recipient: event.recipient.id(), troops: event.troops, + type: "donate_troops", }); } private onSendQuickChatIntent(event: SendQuickChatEvent) { this.sendIntent({ - type: "quick_chat", clientID: this.lobbyConfig.clientID, - recipient: event.recipient.id(), quickChatKey: event.quickChatKey, + recipient: event.recipient.id(), target: event.target, + type: "quick_chat", }); } private onSendEmbargoIntent(event: SendEmbargoIntentEvent) { this.sendIntent({ - type: "embargo", + action: event.action, clientID: this.lobbyConfig.clientID, targetID: event.target.id(), - action: event.action, + type: "embargo", }); } private onBuildUnitIntent(event: BuildUnitIntentEvent) { this.sendIntent({ - type: "build_unit", clientID: this.lobbyConfig.clientID, - unit: event.unit, tile: event.tile, + type: "build_unit", + unit: event.unit, }); } @@ -561,9 +561,9 @@ export class Transport { private onSendWinnerEvent(event: SendWinnerEvent) { if (this.isLocal || this.socket?.readyState === WebSocket.OPEN) { this.sendMsg({ + allPlayersStats: event.allPlayersStats, type: "winner", winner: event.winner, - allPlayersStats: event.allPlayersStats, } satisfies ClientSendWinnerMessage); } else { console.log( @@ -577,9 +577,9 @@ export class Transport { private onSendHashEvent(event: SendHashEvent) { if (this.isLocal || this.socket?.readyState === WebSocket.OPEN) { this.sendMsg({ - type: "hash", - turnNumber: event.tick, hash: event.hash, + turnNumber: event.tick, + type: "hash", } satisfies ClientHashMessage); } else { console.log( @@ -592,50 +592,50 @@ export class Transport { private onCancelAttackIntentEvent(event: CancelAttackIntentEvent) { this.sendIntent({ - type: "cancel_attack", - clientID: this.lobbyConfig.clientID, attackID: event.attackID, + clientID: this.lobbyConfig.clientID, + type: "cancel_attack", }); } private onCancelBoatIntentEvent(event: CancelBoatIntentEvent) { this.sendIntent({ - type: "cancel_boat", clientID: this.lobbyConfig.clientID, + type: "cancel_boat", unitID: event.unitID, }); } private onMoveWarshipEvent(event: MoveWarshipIntentEvent) { this.sendIntent({ - type: "move_warship", clientID: this.lobbyConfig.clientID, - unitId: event.unitId, tile: event.tile, + type: "move_warship", + unitId: event.unitId, }); } private onSendDeleteUnitIntent(event: SendDeleteUnitIntentEvent) { this.sendIntent({ - type: "delete_unit", clientID: this.lobbyConfig.clientID, + type: "delete_unit", unitId: event.unitId, }); } private onSendKickPlayerIntent(event: SendKickPlayerIntentEvent) { this.sendIntent({ - type: "kick_player", clientID: this.lobbyConfig.clientID, target: event.target, + type: "kick_player", }); } private sendIntent(intent: Intent) { if (this.isLocal || this.socket?.readyState === WebSocket.OPEN) { const msg = { - type: "intent", intent, + type: "intent", } satisfies ClientIntentMessage; this.sendMsg(msg); } else { diff --git a/src/client/UserSettingModal.ts b/src/client/UserSettingModal.ts index a5707ab2f..2f8449905 100644 --- a/src/client/UserSettingModal.ts +++ b/src/client/UserSettingModal.ts @@ -100,9 +100,9 @@ export class UserSettingModal extends LitElement { this.dispatchEvent( new CustomEvent("dark-mode-changed", { - detail: { darkMode: enabled }, bubbles: true, composed: true, + detail: { darkMode: enabled }, }), ); diff --git a/src/client/UsernameInput.ts b/src/client/UsernameInput.ts index 3cea66c23..7f3127247 100644 --- a/src/client/UsernameInput.ts +++ b/src/client/UsernameInput.ts @@ -93,9 +93,9 @@ export class UsernameInput extends LitElement { private dispatchUsernameEvent() { this.dispatchEvent( new CustomEvent("username-change", { - detail: { username: this.username }, bubbles: true, composed: true, + detail: { username: this.username }, }), ); } diff --git a/src/client/Utils.ts b/src/client/Utils.ts index 9cea30f6a..83564f92a 100644 --- a/src/client/Utils.ts +++ b/src/client/Utils.ts @@ -150,11 +150,11 @@ export const translateText = ( * Severity colors mapping for message types */ export const severityColors: Record = { - fail: "text-red-400", - warn: "text-yellow-400", - success: "text-green-400", - info: "text-gray-200", blue: "text-blue-400", + fail: "text-red-400", + info: "text-gray-200", + success: "text-green-400", + warn: "text-yellow-400", white: "text-white", }; diff --git a/src/client/components/Maps.ts b/src/client/components/Maps.ts index 6677925a3..76f4d3501 100644 --- a/src/client/components/Maps.ts +++ b/src/client/components/Maps.ts @@ -6,35 +6,35 @@ import { translateText } from "../Utils"; // Add map descriptions export const MapDescription: Record = { - World: "World", - GiantWorldMap: "Giant World Map", + Africa: "Africa", + Asia: "Asia", + Australia: "Australia", + Baikal: "Baikal", + BetweenTwoSeas: "Between Two Seas", + BlackSea: "Black Sea", + Britannia: "Britannia", + DeglaciatedAntarctica: "Deglaciated Antarctica", + EastAsia: "East Asia", Europe: "Europe", EuropeClassic: "Europe Classic", + FalklandIslands: "Falkland Islands", + FaroeIslands: "Faroe Islands", + GatewayToTheAtlantic: "Gateway to the Atlantic", + GiantWorldMap: "Giant World Map", + Halkidiki: "Halkidiki", + Iceland: "Iceland", + Italia: "Italia", + Mars: "Mars", + MarsRevised: "Mars Revised", Mena: "MENA", NorthAmerica: "North America", Oceania: "Oceania", - BlackSea: "Black Sea", - Africa: "Africa", Pangaea: "Pangaea", - Asia: "Asia", - Mars: "Mars", - MarsRevised: "Mars Revised", - SouthAmerica: "South America", - Britannia: "Britannia", - GatewayToTheAtlantic: "Gateway to the Atlantic", - Australia: "Australia", - Iceland: "Iceland", - EastAsia: "East Asia", - BetweenTwoSeas: "Between Two Seas", - FaroeIslands: "Faroe Islands", - DeglaciatedAntarctica: "Deglaciated Antarctica", - FalklandIslands: "Falkland Islands", - Baikal: "Baikal", - Halkidiki: "Halkidiki", - StraitOfGibraltar: "Strait of Gibraltar", - Italia: "Italia", - Yenisei: "Yenisei", Pluto: "Pluto", + SouthAmerica: "South America", + StraitOfGibraltar: "Strait of Gibraltar", + World: "World", + Yenisei: "Yenisei", }; @customElement("map-display") diff --git a/src/client/components/baseComponents/Button.ts b/src/client/components/baseComponents/Button.ts index dd02c0823..e955b84ae 100644 --- a/src/client/components/baseComponents/Button.ts +++ b/src/client/components/baseComponents/Button.ts @@ -23,8 +23,8 @@ export class OButton extends LitElement { "c-button": true, "c-button--block": this.block, "c-button--blockDesktop": this.blockDesktop, - "c-button--secondary": this.secondary, "c-button--disabled": this.disable, + "c-button--secondary": this.secondary, })} ?disabled=${this.disable} > diff --git a/src/client/components/baseComponents/setting/SettingKeybind.ts b/src/client/components/baseComponents/setting/SettingKeybind.ts index 2750103cf..d7cc9809f 100644 --- a/src/client/components/baseComponents/setting/SettingKeybind.ts +++ b/src/client/components/baseComponents/setting/SettingKeybind.ts @@ -6,7 +6,7 @@ import { translateText } from "../../../../client/Utils"; export class SettingKeybind extends LitElement { @property() label = "Setting"; @property() description = ""; - @property({ type: String, reflect: true }) action = ""; + @property({ reflect: true, type: String }) action = ""; @property({ type: String }) defaultKey = ""; @property({ type: String }) value = ""; @property({ type: Boolean }) easter = false; @@ -80,9 +80,9 @@ export class SettingKeybind extends LitElement { this.dispatchEvent( new CustomEvent("change", { - detail: { action: this.action, value: code }, bubbles: true, composed: true, + detail: { action: this.action, value: code }, }), ); @@ -94,9 +94,9 @@ export class SettingKeybind extends LitElement { this.value = this.defaultKey; this.dispatchEvent( new CustomEvent("change", { - detail: { action: this.action, value: this.defaultKey }, bubbles: true, composed: true, + detail: { action: this.action, value: this.defaultKey }, }), ); } @@ -105,9 +105,9 @@ export class SettingKeybind extends LitElement { this.value = ""; this.dispatchEvent( new CustomEvent("change", { - detail: { action: this.action, value: "Null" }, bubbles: true, composed: true, + detail: { action: this.action, value: "Null" }, }), ); this.requestUpdate(); diff --git a/src/client/components/baseComponents/setting/SettingNumber.ts b/src/client/components/baseComponents/setting/SettingNumber.ts index e36f96c72..c9ecdae2b 100644 --- a/src/client/components/baseComponents/setting/SettingNumber.ts +++ b/src/client/components/baseComponents/setting/SettingNumber.ts @@ -21,9 +21,9 @@ export class SettingNumber extends LitElement { this.dispatchEvent( new CustomEvent("change", { - detail: { value: newValue }, bubbles: true, composed: true, + detail: { value: newValue }, }), ); } diff --git a/src/client/components/baseComponents/setting/SettingSlider.ts b/src/client/components/baseComponents/setting/SettingSlider.ts index 466b44e75..4108506e6 100644 --- a/src/client/components/baseComponents/setting/SettingSlider.ts +++ b/src/client/components/baseComponents/setting/SettingSlider.ts @@ -21,9 +21,9 @@ export class SettingSlider extends LitElement { this.dispatchEvent( new CustomEvent("change", { - detail: { value: this.value }, bubbles: true, composed: true, + detail: { value: this.value }, }), ); } diff --git a/src/client/components/baseComponents/setting/SettingToggle.ts b/src/client/components/baseComponents/setting/SettingToggle.ts index 5eb278d09..b1b7c5bdc 100644 --- a/src/client/components/baseComponents/setting/SettingToggle.ts +++ b/src/client/components/baseComponents/setting/SettingToggle.ts @@ -6,7 +6,7 @@ export class SettingToggle extends LitElement { @property() label = "Setting"; @property() description = ""; @property() id = ""; - @property({ type: Boolean, reflect: true }) checked = false; + @property({ reflect: true, type: Boolean }) checked = false; @property({ type: Boolean }) easter = false; createRenderRoot() { @@ -18,9 +18,9 @@ export class SettingToggle extends LitElement { this.checked = input.checked; this.dispatchEvent( new CustomEvent("change", { - detail: { checked: this.checked }, bubbles: true, composed: true, + detail: { checked: this.checked }, }), ); } diff --git a/src/client/graphics/AnimatedSpriteLoader.ts b/src/client/graphics/AnimatedSpriteLoader.ts index b3a8c6cee..51e691d5e 100644 --- a/src/client/graphics/AnimatedSpriteLoader.ts +++ b/src/client/graphics/AnimatedSpriteLoader.ts @@ -27,103 +27,103 @@ type AnimatedSpriteConfig = { const ANIMATED_SPRITE_CONFIG: Partial> = { [FxType.MiniFire]: { - url: miniFire, - frameWidth: 7, frameCount: 6, frameDuration: 100, + frameWidth: 7, looping: true, originX: 3, originY: 11, + url: miniFire, }, [FxType.MiniSmoke]: { - url: miniSmoke, - frameWidth: 11, frameCount: 4, frameDuration: 120, + frameWidth: 11, looping: true, originX: 2, originY: 10, + url: miniSmoke, }, [FxType.MiniBigSmoke]: { - url: miniBigSmoke, - frameWidth: 24, frameCount: 5, frameDuration: 120, + frameWidth: 24, looping: true, originX: 9, originY: 14, + url: miniBigSmoke, }, [FxType.MiniSmokeAndFire]: { - url: miniSmokeAndFire, - frameWidth: 24, frameCount: 5, frameDuration: 120, + frameWidth: 24, looping: true, originX: 9, originY: 14, + url: miniSmokeAndFire, }, [FxType.MiniExplosion]: { - url: miniExplosion, - frameWidth: 13, frameCount: 4, frameDuration: 70, + frameWidth: 13, looping: false, originX: 6, originY: 6, + url: miniExplosion, }, [FxType.Dust]: { - url: dust, - frameWidth: 9, frameCount: 3, frameDuration: 100, + frameWidth: 9, looping: false, originX: 4, originY: 5, + url: dust, }, [FxType.UnitExplosion]: { - url: unitExplosion, - frameWidth: 19, frameCount: 4, frameDuration: 70, + frameWidth: 19, looping: false, originX: 9, originY: 9, + url: unitExplosion, }, [FxType.SinkingShip]: { - url: sinkingShip, - frameWidth: 16, frameCount: 14, frameDuration: 90, + frameWidth: 16, looping: false, originX: 7, originY: 7, + url: sinkingShip, }, [FxType.Nuke]: { - url: nuke, - frameWidth: 60, frameCount: 9, frameDuration: 70, + frameWidth: 60, looping: false, originX: 30, originY: 30, + url: nuke, }, [FxType.SAMExplosion]: { - url: SAMExplosion, - frameWidth: 48, frameCount: 9, frameDuration: 70, + frameWidth: 48, looping: false, originX: 23, originY: 19, + url: SAMExplosion, }, [FxType.Conquest]: { - url: conquestSword, - frameWidth: 21, frameCount: 10, frameDuration: 90, + frameWidth: 21, looping: false, originX: 10, originY: 16, + url: conquestSword, }, }; diff --git a/src/client/graphics/NameBoxCalculator.ts b/src/client/graphics/NameBoxCalculator.ts index 2abc98573..be5cdc8e7 100644 --- a/src/client/graphics/NameBoxCalculator.ts +++ b/src/client/graphics/NameBoxCalculator.ts @@ -56,9 +56,9 @@ export function placeName(game: Game, player: Player): NameViewData { center = new Cell(center.x, center.y - fontSize / 3); return { + size: fontSize, x: Math.ceil(center.x), y: Math.ceil(center.y), - size: fontSize, }; } @@ -69,14 +69,14 @@ export function createGrid( scalingFactor: number, ): boolean[][] { const scaledBoundingBox: { min: Point; max: Point } = { - min: { - x: Math.floor(boundingBox.min.x / scalingFactor), - y: Math.floor(boundingBox.min.y / scalingFactor), - }, max: { x: Math.floor(boundingBox.max.x / scalingFactor), y: Math.floor(boundingBox.max.y / scalingFactor), }, + min: { + x: Math.floor(boundingBox.min.x / scalingFactor), + y: Math.floor(boundingBox.min.y / scalingFactor), + }, }; const width = scaledBoundingBox.max.x - scaledBoundingBox.min.x + 1; @@ -105,7 +105,7 @@ export function findLargestInscribedRectangle(grid: boolean[][]): Rectangle { const rows = grid[0].length; const cols = grid.length; const heights: number[] = new Array(cols).fill(0); - let largestRect: Rectangle = { x: 0, y: 0, width: 0, height: 0 }; + let largestRect: Rectangle = { height: 0, width: 0, x: 0, y: 0 }; for (let row = 0; row < rows; row++) { for (let col = 0; col < cols; col++) { @@ -123,10 +123,10 @@ export function findLargestInscribedRectangle(grid: boolean[][]): Rectangle { largestRect.width * largestRect.height ) { largestRect = { + height: rectForRow.height, + width: rectForRow.width, x: rectForRow.x, y: row - rectForRow.height + 1, - width: rectForRow.width, - height: rectForRow.height, }; } } @@ -137,7 +137,7 @@ export function findLargestInscribedRectangle(grid: boolean[][]): Rectangle { export function largestRectangleInHistogram(widths: number[]): Rectangle { const stack: number[] = []; let maxArea = 0; - let largestRect: Rectangle = { x: 0, y: 0, width: 0, height: 0 }; + let largestRect: Rectangle = { height: 0, width: 0, x: 0, y: 0 }; for (let i = 0; i <= widths.length; i++) { const h = i === widths.length ? 0 : widths[i]; @@ -151,10 +151,10 @@ export function largestRectangleInHistogram(widths: number[]): Rectangle { if (height * width > maxArea) { maxArea = height * width; largestRect = { + height, + width, x: stack.length === 0 ? 0 : stack[stack.length - 1] + 1, y: 0, - width, - height, }; } } diff --git a/src/client/graphics/SpriteLoader.ts b/src/client/graphics/SpriteLoader.ts index 95a913b47..12279bf4c 100644 --- a/src/client/graphics/SpriteLoader.ts +++ b/src/client/graphics/SpriteLoader.ts @@ -15,8 +15,8 @@ import { UnitView } from "../../core/game/GameView"; // Can't reuse TrainType because "loaded" is not a type, just an attribute const TrainTypeSprite = { - Engine: "Engine", Carriage: "Carriage", + Engine: "Engine", LoadedCarriage: "LoadedCarriage", } as const; diff --git a/src/client/graphics/fx/NukeFx.ts b/src/client/graphics/fx/NukeFx.ts index bebf04621..81b1ed693 100644 --- a/src/client/graphics/fx/NukeFx.ts +++ b/src/client/graphics/fx/NukeFx.ts @@ -88,10 +88,10 @@ export function nukeFxFactory( radiusFactor: number; density: number; }> = [ - { type: FxType.MiniFire, radiusFactor: 1.0, density: 1 / 25 }, - { type: FxType.MiniSmoke, radiusFactor: 1.0, density: 1 / 28 }, - { type: FxType.MiniBigSmoke, radiusFactor: 0.9, density: 1 / 70 }, - { type: FxType.MiniSmokeAndFire, radiusFactor: 0.9, density: 1 / 70 }, + { density: 1 / 25, radiusFactor: 1.0, type: FxType.MiniFire }, + { density: 1 / 28, radiusFactor: 1.0, type: FxType.MiniSmoke }, + { density: 1 / 70, radiusFactor: 0.9, type: FxType.MiniBigSmoke }, + { density: 1 / 70, radiusFactor: 0.9, type: FxType.MiniSmokeAndFire }, ]; for (const { type, radiusFactor, density } of debrisPlan) { diff --git a/src/client/graphics/fx/TextFx.ts b/src/client/graphics/fx/TextFx.ts index cfc7288f8..1c034a9b6 100644 --- a/src/client/graphics/fx/TextFx.ts +++ b/src/client/graphics/fx/TextFx.ts @@ -11,9 +11,9 @@ export class TextFx implements Fx { private readonly riseDistance = 30, private readonly font = "11px sans-serif", private readonly color: { r: number; g: number; b: number } = { - r: 255, - g: 255, b: 255, + g: 255, + r: 255, }, ) {} diff --git a/src/client/graphics/fx/Timeline.ts b/src/client/graphics/fx/Timeline.ts index d500a1f33..26918a865 100644 --- a/src/client/graphics/fx/Timeline.ts +++ b/src/client/graphics/fx/Timeline.ts @@ -12,7 +12,7 @@ export class Timeline { private timeElapsed = 0; add(delay: number, action: () => void): Timeline { - this.tasks.push({ delay, action, triggered: false }); + this.tasks.push({ action, delay, triggered: false }); return this; } diff --git a/src/client/graphics/fx/UnitExplosionFx.ts b/src/client/graphics/fx/UnitExplosionFx.ts index 241e07508..f21a6fbba 100644 --- a/src/client/graphics/fx/UnitExplosionFx.ts +++ b/src/client/graphics/fx/UnitExplosionFx.ts @@ -18,9 +18,9 @@ export class UnitExplosionFx implements Fx { game: GameView, ) { const config = [ - { dx: 0, dy: 0, delay: 0, type: FxType.UnitExplosion }, - { dx: 4, dy: -6, delay: 80, type: FxType.UnitExplosion }, - { dx: -6, dy: 4, delay: 160, type: FxType.UnitExplosion }, + { delay: 0, dx: 0, dy: 0, type: FxType.UnitExplosion }, + { delay: 80, dx: 4, dy: -6, type: FxType.UnitExplosion }, + { delay: 160, dx: -6, dy: 4, type: FxType.UnitExplosion }, ]; for (const { dx, dy, delay, type } of config) { this.timeline.add(delay, () => { diff --git a/src/client/graphics/layers/BuildMenu.ts b/src/client/graphics/layers/BuildMenu.ts index dcaa11fd9..b6f49d2dd 100644 --- a/src/client/graphics/layers/BuildMenu.ts +++ b/src/client/graphics/layers/BuildMenu.ts @@ -46,75 +46,75 @@ export type BuildItemDisplay = { export const buildTable: BuildItemDisplay[][] = [ [ { - unitType: UnitType.AtomBomb, - icon: atomBombIcon, + countable: false, description: "build_menu.desc.atom_bomb", + icon: atomBombIcon, key: "unit_type.atom_bomb", - countable: false, + unitType: UnitType.AtomBomb, }, { - unitType: UnitType.MIRV, - icon: mirvIcon, + countable: false, description: "build_menu.desc.mirv", + icon: mirvIcon, key: "unit_type.mirv", - countable: false, + unitType: UnitType.MIRV, }, { - unitType: UnitType.HydrogenBomb, - icon: hydrogenBombIcon, + countable: false, description: "build_menu.desc.hydrogen_bomb", + icon: hydrogenBombIcon, key: "unit_type.hydrogen_bomb", - countable: false, + unitType: UnitType.HydrogenBomb, }, { - unitType: UnitType.Warship, - icon: warshipIcon, + countable: true, description: "build_menu.desc.warship", + icon: warshipIcon, key: "unit_type.warship", - countable: true, + unitType: UnitType.Warship, }, { - unitType: UnitType.Port, - icon: portIcon, + countable: true, description: "build_menu.desc.port", + icon: portIcon, key: "unit_type.port", - countable: true, + unitType: UnitType.Port, }, { - unitType: UnitType.MissileSilo, - icon: missileSiloIcon, - description: "build_menu.desc.missile_silo", - key: "unit_type.missile_silo", countable: true, + description: "build_menu.desc.missile_silo", + icon: missileSiloIcon, + key: "unit_type.missile_silo", + unitType: UnitType.MissileSilo, }, // needs new icon { - unitType: UnitType.SAMLauncher, - icon: samlauncherIcon, + countable: true, description: "build_menu.desc.sam_launcher", + icon: samlauncherIcon, key: "unit_type.sam_launcher", - countable: true, + unitType: UnitType.SAMLauncher, }, { - unitType: UnitType.DefensePost, - icon: shieldIcon, + countable: true, description: "build_menu.desc.defense_post", + icon: shieldIcon, key: "unit_type.defense_post", - countable: true, + unitType: UnitType.DefensePost, }, { - unitType: UnitType.City, - icon: cityIcon, + countable: true, description: "build_menu.desc.city", + icon: cityIcon, key: "unit_type.city", - countable: true, + unitType: UnitType.City, }, { - unitType: UnitType.Factory, - icon: factoryIcon, - description: "build_menu.desc.factory", - key: "unit_type.factory", countable: true, + description: "build_menu.desc.factory", + icon: factoryIcon, + key: "unit_type.factory", + unitType: UnitType.Factory, }, ], ]; diff --git a/src/client/graphics/layers/ChatDisplay.ts b/src/client/graphics/layers/ChatDisplay.ts index 5c87d25c0..56f1e0b8d 100644 --- a/src/client/graphics/layers/ChatDisplay.ts +++ b/src/client/graphics/layers/ChatDisplay.ts @@ -65,8 +65,8 @@ export class ChatDisplay extends LitElement implements Layer { } this.addEvent({ - description: event.message, createdAt: this.game.ticks(), + description: event.message, highlight: true, unsafeDescription: true, }); @@ -97,9 +97,9 @@ export class ChatDisplay extends LitElement implements Layer { this.chatEvents = [ ...this.chatEvents, { + createdAt: this.game.ticks(), description: msg.message, unsafeDescription: true, - createdAt: this.game.ticks(), }, ]; } diff --git a/src/client/graphics/layers/ChatIntegration.ts b/src/client/graphics/layers/ChatIntegration.ts index fd1984811..8d6d991ec 100644 --- a/src/client/graphics/layers/ChatIntegration.ts +++ b/src/client/graphics/layers/ChatIntegration.ts @@ -49,18 +49,6 @@ export class ChatIntegration { const phraseText = translateText(`chat.${category.id}.${phrase.key}`); return { - id: `phrase-${category.id}-${phrase.key}`, - name: phraseText, - disabled: () => false, - text: this.shortenText(phraseText), - fontSize: "10px", - color: categoryColor, - tooltipItems: [ - { - text: phraseText, - className: "description", - }, - ], action: (params: MenuElementParams) => { if (phrase.requiresPlayer) { this.ctModal.openWithSelection( @@ -79,18 +67,30 @@ export class ChatIntegration { ); } }, + color: categoryColor, + disabled: () => false, + fontSize: "10px", + id: `phrase-${category.id}-${phrase.key}`, + name: phraseText, + text: this.shortenText(phraseText), + tooltipItems: [ + { + className: "description", + text: phraseText, + }, + ], }; }, ); return { + _action: () => {}, // Empty action placeholder for RadialMenu + color: categoryColor, + disabled: () => false, id: `chat-category-${category.id}`, name: categoryTranslation, - disabled: () => false, - text: categoryTranslation, - color: categoryColor, - _action: () => {}, // Empty action placeholder for RadialMenu subMenu: () => phraseItems, + text: categoryTranslation, }; }); } diff --git a/src/client/graphics/layers/ChatModal.ts b/src/client/graphics/layers/ChatModal.ts index c8ca5ae01..ddca52279 100644 --- a/src/client/graphics/layers/ChatModal.ts +++ b/src/client/graphics/layers/ChatModal.ts @@ -49,11 +49,11 @@ export class ChatModal extends LitElement { string, Array<{ text: string; requiresPlayer: boolean }> > = { - help: [{ text: "Please give me troops!", requiresPlayer: false }], - attack: [{ text: "Attack [P1]!", requiresPlayer: true }], - defend: [{ text: "Defend [P1]!", requiresPlayer: true }], - greet: [{ text: "Hello!", requiresPlayer: false }], - misc: [{ text: "Let's go!", requiresPlayer: false }], + attack: [{ requiresPlayer: true, text: "Attack [P1]!" }], + defend: [{ requiresPlayer: true, text: "Defend [P1]!" }], + greet: [{ requiresPlayer: false, text: "Hello!" }], + help: [{ requiresPlayer: false, text: "Please give me troops!" }], + misc: [{ requiresPlayer: false, text: "Let's go!" }], }; public categories = [ diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index af089203a..4dcf860d3 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -279,35 +279,35 @@ export class EventsDisplay extends LitElement implements Layer { if (!other.isAlive()) continue; this.addEvent({ - description: translateText("events_display.about_to_expire", { - name: other.name(), - }), - type: MessageType.RENEW_ALLIANCE, - duration: this.game.config().allianceExtensionPromptOffset() - 3 * 10, // 3 second buffer buttons: [ { - text: translateText("events_display.focus"), - className: "btn-gray", action: () => this.eventBus?.emit(new GoToPlayerEvent(other)), + className: "btn-gray", preventClose: true, + text: translateText("events_display.focus"), }, { + action: () => + this.eventBus?.emit(new SendAllianceExtensionIntentEvent(other)), + className: "btn", text: translateText("events_display.renew_alliance", { name: other.name(), }), - className: "btn", - action: () => - this.eventBus?.emit(new SendAllianceExtensionIntentEvent(other)), }, { - text: translateText("events_display.ignore"), - className: "btn-info", action: () => {}, + className: "btn-info", + text: translateText("events_display.ignore"), }, ], - highlight: true, createdAt: this.game.ticks(), + description: translateText("events_display.about_to_expire", { + name: other.name(), + }), + duration: this.game.config().allianceExtensionPromptOffset() - 3 * 10, // 3 second buffer focusID: other.smallID(), + highlight: true, + type: MessageType.RENEW_ALLIANCE, }); } } @@ -374,8 +374,8 @@ export class EventsDisplay extends LitElement implements Layer { } this.addEvent({ - description, createdAt: this.game.ticks(), + description, highlight: true, type: event.messageType, unsafeDescription: true, @@ -417,11 +417,11 @@ export class EventsDisplay extends LitElement implements Layer { } this.addEvent({ - description: translateText(event.isFrom ? "chat.from" : "chat.to", { - user: otherPlayerDiplayName, - msg: translatedMessage, - }), createdAt: this.game.ticks(), + description: translateText(event.isFrom ? "chat.from" : "chat.to", { + msg: translatedMessage, + user: otherPlayerDiplayName, + }), highlight: true, type: MessageType.CHAT, unsafeDescription: false, @@ -443,43 +443,43 @@ export class EventsDisplay extends LitElement implements Layer { ) as PlayerView; this.addEvent({ - description: translateText("events_display.request_alliance", { - name: requestor.name(), - }), buttons: [ { - text: translateText("events_display.focus"), - className: "btn-gray", action: () => this.eventBus?.emit(new GoToPlayerEvent(requestor)), + className: "btn-gray", preventClose: true, + text: translateText("events_display.focus"), }, { - text: translateText("events_display.accept_alliance"), - className: "btn", action: () => this.eventBus?.emit( new SendAllianceReplyIntentEvent(requestor, recipient, true), ), + className: "btn", + text: translateText("events_display.accept_alliance"), }, { - text: translateText("events_display.reject_alliance"), - className: "btn-info", action: () => this.eventBus?.emit( new SendAllianceReplyIntentEvent(requestor, recipient, false), ), + className: "btn-info", + text: translateText("events_display.reject_alliance"), }, ], - highlight: true, - type: MessageType.ALLIANCE_REQUEST, createdAt: this.game.ticks(), + description: translateText("events_display.request_alliance", { + name: requestor.name(), + }), + duration: 150, + focusID: update.requestorID, + highlight: true, onDelete: () => this.eventBus?.emit( new SendAllianceReplyIntentEvent(requestor, recipient, false), ), priority: 0, - duration: 150, - focusID: update.requestorID, + type: MessageType.ALLIANCE_REQUEST, }); } @@ -511,18 +511,18 @@ export class EventsDisplay extends LitElement implements Layer { update.request.recipientID, ) as PlayerView; this.addEvent({ + createdAt: this.game.ticks(), description: translateText("events_display.alliance_request_status", { name: recipient.name(), status: update.accepted ? translateText("events_display.alliance_accepted") : translateText("events_display.alliance_rejected"), }), + focusID: update.request.recipientID, + highlight: true, type: update.accepted ? MessageType.ALLIANCE_ACCEPTED : MessageType.ALLIANCE_REJECTED, - highlight: true, - createdAt: this.game.ticks(), - focusID: update.request.recipientID, }); } @@ -552,34 +552,34 @@ export class EventsDisplay extends LitElement implements Layer { }); this.addEvent({ - description: translateText("events_display.betrayal_description", { - name: betrayed.name(), - malusPercent, - durationText, - }), - type: MessageType.ALLIANCE_BROKEN, - highlight: true, createdAt: this.game.ticks(), + description: translateText("events_display.betrayal_description", { + durationText, + malusPercent, + name: betrayed.name(), + }), focusID: update.betrayedID, + highlight: true, + type: MessageType.ALLIANCE_BROKEN, }); } else if (betrayed === myPlayer) { const buttons = [ { - text: translateText("events_display.focus"), - className: "btn-gray", action: () => this.eventBus?.emit(new GoToPlayerEvent(traitor)), + className: "btn-gray", preventClose: true, + text: translateText("events_display.focus"), }, ]; this.addEvent({ + buttons, + createdAt: this.game.ticks(), description: translateText("events_display.betrayed_you", { name: traitor.name(), }), - type: MessageType.ALLIANCE_BROKEN, - highlight: true, - createdAt: this.game.ticks(), focusID: update.traitorID, - buttons, + highlight: true, + type: MessageType.ALLIANCE_BROKEN, }); } } @@ -600,13 +600,13 @@ export class EventsDisplay extends LitElement implements Layer { if (!other || !myPlayer.isAlive() || !other.isAlive()) return; this.addEvent({ + createdAt: this.game.ticks(), description: translateText("events_display.alliance_expired", { name: other.name(), }), - type: MessageType.ALLIANCE_EXPIRED, - highlight: true, - createdAt: this.game.ticks(), focusID: otherID, + highlight: true, + type: MessageType.ALLIANCE_EXPIRED, }); } @@ -619,14 +619,14 @@ export class EventsDisplay extends LitElement implements Layer { const target = this.game.playerBySmallID(event.targetID) as PlayerView; this.addEvent({ + createdAt: this.game.ticks(), description: translateText("events_display.attack_request", { name: other.name(), target: target.name(), }), - type: MessageType.ATTACK_REQUEST, - highlight: true, - createdAt: this.game.ticks(), focusID: event.targetID, + highlight: true, + type: MessageType.ATTACK_REQUEST, }); } @@ -674,24 +674,24 @@ export class EventsDisplay extends LitElement implements Layer { if (recipient === myPlayer) { this.addEvent({ - description: `${sender.displayName()}: ${update.emoji.message}`, - unsafeDescription: true, - type: MessageType.CHAT, - highlight: true, createdAt: this.game.ticks(), + description: `${sender.displayName()}: ${update.emoji.message}`, focusID: update.emoji.senderID, + highlight: true, + type: MessageType.CHAT, + unsafeDescription: true, }); } else if (sender === myPlayer && recipient !== AllPlayers) { this.addEvent({ - description: translateText("events_display.sent_emoji", { - name: (recipient as PlayerView).displayName(), - emoji: update.emoji.message, - }), - unsafeDescription: true, - type: MessageType.CHAT, - highlight: true, createdAt: this.game.ticks(), + description: translateText("events_display.sent_emoji", { + emoji: update.emoji.message, + name: (recipient as PlayerView).displayName(), + }), focusID: recipient.smallID(), + highlight: true, + type: MessageType.CHAT, + unsafeDescription: true, }); } } @@ -707,12 +707,12 @@ export class EventsDisplay extends LitElement implements Layer { const unitView = this.game.unit(event.unitID); this.addEvent({ - description: event.message, - type: event.messageType, - unsafeDescription: false, - highlight: true, createdAt: this.game.ticks(), + description: event.message, + highlight: true, + type: event.messageType, unitView, + unsafeDescription: false, }); } @@ -754,6 +754,7 @@ export class EventsDisplay extends LitElement implements Layer { const attacker = this.game?.playerBySmallID(attack.attackerID); return html` ${this.renderButton({ + className: "text-left text-red-400", content: html` ${renderTroops(attack.troops)} ${attacker?.isPlayer() ? attacker.name() : "unknown"} @@ -764,7 +765,6 @@ export class EventsDisplay extends LitElement implements Layer { } `, onClick: () => this.attackWarningOnClick(attack), - className: "text-left text-red-400", translate: false, })} `; @@ -786,22 +786,22 @@ export class EventsDisplay extends LitElement implements Layer { return html`
${this.renderButton({ + className: "text-left text-blue-400", content: html` ${renderTroops(attack.troops)} ${target?.isPlayer() ? target.name() : "unknown"} `, onClick: async () => this.attackWarningOnClick(attack), - className: "text-left text-blue-400", translate: false, })} ${ !attack.retreating ? this.renderButton({ + className: "text-left flex-shrink-0", content: "❌", + disabled: attack.retreating, onClick: () => this.emitCancelAttackIntent(attack.id), - className: "text-left flex-shrink-0", - disabled: attack.retreating, }) : html`(${translateText( @@ -829,19 +829,19 @@ export class EventsDisplay extends LitElement implements Layer { (landAttack) => html`
${this.renderButton({ + className: "text-left text-gray-400", content: html`${renderTroops(landAttack.troops)} ${translateText("help_modal.ui_wilderness")}`, - className: "text-left text-gray-400", translate: false, })} ${ !landAttack.retreating ? this.renderButton({ + className: "text-left flex-shrink-0", content: "❌", + disabled: landAttack.retreating, onClick: () => this.emitCancelAttackIntent(landAttack.id), - className: "text-left flex-shrink-0", - disabled: landAttack.retreating, }) : html`(${translateText( @@ -869,19 +869,19 @@ export class EventsDisplay extends LitElement implements Layer { (boat) => html`
${this.renderButton({ + className: "text-left text-blue-400", content: html`${translateText("events_display.boat")}: ${renderTroops(boat.troops())}`, onClick: () => this.emitGoToUnitEvent(boat), - className: "text-left text-blue-400", translate: false, })} ${ !boat.retreating() ? this.renderButton({ - content: "❌", - onClick: () => this.emitBoatCancelIntent(boat.id()), className: "text-left flex-shrink-0", + content: "❌", disabled: boat.retreating(), + onClick: () => this.emitBoatCancelIntent(boat.id()), }) : html`(${translateText( @@ -948,6 +948,9 @@ export class EventsDisplay extends LitElement implements Layer { ? html`
${this.renderButton({ + className: + "text-white cursor-pointer pointer-events-auto w-fit p-2 " + + "lg:p-3 rounded-md bg-gray-800/70 backdrop-blur", content: html` Events `, onClick: this.toggleHidden, - className: - "text-white cursor-pointer pointer-events-auto w-fit p-2 " + - "lg:p-3 rounded-md bg-gray-800/70 backdrop-blur", })}
` @@ -976,6 +976,7 @@ export class EventsDisplay extends LitElement implements Layer {
${this.renderButton({ + className: "cursor-pointer pointer-events-auto", content: html``, onClick: () => this.toggleEventFilter(MessageCategory.ATTACK), - className: "cursor-pointer pointer-events-auto", })} ${this.renderButton({ + className: "cursor-pointer pointer-events-auto", content: html``, onClick: () => this.toggleEventFilter(MessageCategory.TRADE), - className: "cursor-pointer pointer-events-auto", })} ${this.renderButton({ + className: "cursor-pointer pointer-events-auto", content: html``, onClick: () => this.toggleEventFilter(MessageCategory.ALLIANCE), - className: "cursor-pointer pointer-events-auto", })} ${this.renderButton({ + className: "cursor-pointer pointer-events-auto", content: html``, onClick: () => this.toggleEventFilter(MessageCategory.CHAT), - className: "cursor-pointer pointer-events-auto", })}
@@ -1051,10 +1051,10 @@ export class EventsDisplay extends LitElement implements Layer { : "" } ${this.renderButton({ - content: translateText("leaderboard.hide"), - onClick: this.toggleHidden, className: "text-white cursor-pointer pointer-events-auto", + content: translateText("leaderboard.hide"), + onClick: this.toggleHidden, })}
@@ -1083,6 +1083,7 @@ export class EventsDisplay extends LitElement implements Layer { ${ event.focusID ? this.renderButton({ + className: "text-left", content: this.getEventDescription(event), onClick: () => { event.focusID && @@ -1090,10 +1091,10 @@ export class EventsDisplay extends LitElement implements Layer { event.focusID, ); }, - className: "text-left", }) : event.unitView ? this.renderButton({ + className: "text-left", content: this.getEventDescription(event), onClick: () => { @@ -1102,7 +1103,6 @@ export class EventsDisplay extends LitElement implements Layer { event.unitView, ); }, - className: "text-left", }) : this.getEventDescription(event) } diff --git a/src/client/graphics/layers/GutterAdModal.ts b/src/client/graphics/layers/GutterAdModal.ts index b2447db65..596833a16 100644 --- a/src/client/graphics/layers/GutterAdModal.ts +++ b/src/client/graphics/layers/GutterAdModal.ts @@ -96,12 +96,12 @@ export class GutterAdModal extends LitElement implements Layer { window.ramp.que.push(() => { window.ramp.spaAddAds([ { - type: this.leftAdType, selectorId: this.leftContainerId, + type: this.leftAdType, }, { - type: this.rightAdType, selectorId: this.rightContainerId, + type: this.rightAdType, }, ]); this.adLoaded = true; diff --git a/src/client/graphics/layers/Leaderboard.ts b/src/client/graphics/layers/Leaderboard.ts index 7d388bf48..95737ed61 100644 --- a/src/client/graphics/layers/Leaderboard.ts +++ b/src/client/graphics/layers/Leaderboard.ts @@ -107,15 +107,15 @@ export class Leaderboard extends LitElement implements Layer { troops = 0; } return { + gold: renderNumber(player.gold()), + isMyPlayer: player === myPlayer, name: player.displayName(), + player, position: index + 1, score: formatPercentage( player.numTilesOwned() / numTilesWithoutFallout, ), - gold: renderNumber(player.gold()), troops: renderNumber(troops), - isMyPlayer: player === myPlayer, - player, }; }); @@ -137,15 +137,15 @@ export class Leaderboard extends LitElement implements Layer { } this.players.pop(); this.players.push({ + gold: renderNumber(myPlayer.gold()), + isMyPlayer: true, name: myPlayer.displayName(), + player: myPlayer, position: place, score: formatPercentage( myPlayer.numTilesOwned() / this.game.numLandTiles(), ), - gold: renderNumber(myPlayer.gold()), troops: renderNumber(myPlayerTroops), - isMyPlayer: true, - player: myPlayer, }); } diff --git a/src/client/graphics/layers/MainRadialMenu.ts b/src/client/graphics/layers/MainRadialMenu.ts index 91356b571..0c62ac1c7 100644 --- a/src/client/graphics/layers/MainRadialMenu.ts +++ b/src/client/graphics/layers/MainRadialMenu.ts @@ -114,18 +114,18 @@ export class MainRadialMenu extends LitElement implements Layer { } const params: MenuElementParams = { - myPlayer, - selected: recipient, - tile, - playerActions: actions, - game: this.game, buildMenu: this.buildMenu, - emojiTable: this.emojiTable, - playerActionHandler: this.playerActionHandler, - playerPanel: this.playerPanel, chatIntegration: this.chatIntegration, closeMenu: () => this.closeMenu(), + emojiTable: this.emojiTable, eventBus: this.eventBus, + game: this.game, + myPlayer, + playerActionHandler: this.playerActionHandler, + playerActions: actions, + playerPanel: this.playerPanel, + selected: recipient, + tile, }; this.radialMenu.setParams(params); diff --git a/src/client/graphics/layers/OptionsMenu.ts b/src/client/graphics/layers/OptionsMenu.ts index 1af1edb8f..5f098d5d4 100644 --- a/src/client/graphics/layers/OptionsMenu.ts +++ b/src/client/graphics/layers/OptionsMenu.ts @@ -181,10 +181,10 @@ export class OptionsMenu extends LitElement implements Layer { >
${button({ + children: this.isPaused ? "▶️" : "⏸", classes: !this.showPauseButton ? "hidden" : "", onClick: this.onPauseButtonClick, title: this.isPaused ? "Resume game" : "Pause game", - children: this.isPaused ? "▶️" : "⏸", })}
@@ -212,65 +212,65 @@ export class OptionsMenu extends LitElement implements Layer { ${!this.showSettings ? "hidden" : ""}" > ${button({ + children: "🌲: " + (this.alternateView ? "On" : "Off"), onClick: this.onTerrainButtonClick, title: "Toggle Terrain", - children: "🌲: " + (this.alternateView ? "On" : "Off"), })} ${button({ + children: "🙂: " + (this.userSettings.emojis() ? "On" : "Off"), onClick: this.onToggleEmojisButtonClick, title: "Toggle Emojis", - children: "🙂: " + (this.userSettings.emojis() ? "On" : "Off"), })} ${button({ + children: "🚨: " + (this.userSettings.alertFrame() ? "On" : "Off"), onClick: this.onToggleAlertFrameButtonClick, title: "Toggle Alert frame", - children: "🚨: " + (this.userSettings.alertFrame() ? "On" : "Off"), })} ${button({ + children: "💥: " + (this.userSettings.fxLayer() ? "On" : "Off"), onClick: this.onToggleSpecialEffectsButtonClick, title: "Toggle Special effects", - children: "💥: " + (this.userSettings.fxLayer() ? "On" : "Off"), })} ${button({ - onClick: this.onToggleTerritoryPatterns, - title: "Territory Patterns", children: "🏳️: " + (this.userSettings.territoryPatterns() ? "On" : "Off"), + onClick: this.onToggleTerritoryPatterns, + title: "Territory Patterns", })} ${button({ + children: "🌙: " + (this.userSettings.darkMode() ? "On" : "Off"), onClick: this.onToggleDarkModeButtonClick, title: "Dark Mode", - children: "🌙: " + (this.userSettings.darkMode() ? "On" : "Off"), })} ${button({ - onClick: this.onToggleRandomNameModeButtonClick, - title: "Random name mode", children: "🥷: " + (this.userSettings.anonymousNames() ? "On" : "Off"), + onClick: this.onToggleRandomNameModeButtonClick, + title: "Random name mode", })} ${button({ - onClick: this.onToggleLeftClickOpensMenu, - title: "Left click", children: "🖱️: " + (this.userSettings.leftClickOpensMenu() ? "Opens menu" : "Attack"), + onClick: this.onToggleLeftClickOpensMenu, + title: "Left click", })} ${button({ - onClick: this.onTogglePerformanceOverlayButtonClick, - title: "Performance Overlay", children: "🚀: " + (this.userSettings.performanceOverlay() ? "On" : "Off"), + onClick: this.onTogglePerformanceOverlayButtonClick, + title: "Performance Overlay", })}
diff --git a/src/client/graphics/layers/RadialMenu.ts b/src/client/graphics/layers/RadialMenu.ts index 2b5b027f1..5d7c30505 100644 --- a/src/client/graphics/layers/RadialMenu.ts +++ b/src/client/graphics/layers/RadialMenu.ts @@ -91,17 +91,17 @@ export class RadialMenu implements Layer { config: RadialMenuConfig = {}, ) { this.config = { - menuSize: config.menuSize ?? 190, - submenuScale: config.submenuScale ?? 1.5, + centerButtonIcon: config.centerButtonIcon ?? "", centerButtonSize: config.centerButtonSize ?? 30, - iconSize: config.iconSize ?? 32, centerIconSize: config.centerIconSize ?? 48, disabledColor: config.disabledColor ?? d3.rgb(128, 128, 128).toString(), - menuTransitionDuration: config.menuTransitionDuration ?? 300, - mainMenuInnerRadius: config.mainMenuInnerRadius ?? 40, - centerButtonIcon: config.centerButtonIcon ?? "", - maxNestedLevels: config.maxNestedLevels ?? 3, + iconSize: config.iconSize ?? 32, innerRadiusIncrement: config.innerRadiusIncrement ?? 20, + mainMenuInnerRadius: config.mainMenuInnerRadius ?? 40, + maxNestedLevels: config.maxNestedLevels ?? 3, + menuSize: config.menuSize ?? 190, + menuTransitionDuration: config.menuTransitionDuration ?? 300, + submenuScale: config.submenuScale ?? 1.5, tooltipStyle: config.tooltipStyle ?? "", }; this.originalCenterButtonIcon = this.config.centerButtonIcon; diff --git a/src/client/graphics/layers/RadialMenuElements.ts b/src/client/graphics/layers/RadialMenuElements.ts index 2e6a70fd5..a63da0382 100644 --- a/src/client/graphics/layers/RadialMenuElements.ts +++ b/src/client/graphics/layers/RadialMenuElements.ts @@ -67,32 +67,32 @@ export type CenterButtonElement = { }; export const COLORS = { + ally: "#53ac75", + attack: "#ff0000", + boat: "#3f6ab1", + breakAlly: "#c74848", build: "#ebe250", building: "#2c2c2c", - boat: "#3f6ab1", - ally: "#53ac75", - breakAlly: "#c74848", + chat: { + attack: "#f44336", + default: "#66c", + defend: "#2196f3", + greet: "#ff9800", + help: "#4caf50", + misc: "#9c27b0", + warnings: "#e3c532", + }, delete: "#ff0000", + embargo: "#6600cc", info: "#64748B", - target: "#ff0000", - attack: "#ff0000", infoDetails: "#7f8c8d", infoEmoji: "#f1c40f", - trade: "#008080", - embargo: "#6600cc", + target: "#ff0000", tooltip: { cost: "#ffd700", count: "#aaa", }, - chat: { - default: "#66c", - help: "#4caf50", - attack: "#f44336", - defend: "#2196f3", - greet: "#ff9800", - misc: "#9c27b0", - warnings: "#e3c532", - }, + trade: "#008080", }; export enum Slot { @@ -107,11 +107,11 @@ export enum Slot { /* eslint-disable @typescript-eslint/no-non-null-assertion */ const infoChatElement: MenuElement = { + color: COLORS.chat.default, + disabled: () => false, + icon: chatIcon, id: "info_chat", name: "chat", - disabled: () => false, - color: COLORS.chat.default, - icon: chatIcon, subMenu: (params: MenuElementParams) => params.chatIntegration .createQuickChatMenu(params.selected!) @@ -124,59 +124,51 @@ const infoChatElement: MenuElement = { }; const allyTargetElement: MenuElement = { - id: "ally_target", - name: "target", - disabled: (params: MenuElementParams): boolean => { - if (params.selected === null) return true; - return !params.playerActions.interaction?.canTarget; - }, - color: COLORS.target, - icon: targetIcon, action: (params: MenuElementParams) => { params.playerActionHandler.handleTargetPlayer(params.selected!.id()); params.closeMenu(); }, + color: COLORS.target, + disabled: (params: MenuElementParams): boolean => { + if (params.selected === null) return true; + return !params.playerActions.interaction?.canTarget; + }, + icon: targetIcon, + id: "ally_target", + name: "target", }; const allyTradeElement: MenuElement = { - id: "ally_trade", - name: "trade", - disabled: (params: MenuElementParams) => - !!params.playerActions?.interaction?.canEmbargo, - displayed: (params: MenuElementParams) => - !params.playerActions?.interaction?.canEmbargo, - color: COLORS.trade, - text: translateText("player_panel.start_trade"), action: (params: MenuElementParams) => { params.playerActionHandler.handleEmbargo(params.selected!, "stop"); params.closeMenu(); }, + color: COLORS.trade, + disabled: (params: MenuElementParams) => + !!params.playerActions?.interaction?.canEmbargo, + displayed: (params: MenuElementParams) => + !params.playerActions?.interaction?.canEmbargo, + id: "ally_trade", + name: "trade", + text: translateText("player_panel.start_trade"), }; const allyEmbargoElement: MenuElement = { - id: "ally_embargo", - name: "embargo", - disabled: (params: MenuElementParams) => - !params.playerActions?.interaction?.canEmbargo, - displayed: (params: MenuElementParams) => - !!params.playerActions?.interaction?.canEmbargo, - color: COLORS.embargo, - text: translateText("player_panel.stop_trade"), action: (params: MenuElementParams) => { params.playerActionHandler.handleEmbargo(params.selected!, "start"); params.closeMenu(); }, + color: COLORS.embargo, + disabled: (params: MenuElementParams) => + !params.playerActions?.interaction?.canEmbargo, + displayed: (params: MenuElementParams) => + !!params.playerActions?.interaction?.canEmbargo, + id: "ally_embargo", + name: "embargo", + text: translateText("player_panel.stop_trade"), }; const allyRequestElement: MenuElement = { - id: "ally_request", - name: "request", - disabled: (params: MenuElementParams) => - !params.playerActions?.interaction?.canSendAllianceRequest, - displayed: (params: MenuElementParams) => - !params.playerActions?.interaction?.canBreakAlliance, - color: COLORS.ally, - icon: allianceIcon, action: (params: MenuElementParams) => { params.playerActionHandler.handleAllianceRequest( params.myPlayer, @@ -184,17 +176,17 @@ const allyRequestElement: MenuElement = { ); params.closeMenu(); }, + color: COLORS.ally, + disabled: (params: MenuElementParams) => + !params.playerActions?.interaction?.canSendAllianceRequest, + displayed: (params: MenuElementParams) => + !params.playerActions?.interaction?.canBreakAlliance, + icon: allianceIcon, + id: "ally_request", + name: "request", }; const allyBreakElement: MenuElement = { - id: "ally_break", - name: "break", - disabled: (params: MenuElementParams) => - !params.playerActions?.interaction?.canBreakAlliance, - displayed: (params: MenuElementParams) => - !!params.playerActions?.interaction?.canBreakAlliance, - color: COLORS.breakAlly, - icon: traitorIcon, action: (params: MenuElementParams) => { params.playerActionHandler.handleBreakAlliance( params.myPlayer, @@ -202,59 +194,62 @@ const allyBreakElement: MenuElement = { ); params.closeMenu(); }, + color: COLORS.breakAlly, + disabled: (params: MenuElementParams) => + !params.playerActions?.interaction?.canBreakAlliance, + displayed: (params: MenuElementParams) => + !!params.playerActions?.interaction?.canBreakAlliance, + icon: traitorIcon, + id: "ally_break", + name: "break", }; const allyDonateGoldElement: MenuElement = { - id: "ally_donate_gold", - name: "donate gold", - disabled: (params: MenuElementParams) => - !params.playerActions?.interaction?.canDonateGold, - color: COLORS.ally, - icon: donateGoldIcon, action: (params: MenuElementParams) => { params.playerActionHandler.handleDonateGold(params.selected!); params.closeMenu(); }, + color: COLORS.ally, + disabled: (params: MenuElementParams) => + !params.playerActions?.interaction?.canDonateGold, + icon: donateGoldIcon, + id: "ally_donate_gold", + name: "donate gold", }; const allyDonateTroopsElement: MenuElement = { - id: "ally_donate_troops", - name: "donate troops", - disabled: (params: MenuElementParams) => - !params.playerActions?.interaction?.canDonateTroops, - color: COLORS.ally, - icon: donateTroopIcon, action: (params: MenuElementParams) => { params.playerActionHandler.handleDonateTroops(params.selected!); params.closeMenu(); }, + color: COLORS.ally, + disabled: (params: MenuElementParams) => + !params.playerActions?.interaction?.canDonateTroops, + icon: donateTroopIcon, + id: "ally_donate_troops", + name: "donate troops", }; const infoPlayerElement: MenuElement = { - id: "info_player", - name: "player", - disabled: () => false, - color: COLORS.info, - icon: infoIcon, action: (params: MenuElementParams) => { params.playerPanel.show(params.playerActions, params.tile); }, + color: COLORS.info, + disabled: () => false, + icon: infoIcon, + id: "info_player", + name: "player", }; const infoEmojiElement: MenuElement = { + color: COLORS.infoEmoji, + disabled: () => false, + icon: emojiIcon, id: "info_emoji", name: "emoji", - disabled: () => false, - color: COLORS.infoEmoji, - icon: emojiIcon, subMenu: (params: MenuElementParams) => { const emojiElements: MenuElement[] = [ { - id: "emoji_more", - name: "more", - disabled: () => false, - color: COLORS.infoEmoji, - icon: emojiIcon, action: (params: MenuElementParams) => { params.emojiTable.showTable((emoji) => { const targetPlayer = @@ -268,17 +263,17 @@ const infoEmojiElement: MenuElement = { params.emojiTable.hideTable(); }); }, + color: COLORS.infoEmoji, + disabled: () => false, + icon: emojiIcon, + id: "emoji_more", + name: "more", }, ]; const emojiCount = 8; for (let i = 0; i < emojiCount; i++) { emojiElements.push({ - id: `emoji_${i}`, - name: flattenedEmojiTable[i], - text: flattenedEmojiTable[i], - disabled: () => false, - fontSize: "25px", action: (params: MenuElementParams) => { const targetPlayer = params.selected === params.game.myPlayer() @@ -287,6 +282,11 @@ const infoEmojiElement: MenuElement = { params.playerActionHandler.handleEmoji(targetPlayer!, i); params.closeMenu(); }, + disabled: () => false, + fontSize: "25px", + id: `emoji_${i}`, + name: flattenedEmojiTable[i], + text: flattenedEmojiTable[i], }); } @@ -296,15 +296,15 @@ const infoEmojiElement: MenuElement = { /* eslint-enable @typescript-eslint/no-non-null-assertion */ export const infoMenuElement: MenuElement = { - id: Slot.Info, - name: "info", - disabled: (params: MenuElementParams) => - !params.selected || params.game.inSpawnPhase(), - icon: infoIcon, - color: COLORS.info, action: (params: MenuElementParams) => { params.playerPanel.show(params.playerActions, params.tile); }, + color: COLORS.info, + disabled: (params: MenuElementParams) => + !params.selected || params.game.inSpawnPhase(), + icon: infoIcon, + id: Slot.Info, + name: "info", }; function getAllEnabledUnits(myPlayer: boolean, config: Config): Set { @@ -359,34 +359,6 @@ function createMenuElements( : !ATTACK_UNIT_TYPES.includes(item.unitType)), ) .map((item: BuildItemDisplay) => ({ - id: `${elementIdPrefix}_${item.unitType}`, - name: item.key - ? item.key.replace("unit_type.", "") - : item.unitType.toString(), - disabled: (params: MenuElementParams) => - !params.buildMenu.canBuildOrUpgrade(item), - color: params.buildMenu.canBuildOrUpgrade(item) - ? filterType === "attack" - ? COLORS.attack - : COLORS.building - : undefined, - icon: item.icon, - tooltipItems: [ - { text: translateText(item.key ?? ""), className: "title" }, - { - text: translateText(item.description ?? ""), - className: "description", - }, - { - text: `${renderNumber(params.buildMenu.cost(item))} ${translateText("player_panel.gold")}`, - className: "cost", - }, - item.countable - ? { text: `${params.buildMenu.count(item)}x`, className: "count" } - : null, - ].filter( - (tooltipItem): tooltipItem is TooltipItem => tooltipItem !== null, - ), action: (params: MenuElementParams) => { const buildableUnit = params.playerActions.buildableUnits.find( (bu) => bu.type === item.unitType, @@ -399,15 +371,43 @@ function createMenuElements( } params.closeMenu(); }, + color: params.buildMenu.canBuildOrUpgrade(item) + ? filterType === "attack" + ? COLORS.attack + : COLORS.building + : undefined, + disabled: (params: MenuElementParams) => + !params.buildMenu.canBuildOrUpgrade(item), + icon: item.icon, + id: `${elementIdPrefix}_${item.unitType}`, + name: item.key + ? item.key.replace("unit_type.", "") + : item.unitType.toString(), + tooltipItems: [ + { className: "title", text: translateText(item.key ?? "") }, + { + className: "description", + text: translateText(item.description ?? ""), + }, + { + className: "cost", + text: `${renderNumber(params.buildMenu.cost(item))} ${translateText("player_panel.gold")}`, + }, + item.countable + ? { className: "count", text: `${params.buildMenu.count(item)}x` } + : null, + ].filter( + (tooltipItem): tooltipItem is TooltipItem => tooltipItem !== null, + ), })); } export const attackMenuElement: MenuElement = { - id: Slot.Attack, - name: "radial_attack", + color: COLORS.attack, disabled: (params: MenuElementParams) => params.game.inSpawnPhase(), icon: swordIcon, - color: COLORS.attack, + id: Slot.Attack, + name: "radial_attack", subMenu: (params: MenuElementParams) => { if (params === undefined) return []; @@ -416,8 +416,29 @@ export const attackMenuElement: MenuElement = { }; export const deleteUnitElement: MenuElement = { - id: Slot.Delete, - name: "delete", + action: (params: MenuElementParams) => { + const DELETE_SELECTION_RADIUS = 5; + const myUnits = params.myPlayer + .units() + .filter( + (unit) => + params.game.manhattanDist(unit.tile(), params.tile) <= + DELETE_SELECTION_RADIUS, + ); + + if (myUnits.length > 0) { + myUnits.sort( + (a, b) => + params.game.manhattanDist(a.tile(), params.tile) - + params.game.manhattanDist(b.tile(), params.tile), + ); + + params.playerActionHandler.handleDeleteUnit(myUnits[0].id()); + } + + params.closeMenu(); + }, + color: COLORS.delete, disabled: (params: MenuElementParams) => { const tileOwner = params.game.owner(params.tile); const isLand = params.game.isLand(params.tile); @@ -450,47 +471,26 @@ export const deleteUnitElement: MenuElement = { return myUnits.length === 0; }, icon: xIcon, - color: COLORS.delete, + id: Slot.Delete, + name: "delete", tooltipKeys: [ { - key: "radial_menu.delete_unit_title", className: "title", + key: "radial_menu.delete_unit_title", }, { - key: "radial_menu.delete_unit_description", className: "description", + key: "radial_menu.delete_unit_description", }, ], - action: (params: MenuElementParams) => { - const DELETE_SELECTION_RADIUS = 5; - const myUnits = params.myPlayer - .units() - .filter( - (unit) => - params.game.manhattanDist(unit.tile(), params.tile) <= - DELETE_SELECTION_RADIUS, - ); - - if (myUnits.length > 0) { - myUnits.sort( - (a, b) => - params.game.manhattanDist(a.tile(), params.tile) - - params.game.manhattanDist(b.tile(), params.tile), - ); - - params.playerActionHandler.handleDeleteUnit(myUnits[0].id()); - } - - params.closeMenu(); - }, }; export const buildMenuElement: MenuElement = { - id: Slot.Build, - name: "build", + color: COLORS.build, disabled: (params: MenuElementParams) => params.game.inSpawnPhase(), icon: buildIcon, - color: COLORS.build, + id: Slot.Build, + name: "build", subMenu: (params: MenuElementParams) => { if (params === undefined) return []; @@ -499,15 +499,6 @@ export const buildMenuElement: MenuElement = { }; export const boatMenuElement: MenuElement = { - id: Slot.Boat, - name: "boat", - disabled: (params: MenuElementParams) => - !params.playerActions.buildableUnits.some( - (unit) => unit.type === UnitType.TransportShip && unit.canBuild, - ), - icon: boatIcon, - color: COLORS.boat, - action: async (params: MenuElementParams) => { const spawn = await params.playerActionHandler.findBestTransportShipSpawn( params.myPlayer, @@ -523,9 +514,28 @@ export const boatMenuElement: MenuElement = { params.closeMenu(); }, + color: COLORS.boat, + disabled: (params: MenuElementParams) => + !params.playerActions.buildableUnits.some( + (unit) => unit.type === UnitType.TransportShip && unit.canBuild, + ), + icon: boatIcon, + id: Slot.Boat, + name: "boat", }; export const centerButtonElement: CenterButtonElement = { + action: (params: MenuElementParams) => { + if (params.game.inSpawnPhase()) { + params.playerActionHandler.handleSpawn(params.tile); + } else { + params.playerActionHandler.handleAttack( + params.myPlayer, + params.selected?.id() ?? null, + ); + } + params.closeMenu(); + }, disabled: (params: MenuElementParams): boolean => { const tileOwner = params.game.owner(params.tile); const isLand = params.game.isLand(params.tile); @@ -540,25 +550,14 @@ export const centerButtonElement: CenterButtonElement = { } return !params.playerActions.canAttack; }, - action: (params: MenuElementParams) => { - if (params.game.inSpawnPhase()) { - params.playerActionHandler.handleSpawn(params.tile); - } else { - params.playerActionHandler.handleAttack( - params.myPlayer, - params.selected?.id() ?? null, - ); - } - params.closeMenu(); - }, }; export const rootMenuElement: MenuElement = { - id: "root", - name: "root", + color: COLORS.info, disabled: () => false, icon: infoIcon, - color: COLORS.info, + id: "root", + name: "root", subMenu: (params: MenuElementParams) => { let ally = allyRequestElement; if (params.selected?.isAlliedWith(params.myPlayer)) { diff --git a/src/client/graphics/layers/RailroadLayer.ts b/src/client/graphics/layers/RailroadLayer.ts index 0d4e0afff..e0be4d7d4 100644 --- a/src/client/graphics/layers/RailroadLayer.ts +++ b/src/client/graphics/layers/RailroadLayer.ts @@ -123,9 +123,9 @@ export class RailroadLayer implements Layer { railTile.lastOwnerId = currentOwner; } else { this.existingRailroads.set(railRoad.tile, { - tile: railRoad, - numOccurence: 1, lastOwnerId: currentOwner, + numOccurence: 1, + tile: railRoad, }); this.railTileList.push(railRoad.tile); this.paintRail(railRoad); @@ -156,7 +156,7 @@ export class RailroadLayer implements Layer { const recipient = owner.isPlayer() ? owner : null; const color = recipient ? this.theme.railroadColor(recipient) - : new Colord({ r: 255, g: 255, b: 255, a: 1 }); + : new Colord({ a: 1, b: 255, g: 255, r: 255 }); if (this.context === undefined) throw new Error("Not initialized"); this.context.fillStyle = color.toRgbString(); this.paintRailRects(x, y, railRoad.railType); diff --git a/src/client/graphics/layers/SpawnAd.ts b/src/client/graphics/layers/SpawnAd.ts index 636b4c512..9dd4f32f1 100644 --- a/src/client/graphics/layers/SpawnAd.ts +++ b/src/client/graphics/layers/SpawnAd.ts @@ -79,8 +79,8 @@ export class SpawnAd extends LitElement implements Layer { window.ramp.que.push(() => { window.ramp.spaAddAds([ { - type: AD_TYPE, selectorId: AD_CONTAINER_ID, + type: AD_TYPE, }, ]); this.adLoaded = true; diff --git a/src/client/graphics/layers/StructureIconsLayer.ts b/src/client/graphics/layers/StructureIconsLayer.ts index 5f569496c..cd2a4059d 100644 --- a/src/client/graphics/layers/StructureIconsLayer.ts +++ b/src/client/graphics/layers/StructureIconsLayer.ts @@ -68,20 +68,20 @@ export class StructureIconsLayer implements Layer { UnitType, { visible: boolean; iconPath: string; image: HTMLImageElement | null } > = new Map([ - [UnitType.City, { visible: true, iconPath: cityIcon, image: null }], - [UnitType.Factory, { visible: true, iconPath: factoryIcon, image: null }], + [UnitType.City, { iconPath: cityIcon, image: null, visible: true }], + [UnitType.Factory, { iconPath: factoryIcon, image: null, visible: true }], [ UnitType.DefensePost, - { visible: true, iconPath: shieldIcon, image: null }, + { iconPath: shieldIcon, image: null, visible: true }, ], - [UnitType.Port, { visible: true, iconPath: anchorIcon, image: null }], + [UnitType.Port, { iconPath: anchorIcon, image: null, visible: true }], [ UnitType.MissileSilo, - { visible: true, iconPath: missileSiloIcon, image: null }, + { iconPath: missileSiloIcon, image: null, visible: true }, ], [ UnitType.SAMLauncher, - { visible: true, iconPath: SAMMissileIcon, image: null }, + { iconPath: SAMMissileIcon, image: null, visible: true }, ], ]); private renderSprites = true; @@ -119,14 +119,14 @@ export class StructureIconsLayer implements Layer { this.dotsStage.setSize(this.pixicanvas.width, this.pixicanvas.height); await this.renderer.init({ - canvas: this.pixicanvas, - resolution: 1, - width: this.pixicanvas.width, - height: this.pixicanvas.height, antialias: false, - clearBeforeRender: true, backgroundAlpha: 0, backgroundColor: 0x00000000, + canvas: this.pixicanvas, + clearBeforeRender: true, + height: this.pixicanvas.height, + resolution: 1, + width: this.pixicanvas.width, }); } @@ -249,10 +249,10 @@ export class StructureIconsLayer implements Layer { render.dotContainer.alpha = structureInfos.visible ? 1 : 0.3; if (structureInfos.visible && focusStructure) { render.iconContainer.filters = [ - new OutlineFilter({ thickness: 2, color: "rgb(255, 255, 255)" }), + new OutlineFilter({ color: "rgb(255, 255, 255)", thickness: 2 }), ]; render.dotContainer.filters = [ - new OutlineFilter({ thickness: 2, color: "rgb(255, 255, 255)" }), + new OutlineFilter({ color: "rgb(255, 255, 255)", thickness: 2 }), ]; } else { render.iconContainer.filters = []; @@ -490,11 +490,11 @@ export class StructureIconsLayer implements Layer { if (renderIcon) { const SHAPE_OFFSETS = { - triangle: [6, 11], - square: [5, 5], + circle: [6, 6], octagon: [6, 6], pentagon: [7, 7], - circle: [6, 6], + square: [5, 5], + triangle: [6, 11], }; const [offsetX, offsetY] = SHAPE_OFFSETS[shape] || [0, 0]; context.drawImage( @@ -509,24 +509,24 @@ export class StructureIconsLayer implements Layer { private createLevelSprite(unit: UnitView): PIXI.Container { if (this.levelsStage === undefined) throw new Error("Not initialized"); return this.createUnitContainer(unit, { - type: "level", stage: this.levelsStage, + type: "level", }); } private createDotSprite(unit: UnitView): PIXI.Container { if (this.dotsStage === undefined) throw new Error("Not initialized"); return this.createUnitContainer(unit, { - type: "dot", stage: this.dotsStage, + type: "dot", }); } private createIconSprite(unit: UnitView): PIXI.Container { if (this.iconsStage === undefined) throw new Error("Not initialized"); return this.createUnitContainer(unit, { - type: "icon", stage: this.iconsStage, + type: "icon", }); } @@ -557,11 +557,11 @@ export class StructureIconsLayer implements Layer { // Add level text if needed if ((type === "icon" || type === "level") && unit.level() > 1) { const text = new PIXI.BitmapText({ - text: unit.level().toString(), style: { fontFamily: "round_6x6_modified", fontSize: 14, }, + text: unit.level().toString(), }); text.anchor.set(0.5); diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts index f32a74b78..02a69b6df 100644 --- a/src/client/graphics/layers/StructureLayer.ts +++ b/src/client/graphics/layers/StructureLayer.ts @@ -14,7 +14,7 @@ import { GameView, UnitView } from "../../../core/game/GameView"; import { TransformHandler } from "../TransformHandler"; import { Layer } from "./Layer"; -const underConstructionColor = colord({ r: 150, g: 150, b: 150 }); +const underConstructionColor = colord({ b: 150, g: 150, r: 150 }); // Base radius values and scaling factor for unit borders and territories const BASE_BORDER_RADIUS = 16.5; @@ -39,33 +39,33 @@ export class StructureLayer implements Layer { // Configuration for supported unit types only private readonly unitConfigs: Partial> = { [UnitType.Port]: { - icon: anchorIcon, borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + icon: anchorIcon, territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, }, [UnitType.City]: { - icon: cityIcon, borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + icon: cityIcon, territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, }, [UnitType.Factory]: { - icon: factoryIcon, borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + icon: factoryIcon, territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, }, [UnitType.MissileSilo]: { - icon: missileSiloIcon, borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + icon: missileSiloIcon, territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, }, [UnitType.DefensePost]: { - icon: shieldIcon, borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + icon: shieldIcon, territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, }, [UnitType.SAMLauncher]: { - icon: SAMMissileIcon, borderRadius: BASE_BORDER_RADIUS * RADIUS_SCALE_FACTOR, + icon: SAMMissileIcon, territoryRadius: BASE_TERRITORY_RADIUS * RADIUS_SCALE_FACTOR, }, }; diff --git a/src/client/graphics/layers/TeamStats.ts b/src/client/graphics/layers/TeamStats.ts index fbbe8f7c1..7f2f223f5 100644 --- a/src/client/graphics/layers/TeamStats.ts +++ b/src/client/graphics/layers/TeamStats.ts @@ -89,17 +89,17 @@ export class TeamStats extends LitElement implements Layer { const totalScorePercent = totalScoreSort / this.game.numLandTiles(); return { - teamName: teamStr, - totalScoreStr: formatPercentage(totalScorePercent), - totalScoreSort, - totalGold: renderNumber(totalGold), - totalTroops: renderNumber(totalTroops / 10), players: teamPlayers, + teamName: teamStr, + totalCities: renderNumber(totalCities), + totalGold: renderNumber(totalGold), totalLaunchers: renderNumber(totalLaunchers), totalSAMs: renderNumber(totalSAMs), + totalScoreSort, + totalScoreStr: formatPercentage(totalScorePercent), + totalTroops: renderNumber(totalTroops / 10), totalWarShips: renderNumber(totalWarShips), - totalCities: renderNumber(totalCities), }; }) .sort((a, b) => b.totalScoreSort - a.totalScoreSort); diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts index fb25c6b0b..508fc8c61 100644 --- a/src/client/graphics/layers/TerritoryLayer.ts +++ b/src/client/graphics/layers/TerritoryLayer.ts @@ -544,8 +544,8 @@ export class TerritoryLayer implements Layer { enqueueTile(tile: TileRef) { this.tileToRenderQueue.push({ - tile, lastUpdate: this.game.ticks() + this.random.nextFloat(0, 0.5), + tile, }); } diff --git a/src/client/graphics/layers/UILayer.ts b/src/client/graphics/layers/UILayer.ts index d345d40b8..9215302da 100644 --- a/src/client/graphics/layers/UILayer.ts +++ b/src/client/graphics/layers/UILayer.ts @@ -252,9 +252,9 @@ export class UILayer implements Layer { // Store current selection box position for next cleanup this.lastSelectionBoxCenter = { + size: selectionSize, x: centerX, y: centerY, - size: selectionSize, }; } @@ -349,8 +349,8 @@ export class UILayer implements Layer { 0, ); this.allProgressBars.set(unit.id(), { - unit, progressBar, + unit, }); } } diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index 6ffb4625e..0b1a6f253 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -300,7 +300,7 @@ export class UnitLayer implements Layer { private handleWarShipEvent(unit: UnitView) { if (unit.targetUnitId()) { - this.drawSprite(unit, colord({ r: 200, b: 0, g: 0 })); + this.drawSprite(unit, colord({ b: 0, g: 0, r: 200 })); } else { this.drawSprite(unit); } diff --git a/src/client/jwt.ts b/src/client/jwt.ts index 8b365adf6..019aa4791 100644 --- a/src/client/jwt.ts +++ b/src/client/jwt.ts @@ -85,10 +85,10 @@ export async function logOut(allSessions = false) { const response = await fetch( getApiBase() + (allSessions ? "/revoke" : "/logout"), { - method: "POST", headers: { authorization: `Bearer ${token}`, }, + method: "POST", }, ); @@ -179,7 +179,7 @@ function _isLoggedIn(): IsLoggedInResponse { } const claims = result.data; - return { token, claims }; + return { claims, token }; } catch (e) { console.log(e); return false; @@ -193,10 +193,10 @@ export async function postRefresh(): Promise { // Refresh the JWT const response = await fetch(getApiBase() + "/refresh", { - method: "POST", headers: { authorization: `Bearer ${token}`, }, + method: "POST", }); if (response.status === 401) { clearToken(); diff --git a/src/client/utilities/RenderUnitTypeOptions.ts b/src/client/utilities/RenderUnitTypeOptions.ts index 71558c018..d777b4f0c 100644 --- a/src/client/utilities/RenderUnitTypeOptions.ts +++ b/src/client/utilities/RenderUnitTypeOptions.ts @@ -9,16 +9,16 @@ export type UnitTypeRenderContext = { }; const unitOptions: { type: UnitType; translationKey: string }[] = [ - { type: UnitType.City, translationKey: "unit_type.city" }, - { type: UnitType.DefensePost, translationKey: "unit_type.defense_post" }, - { type: UnitType.Port, translationKey: "unit_type.port" }, - { type: UnitType.Warship, translationKey: "unit_type.warship" }, - { type: UnitType.MissileSilo, translationKey: "unit_type.missile_silo" }, - { type: UnitType.SAMLauncher, translationKey: "unit_type.sam_launcher" }, - { type: UnitType.AtomBomb, translationKey: "unit_type.atom_bomb" }, - { type: UnitType.HydrogenBomb, translationKey: "unit_type.hydrogen_bomb" }, - { type: UnitType.MIRV, translationKey: "unit_type.mirv" }, - { type: UnitType.Factory, translationKey: "unit_type.factory" }, + { translationKey: "unit_type.city", type: UnitType.City }, + { translationKey: "unit_type.defense_post", type: UnitType.DefensePost }, + { translationKey: "unit_type.port", type: UnitType.Port }, + { translationKey: "unit_type.warship", type: UnitType.Warship }, + { translationKey: "unit_type.missile_silo", type: UnitType.MissileSilo }, + { translationKey: "unit_type.sam_launcher", type: UnitType.SAMLauncher }, + { translationKey: "unit_type.atom_bomb", type: UnitType.AtomBomb }, + { translationKey: "unit_type.hydrogen_bomb", type: UnitType.HydrogenBomb }, + { translationKey: "unit_type.mirv", type: UnitType.MIRV }, + { translationKey: "unit_type.factory", type: UnitType.Factory }, ]; export function renderUnitTypeOptions({ diff --git a/src/core/ApiSchemas.ts b/src/core/ApiSchemas.ts index 208557e3d..4ab8089fe 100644 --- a/src/core/ApiSchemas.ts +++ b/src/core/ApiSchemas.ts @@ -8,8 +8,11 @@ export const RefreshResponseSchema = z.object({ }); export type RefreshResponse = z.infer; -/* eslint-disable sort-keys */ export const TokenPayloadSchema = z.object({ + aud: z.string(), + exp: z.number(), + iat: z.number(), + iss: z.string(), jti: z.string(), sub: z .string() @@ -27,41 +30,37 @@ export const TokenPayloadSchema = z.object({ if (!uuid) throw new Error("Invalid base64 UUID"); return uuid; }), - iat: z.number(), - iss: z.string(), - aud: z.string(), - exp: z.number(), }); export type TokenPayload = z.infer; export const UserMeResponseSchema = z.object({ - user: z.object({ - id: z.string(), - avatar: z.string().nullable(), - username: z.string(), - global_name: z.string().nullable(), - discriminator: z.string(), - locale: z.string().optional(), - }), player: z.object({ + flares: z.string().array().optional(), publicId: z.string(), roles: z.string().array().optional(), - flares: z.string().array().optional(), + }), + user: z.object({ + avatar: z.string().nullable(), + discriminator: z.string(), + global_name: z.string().nullable(), + id: z.string(), + locale: z.string().optional(), + username: z.string(), }), }); export type UserMeResponse = z.infer; export const StripeCreateCheckoutSessionResponseSchema = z.object({ - id: z.string(), - object: z.literal("checkout.session"), - url: z.string(), - payment_status: z.enum(["paid", "unpaid", "no_payment_required"]), - status: z.enum(["open", "complete", "expired"]), client_reference_id: z.string().optional(), customer: z.string().optional(), - payment_intent: z.string().optional(), - subscription: z.string().optional(), + id: z.string(), metadata: z.partialRecord(z.string(), z.string()), + object: z.literal("checkout.session"), + payment_intent: z.string().optional(), + payment_status: z.enum(["paid", "unpaid", "no_payment_required"]), + status: z.enum(["open", "complete", "expired"]), + subscription: z.string().optional(), + url: z.string(), }); export type StripeCreateCheckoutSessionResponse = z.infer< typeof StripeCreateCheckoutSessionResponseSchema diff --git a/src/core/CosmeticSchemas.ts b/src/core/CosmeticSchemas.ts index af3469fe1..35ef1ce13 100644 --- a/src/core/CosmeticSchemas.ts +++ b/src/core/CosmeticSchemas.ts @@ -2,11 +2,10 @@ import { z } from "zod"; import { RequiredPatternSchema } from "./Schemas"; export const ProductSchema = z.object({ - productId: z.string(), - /* eslint-disable sort-keys */ - priceId: z.string(), price: z.string(), - /* eslint-enable sort-keys */ + + priceId: z.string(), + productId: z.string(), }); const PatternSchema = z.object({ @@ -17,28 +16,26 @@ const PatternSchema = z.object({ // Schema for resources/cosmetics/cosmetics.json export const CosmeticsSchema = z.object({ - patterns: z.record(z.string(), PatternSchema), - /* eslint-disable sort-keys */ flag: z .object({ - layers: z.record( - z.string(), - z.object({ - name: z.string(), - flares: z.string().array().optional(), - }), - ), color: z.record( z.string(), z.object({ color: z.string(), - name: z.string(), flares: z.string().array().optional(), + name: z.string(), + }), + ), + layers: z.record( + z.string(), + z.object({ + flares: z.string().array().optional(), + name: z.string(), }), ), }) .optional(), - /* eslint-enable sort-keys */ + patterns: z.record(z.string(), PatternSchema), }); export type Cosmetics = z.infer; export type Pattern = z.infer; diff --git a/src/core/CustomFlag.ts b/src/core/CustomFlag.ts index 368e85cdf..4df27b1fe 100644 --- a/src/core/CustomFlag.ts +++ b/src/core/CustomFlag.ts @@ -28,8 +28,8 @@ export function renderPlayerFlag( const code = flag.slice("!".length); const layers = code.split("_").map((segment) => { const [layerKey, colorKey] = segment.split("-"); - // eslint-disable-next-line sort-keys - return { layerKey, colorKey }; + + return { colorKey, layerKey }; }); target.innerHTML = ""; diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index 2c58a95b4..46bf7c4eb 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -138,8 +138,8 @@ export type TeamCountConfig = z.infer; export const GameConfigSchema = z.object({ bots: z.number().int().min(0).max(400), difficulty: z.enum(Difficulty), - disableNPCs: z.boolean(), disabledUnits: z.enum(UnitType).array().optional(), + disableNPCs: z.boolean(), donateGold: z.boolean(), donateTroops: z.boolean(), gameMap: z.enum(GameMapType), diff --git a/src/core/Util.ts b/src/core/Util.ts index 162e5835e..3f3ab14c0 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -89,8 +89,7 @@ export function calculateBoundingBox( maxY = Math.max(maxY, cell.y); }); - // eslint-disable-next-line sort-keys - return { min: new Cell(minX, minY), max: new Cell(maxX, maxY) }; + return { max: new Cell(maxX, maxY), min: new Cell(minX, minY) }; } export function calculateBoundingBoxCenter( diff --git a/src/core/configuration/Colors.ts b/src/core/configuration/Colors.ts index afee46dc4..2bfa66bac 100644 --- a/src/core/configuration/Colors.ts +++ b/src/core/configuration/Colors.ts @@ -5,15 +5,14 @@ import lchPlugin from "colord/plugins/lch"; extend([lchPlugin]); extend([labPlugin]); -/* eslint-disable sort-keys */ -export const red = colord({ h: 0, s: 82, l: 56 }); -export const blue = colord({ h: 224, s: 100, l: 58 }); -export const teal = colord({ h: 172, s: 66, l: 50 }); -export const purple = colord({ h: 271, s: 81, l: 56 }); -export const yellow = colord({ h: 45, s: 93, l: 47 }); -export const orange = colord({ h: 25, s: 95, l: 53 }); -export const green = colord({ h: 128, s: 49, l: 50 }); -export const botColor = colord({ h: 36, s: 10, l: 80 }); +export const red = colord({ h: 0, l: 56, s: 82 }); +export const blue = colord({ h: 224, l: 58, s: 100 }); +export const teal = colord({ h: 172, l: 50, s: 66 }); +export const purple = colord({ h: 271, l: 56, s: 81 }); +export const yellow = colord({ h: 45, l: 47, s: 93 }); +export const orange = colord({ h: 25, l: 53, s: 95 }); +export const green = colord({ h: 128, l: 50, s: 49 }); +export const botColor = colord({ h: 36, l: 80, s: 10 }); export const redTeamColors: Colord[] = generateTeamColors(red); export const blueTeamColors: Colord[] = generateTeamColors(blue); @@ -36,331 +35,331 @@ function generateTeamColors(baseColor: Colord): Colord[] { return colord({ h: baseHue, - s: saturation, l: lightness, + s: saturation, }); }); } export const nationColors: Colord[] = [ - colord({ r: 230, g: 100, b: 100 }), // Bright Red - colord({ r: 100, g: 180, b: 230 }), // Sky Blue - colord({ r: 230, g: 180, b: 80 }), // Golden Yellow - colord({ r: 180, g: 100, b: 230 }), // Purple - colord({ r: 80, g: 200, b: 120 }), // Emerald Green - colord({ r: 230, g: 130, b: 180 }), // Pink - colord({ r: 100, g: 160, b: 80 }), // Olive Green - colord({ r: 230, g: 150, b: 100 }), // Peach - colord({ r: 80, g: 130, b: 190 }), // Navy Blue - colord({ r: 210, g: 210, b: 100 }), // Lime Yellow - colord({ r: 190, g: 100, b: 130 }), // Maroon - colord({ r: 100, g: 210, b: 210 }), // Turquoise - colord({ r: 210, g: 140, b: 80 }), // Light Orange - colord({ r: 150, g: 110, b: 190 }), // Lavender - colord({ r: 180, g: 210, b: 120 }), // Light Green - colord({ r: 210, g: 100, b: 160 }), // Hot Pink - colord({ r: 100, g: 140, b: 110 }), // Sea Green - colord({ r: 230, g: 180, b: 180 }), // Light Pink - colord({ r: 120, g: 120, b: 190 }), // Periwinkle - colord({ r: 190, g: 170, b: 100 }), // Sand - colord({ r: 100, g: 180, b: 160 }), // Aquamarine - colord({ r: 210, g: 160, b: 200 }), // Orchid - colord({ r: 170, g: 190, b: 100 }), // Yellow Green - colord({ r: 100, g: 130, b: 150 }), // Steel Blue - colord({ r: 230, g: 140, b: 140 }), // Salmon - colord({ r: 140, g: 180, b: 220 }), // Light Blue - colord({ r: 200, g: 160, b: 110 }), // Tan - colord({ r: 180, g: 130, b: 180 }), // Plum - colord({ r: 130, g: 200, b: 130 }), // Light Sea Green - colord({ r: 220, g: 120, b: 120 }), // Coral - colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue - colord({ r: 200, g: 200, b: 140 }), // Khaki - colord({ r: 160, g: 120, b: 160 }), // Purple Gray - colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green - colord({ r: 200, g: 130, b: 110 }), // Dark Salmon - colord({ r: 130, g: 170, b: 190 }), // Cadet Blue - colord({ r: 190, g: 180, b: 160 }), // Tan Gray - colord({ r: 170, g: 140, b: 190 }), // Medium Purple - colord({ r: 160, g: 190, b: 160 }), // Pale Green - colord({ r: 190, g: 150, b: 130 }), // Rosy Brown - colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray - colord({ r: 180, g: 170, b: 140 }), // Dark Khaki - colord({ r: 150, g: 130, b: 150 }), // Thistle - colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green - colord({ r: 190, g: 140, b: 150 }), // Puce - colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine - colord({ r: 180, g: 160, b: 180 }), // Mauve - colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green - colord({ r: 170, g: 150, b: 170 }), // Dusty Rose - colord({ r: 100, g: 180, b: 230 }), // Sky Blue - colord({ r: 230, g: 180, b: 80 }), // Golden Yellow - colord({ r: 180, g: 100, b: 230 }), // Purple - colord({ r: 80, g: 200, b: 120 }), // Emerald Green - colord({ r: 230, g: 130, b: 180 }), // Pink - colord({ r: 100, g: 160, b: 80 }), // Olive Green - colord({ r: 230, g: 150, b: 100 }), // Peach - colord({ r: 80, g: 130, b: 190 }), // Navy Blue - colord({ r: 210, g: 210, b: 100 }), // Lime Yellow - colord({ r: 190, g: 100, b: 130 }), // Maroon - colord({ r: 100, g: 210, b: 210 }), // Turquoise - colord({ r: 210, g: 140, b: 80 }), // Light Orange - colord({ r: 150, g: 110, b: 190 }), // Lavender - colord({ r: 180, g: 210, b: 120 }), // Light Green - colord({ r: 210, g: 100, b: 160 }), // Hot Pink - colord({ r: 100, g: 140, b: 110 }), // Sea Green - colord({ r: 230, g: 180, b: 180 }), // Light Pink - colord({ r: 120, g: 120, b: 190 }), // Periwinkle - colord({ r: 190, g: 170, b: 100 }), // Sand - colord({ r: 100, g: 180, b: 160 }), // Aquamarine - colord({ r: 210, g: 160, b: 200 }), // Orchid - colord({ r: 170, g: 190, b: 100 }), // Yellow Green - colord({ r: 100, g: 130, b: 150 }), // Steel Blue - colord({ r: 230, g: 140, b: 140 }), // Salmon - colord({ r: 140, g: 180, b: 220 }), // Light Blue - colord({ r: 200, g: 160, b: 110 }), // Tan - colord({ r: 180, g: 130, b: 180 }), // Plum - colord({ r: 130, g: 200, b: 130 }), // Light Sea Green - colord({ r: 220, g: 120, b: 120 }), // Coral - colord({ r: 120, g: 160, b: 200 }), // Cornflower Blue - colord({ r: 200, g: 200, b: 140 }), // Khaki - colord({ r: 160, g: 120, b: 160 }), // Purple Gray - colord({ r: 140, g: 180, b: 140 }), // Dark Sea Green - colord({ r: 200, g: 130, b: 110 }), // Dark Salmon - colord({ r: 130, g: 170, b: 190 }), // Cadet Blue - colord({ r: 190, g: 180, b: 160 }), // Tan Gray - colord({ r: 170, g: 140, b: 190 }), // Medium Purple - colord({ r: 160, g: 190, b: 160 }), // Pale Green - colord({ r: 190, g: 150, b: 130 }), // Rosy Brown - colord({ r: 140, g: 150, b: 180 }), // Light Slate Gray - colord({ r: 180, g: 170, b: 140 }), // Dark Khaki - colord({ r: 150, g: 130, b: 150 }), // Thistle - colord({ r: 170, g: 190, b: 180 }), // Pale Blue Green - colord({ r: 190, g: 140, b: 150 }), // Puce - colord({ r: 130, g: 180, b: 170 }), // Medium Aquamarine - colord({ r: 180, g: 160, b: 180 }), // Mauve - colord({ r: 160, g: 180, b: 140 }), // Dark Olive Green - colord({ r: 170, g: 150, b: 170 }), // Dusty Rose + colord({ b: 100, g: 100, r: 230 }), // Bright Red + colord({ b: 230, g: 180, r: 100 }), // Sky Blue + colord({ b: 80, g: 180, r: 230 }), // Golden Yellow + colord({ b: 230, g: 100, r: 180 }), // Purple + colord({ b: 120, g: 200, r: 80 }), // Emerald Green + colord({ b: 180, g: 130, r: 230 }), // Pink + colord({ b: 80, g: 160, r: 100 }), // Olive Green + colord({ b: 100, g: 150, r: 230 }), // Peach + colord({ b: 190, g: 130, r: 80 }), // Navy Blue + colord({ b: 100, g: 210, r: 210 }), // Lime Yellow + colord({ b: 130, g: 100, r: 190 }), // Maroon + colord({ b: 210, g: 210, r: 100 }), // Turquoise + colord({ b: 80, g: 140, r: 210 }), // Light Orange + colord({ b: 190, g: 110, r: 150 }), // Lavender + colord({ b: 120, g: 210, r: 180 }), // Light Green + colord({ b: 160, g: 100, r: 210 }), // Hot Pink + colord({ b: 110, g: 140, r: 100 }), // Sea Green + colord({ b: 180, g: 180, r: 230 }), // Light Pink + colord({ b: 190, g: 120, r: 120 }), // Periwinkle + colord({ b: 100, g: 170, r: 190 }), // Sand + colord({ b: 160, g: 180, r: 100 }), // Aquamarine + colord({ b: 200, g: 160, r: 210 }), // Orchid + colord({ b: 100, g: 190, r: 170 }), // Yellow Green + colord({ b: 150, g: 130, r: 100 }), // Steel Blue + colord({ b: 140, g: 140, r: 230 }), // Salmon + colord({ b: 220, g: 180, r: 140 }), // Light Blue + colord({ b: 110, g: 160, r: 200 }), // Tan + colord({ b: 180, g: 130, r: 180 }), // Plum + colord({ b: 130, g: 200, r: 130 }), // Light Sea Green + colord({ b: 120, g: 120, r: 220 }), // Coral + colord({ b: 200, g: 160, r: 120 }), // Cornflower Blue + colord({ b: 140, g: 200, r: 200 }), // Khaki + colord({ b: 160, g: 120, r: 160 }), // Purple Gray + colord({ b: 140, g: 180, r: 140 }), // Dark Sea Green + colord({ b: 110, g: 130, r: 200 }), // Dark Salmon + colord({ b: 190, g: 170, r: 130 }), // Cadet Blue + colord({ b: 160, g: 180, r: 190 }), // Tan Gray + colord({ b: 190, g: 140, r: 170 }), // Medium Purple + colord({ b: 160, g: 190, r: 160 }), // Pale Green + colord({ b: 130, g: 150, r: 190 }), // Rosy Brown + colord({ b: 180, g: 150, r: 140 }), // Light Slate Gray + colord({ b: 140, g: 170, r: 180 }), // Dark Khaki + colord({ b: 150, g: 130, r: 150 }), // Thistle + colord({ b: 180, g: 190, r: 170 }), // Pale Blue Green + colord({ b: 150, g: 140, r: 190 }), // Puce + colord({ b: 170, g: 180, r: 130 }), // Medium Aquamarine + colord({ b: 180, g: 160, r: 180 }), // Mauve + colord({ b: 140, g: 180, r: 160 }), // Dark Olive Green + colord({ b: 170, g: 150, r: 170 }), // Dusty Rose + colord({ b: 230, g: 180, r: 100 }), // Sky Blue + colord({ b: 80, g: 180, r: 230 }), // Golden Yellow + colord({ b: 230, g: 100, r: 180 }), // Purple + colord({ b: 120, g: 200, r: 80 }), // Emerald Green + colord({ b: 180, g: 130, r: 230 }), // Pink + colord({ b: 80, g: 160, r: 100 }), // Olive Green + colord({ b: 100, g: 150, r: 230 }), // Peach + colord({ b: 190, g: 130, r: 80 }), // Navy Blue + colord({ b: 100, g: 210, r: 210 }), // Lime Yellow + colord({ b: 130, g: 100, r: 190 }), // Maroon + colord({ b: 210, g: 210, r: 100 }), // Turquoise + colord({ b: 80, g: 140, r: 210 }), // Light Orange + colord({ b: 190, g: 110, r: 150 }), // Lavender + colord({ b: 120, g: 210, r: 180 }), // Light Green + colord({ b: 160, g: 100, r: 210 }), // Hot Pink + colord({ b: 110, g: 140, r: 100 }), // Sea Green + colord({ b: 180, g: 180, r: 230 }), // Light Pink + colord({ b: 190, g: 120, r: 120 }), // Periwinkle + colord({ b: 100, g: 170, r: 190 }), // Sand + colord({ b: 160, g: 180, r: 100 }), // Aquamarine + colord({ b: 200, g: 160, r: 210 }), // Orchid + colord({ b: 100, g: 190, r: 170 }), // Yellow Green + colord({ b: 150, g: 130, r: 100 }), // Steel Blue + colord({ b: 140, g: 140, r: 230 }), // Salmon + colord({ b: 220, g: 180, r: 140 }), // Light Blue + colord({ b: 110, g: 160, r: 200 }), // Tan + colord({ b: 180, g: 130, r: 180 }), // Plum + colord({ b: 130, g: 200, r: 130 }), // Light Sea Green + colord({ b: 120, g: 120, r: 220 }), // Coral + colord({ b: 200, g: 160, r: 120 }), // Cornflower Blue + colord({ b: 140, g: 200, r: 200 }), // Khaki + colord({ b: 160, g: 120, r: 160 }), // Purple Gray + colord({ b: 140, g: 180, r: 140 }), // Dark Sea Green + colord({ b: 110, g: 130, r: 200 }), // Dark Salmon + colord({ b: 190, g: 170, r: 130 }), // Cadet Blue + colord({ b: 160, g: 180, r: 190 }), // Tan Gray + colord({ b: 190, g: 140, r: 170 }), // Medium Purple + colord({ b: 160, g: 190, r: 160 }), // Pale Green + colord({ b: 130, g: 150, r: 190 }), // Rosy Brown + colord({ b: 180, g: 150, r: 140 }), // Light Slate Gray + colord({ b: 140, g: 170, r: 180 }), // Dark Khaki + colord({ b: 150, g: 130, r: 150 }), // Thistle + colord({ b: 180, g: 190, r: 170 }), // Pale Blue Green + colord({ b: 150, g: 140, r: 190 }), // Puce + colord({ b: 170, g: 180, r: 130 }), // Medium Aquamarine + colord({ b: 180, g: 160, r: 180 }), // Mauve + colord({ b: 140, g: 180, r: 160 }), // Dark Olive Green + colord({ b: 170, g: 150, r: 170 }), // Dusty Rose ]; // Bright pastel theme with 64 colors export const humanColors: Colord[] = [ - colord({ r: 16, g: 185, b: 129 }), // Sea Green - colord({ r: 34, g: 197, b: 94 }), // Emerald - colord({ r: 45, g: 212, b: 191 }), // Turquoise - colord({ r: 48, g: 178, b: 180 }), // Teal - colord({ r: 52, g: 211, b: 153 }), // Spearmint - colord({ r: 56, g: 189, b: 248 }), // Light Blue - colord({ r: 59, g: 130, b: 246 }), // Royal Blue - colord({ r: 67, g: 190, b: 84 }), // Fresh Green - colord({ r: 74, g: 222, b: 128 }), // Mint - colord({ r: 79, g: 70, b: 229 }), // Indigo - colord({ r: 82, g: 183, b: 136 }), // Jade - colord({ r: 96, g: 165, b: 250 }), // Sky Blue - colord({ r: 99, g: 202, b: 253 }), // Azure - colord({ r: 110, g: 231, b: 183 }), // Seafoam - colord({ r: 124, g: 58, b: 237 }), // Royal Purple - colord({ r: 125, g: 211, b: 252 }), // Crystal Blue - colord({ r: 132, g: 204, b: 22 }), // Lime - colord({ r: 133, g: 77, b: 14 }), // Chocolate - colord({ r: 134, g: 239, b: 172 }), // Light Green - colord({ r: 147, g: 51, b: 234 }), // Bright Purple - colord({ r: 147, g: 197, b: 253 }), // Powder Blue - colord({ r: 151, g: 255, b: 187 }), // Fresh Mint - colord({ r: 163, g: 230, b: 53 }), // Yellow Green - colord({ r: 167, g: 139, b: 250 }), // Periwinkle - colord({ r: 168, g: 85, b: 247 }), // Vibrant Purple - colord({ r: 179, g: 136, b: 255 }), // Light Purple - colord({ r: 186, g: 255, b: 201 }), // Pale Emerald - colord({ r: 190, g: 92, b: 251 }), // Amethyst - colord({ r: 192, g: 132, b: 252 }), // Lavender - colord({ r: 202, g: 138, b: 4 }), // Rich Gold - colord({ r: 202, g: 225, b: 255 }), // Baby Blue - colord({ r: 204, g: 204, b: 255 }), // Soft Lavender Blue - colord({ r: 217, g: 70, b: 239 }), // Fuchsia - colord({ r: 220, g: 38, b: 38 }), // Ruby - colord({ r: 220, g: 220, b: 255 }), // Meringue Blue - colord({ r: 220, g: 240, b: 250 }), // Ice Blue - colord({ r: 230, g: 250, b: 210 }), // Pastel Lime - colord({ r: 230, g: 255, b: 250 }), // Mint Whisper - colord({ r: 233, g: 213, b: 255 }), // Light Lilac - colord({ r: 234, g: 88, b: 12 }), // Burnt Orange - colord({ r: 234, g: 179, b: 8 }), // Sunflower - colord({ r: 235, g: 75, b: 75 }), // Bright Red - colord({ r: 236, g: 72, b: 153 }), // Deep Pink - colord({ r: 239, g: 68, b: 68 }), // Crimson - colord({ r: 240, g: 171, b: 252 }), // Orchid - colord({ r: 240, g: 240, b: 200 }), // Light Khaki - colord({ r: 244, g: 114, b: 182 }), // Rose - colord({ r: 245, g: 101, b: 101 }), // Coral - colord({ r: 245, g: 158, b: 11 }), // Amber - colord({ r: 248, g: 113, b: 113 }), // Warm Red - colord({ r: 249, g: 115, b: 22 }), // Tangerine - colord({ r: 250, g: 215, b: 225 }), // Cotton Candy - colord({ r: 250, g: 250, b: 210 }), // Pastel Lemon - colord({ r: 251, g: 113, b: 133 }), // Watermelon - colord({ r: 251, g: 146, b: 60 }), // Light Orange - colord({ r: 251, g: 191, b: 36 }), // Marigold - colord({ r: 251, g: 235, b: 245 }), // Rose Powder - colord({ r: 252, g: 165, b: 165 }), // Peach - colord({ r: 252, g: 211, b: 77 }), // Golden - colord({ r: 253, g: 164, b: 175 }), // Salmon Pink - colord({ r: 255, g: 204, b: 229 }), // Blush Pink - colord({ r: 255, g: 223, b: 186 }), // Apricot Cream - colord({ r: 255, g: 240, b: 200 }), // Vanilla + colord({ b: 129, g: 185, r: 16 }), // Sea Green + colord({ b: 94, g: 197, r: 34 }), // Emerald + colord({ b: 191, g: 212, r: 45 }), // Turquoise + colord({ b: 180, g: 178, r: 48 }), // Teal + colord({ b: 153, g: 211, r: 52 }), // Spearmint + colord({ b: 248, g: 189, r: 56 }), // Light Blue + colord({ b: 246, g: 130, r: 59 }), // Royal Blue + colord({ b: 84, g: 190, r: 67 }), // Fresh Green + colord({ b: 128, g: 222, r: 74 }), // Mint + colord({ b: 229, g: 70, r: 79 }), // Indigo + colord({ b: 136, g: 183, r: 82 }), // Jade + colord({ b: 250, g: 165, r: 96 }), // Sky Blue + colord({ b: 253, g: 202, r: 99 }), // Azure + colord({ b: 183, g: 231, r: 110 }), // Seafoam + colord({ b: 237, g: 58, r: 124 }), // Royal Purple + colord({ b: 252, g: 211, r: 125 }), // Crystal Blue + colord({ b: 22, g: 204, r: 132 }), // Lime + colord({ b: 14, g: 77, r: 133 }), // Chocolate + colord({ b: 172, g: 239, r: 134 }), // Light Green + colord({ b: 234, g: 51, r: 147 }), // Bright Purple + colord({ b: 253, g: 197, r: 147 }), // Powder Blue + colord({ b: 187, g: 255, r: 151 }), // Fresh Mint + colord({ b: 53, g: 230, r: 163 }), // Yellow Green + colord({ b: 250, g: 139, r: 167 }), // Periwinkle + colord({ b: 247, g: 85, r: 168 }), // Vibrant Purple + colord({ b: 255, g: 136, r: 179 }), // Light Purple + colord({ b: 201, g: 255, r: 186 }), // Pale Emerald + colord({ b: 251, g: 92, r: 190 }), // Amethyst + colord({ b: 252, g: 132, r: 192 }), // Lavender + colord({ b: 4, g: 138, r: 202 }), // Rich Gold + colord({ b: 255, g: 225, r: 202 }), // Baby Blue + colord({ b: 255, g: 204, r: 204 }), // Soft Lavender Blue + colord({ b: 239, g: 70, r: 217 }), // Fuchsia + colord({ b: 38, g: 38, r: 220 }), // Ruby + colord({ b: 255, g: 220, r: 220 }), // Meringue Blue + colord({ b: 250, g: 240, r: 220 }), // Ice Blue + colord({ b: 210, g: 250, r: 230 }), // Pastel Lime + colord({ b: 250, g: 255, r: 230 }), // Mint Whisper + colord({ b: 255, g: 213, r: 233 }), // Light Lilac + colord({ b: 12, g: 88, r: 234 }), // Burnt Orange + colord({ b: 8, g: 179, r: 234 }), // Sunflower + colord({ b: 75, g: 75, r: 235 }), // Bright Red + colord({ b: 153, g: 72, r: 236 }), // Deep Pink + colord({ b: 68, g: 68, r: 239 }), // Crimson + colord({ b: 252, g: 171, r: 240 }), // Orchid + colord({ b: 200, g: 240, r: 240 }), // Light Khaki + colord({ b: 182, g: 114, r: 244 }), // Rose + colord({ b: 101, g: 101, r: 245 }), // Coral + colord({ b: 11, g: 158, r: 245 }), // Amber + colord({ b: 113, g: 113, r: 248 }), // Warm Red + colord({ b: 22, g: 115, r: 249 }), // Tangerine + colord({ b: 225, g: 215, r: 250 }), // Cotton Candy + colord({ b: 210, g: 250, r: 250 }), // Pastel Lemon + colord({ b: 133, g: 113, r: 251 }), // Watermelon + colord({ b: 60, g: 146, r: 251 }), // Light Orange + colord({ b: 36, g: 191, r: 251 }), // Marigold + colord({ b: 245, g: 235, r: 251 }), // Rose Powder + colord({ b: 165, g: 165, r: 252 }), // Peach + colord({ b: 77, g: 211, r: 252 }), // Golden + colord({ b: 175, g: 164, r: 253 }), // Salmon Pink + colord({ b: 229, g: 204, r: 255 }), // Blush Pink + colord({ b: 186, g: 223, r: 255 }), // Apricot Cream + colord({ b: 200, g: 240, r: 255 }), // Vanilla ]; export const botColors: Colord[] = [ - colord({ r: 190, g: 120, b: 120 }), // Muted Red - colord({ r: 120, g: 160, b: 190 }), // Muted Sky Blue - colord({ r: 190, g: 160, b: 100 }), // Muted Golden Yellow - colord({ r: 160, g: 120, b: 190 }), // Muted Purple - colord({ r: 100, g: 170, b: 130 }), // Muted Emerald Green - colord({ r: 190, g: 130, b: 160 }), // Muted Pink - colord({ r: 120, g: 150, b: 100 }), // Muted Olive Green - colord({ r: 190, g: 140, b: 120 }), // Muted Peach - colord({ r: 100, g: 120, b: 160 }), // Muted Navy Blue - colord({ r: 170, g: 170, b: 120 }), // Muted Lime Yellow - colord({ r: 160, g: 120, b: 130 }), // Muted Maroon - colord({ r: 120, g: 170, b: 170 }), // Muted Turquoise - colord({ r: 170, g: 140, b: 100 }), // Muted Light Orange - colord({ r: 140, g: 120, b: 160 }), // Muted Lavender - colord({ r: 150, g: 170, b: 130 }), // Muted Light Green - colord({ r: 170, g: 120, b: 140 }), // Muted Hot Pink - colord({ r: 120, g: 140, b: 120 }), // Muted Sea Green - colord({ r: 180, g: 160, b: 160 }), // Muted Light Pink - colord({ r: 130, g: 130, b: 160 }), // Muted Periwinkle - colord({ r: 160, g: 150, b: 120 }), // Muted Sand - colord({ r: 120, g: 160, b: 150 }), // Muted Aquamarine - colord({ r: 170, g: 150, b: 170 }), // Muted Orchid - colord({ r: 150, g: 160, b: 120 }), // Muted Yellow Green - colord({ r: 120, g: 130, b: 140 }), // Muted Steel Blue - colord({ r: 180, g: 140, b: 140 }), // Muted Salmon - colord({ r: 140, g: 160, b: 170 }), // Muted Light Blue - colord({ r: 170, g: 150, b: 130 }), // Muted Tan - colord({ r: 160, g: 130, b: 160 }), // Muted Plum - colord({ r: 130, g: 170, b: 130 }), // Muted Light Sea Green - colord({ r: 170, g: 130, b: 130 }), // Muted Coral - colord({ r: 130, g: 150, b: 170 }), // Muted Cornflower Blue - colord({ r: 170, g: 170, b: 140 }), // Muted Khaki - colord({ r: 150, g: 130, b: 150 }), // Muted Purple Gray - colord({ r: 140, g: 160, b: 140 }), // Muted Dark Sea Green - colord({ r: 170, g: 130, b: 120 }), // Muted Dark Salmon - colord({ r: 130, g: 150, b: 160 }), // Muted Cadet Blue - colord({ r: 160, g: 160, b: 150 }), // Muted Tan Gray - colord({ r: 150, g: 140, b: 160 }), // Muted Medium Purple - colord({ r: 150, g: 170, b: 150 }), // Muted Pale Green - colord({ r: 160, g: 140, b: 130 }), // Muted Rosy Brown - colord({ r: 140, g: 150, b: 160 }), // Muted Light Slate Gray - colord({ r: 160, g: 150, b: 140 }), // Muted Dark Khaki - colord({ r: 140, g: 130, b: 140 }), // Muted Thistle - colord({ r: 150, g: 160, b: 160 }), // Muted Pale Blue Green - colord({ r: 160, g: 140, b: 150 }), // Muted Puce - colord({ r: 130, g: 160, b: 150 }), // Muted Medium Aquamarine - colord({ r: 160, g: 150, b: 160 }), // Muted Mauve - colord({ r: 150, g: 160, b: 140 }), // Muted Dark Olive Green - colord({ r: 150, g: 140, b: 150 }), // Muted Dusty Rose + colord({ b: 120, g: 120, r: 190 }), // Muted Red + colord({ b: 190, g: 160, r: 120 }), // Muted Sky Blue + colord({ b: 100, g: 160, r: 190 }), // Muted Golden Yellow + colord({ b: 190, g: 120, r: 160 }), // Muted Purple + colord({ b: 130, g: 170, r: 100 }), // Muted Emerald Green + colord({ b: 160, g: 130, r: 190 }), // Muted Pink + colord({ b: 100, g: 150, r: 120 }), // Muted Olive Green + colord({ b: 120, g: 140, r: 190 }), // Muted Peach + colord({ b: 160, g: 120, r: 100 }), // Muted Navy Blue + colord({ b: 120, g: 170, r: 170 }), // Muted Lime Yellow + colord({ b: 130, g: 120, r: 160 }), // Muted Maroon + colord({ b: 170, g: 170, r: 120 }), // Muted Turquoise + colord({ b: 100, g: 140, r: 170 }), // Muted Light Orange + colord({ b: 160, g: 120, r: 140 }), // Muted Lavender + colord({ b: 130, g: 170, r: 150 }), // Muted Light Green + colord({ b: 140, g: 120, r: 170 }), // Muted Hot Pink + colord({ b: 120, g: 140, r: 120 }), // Muted Sea Green + colord({ b: 160, g: 160, r: 180 }), // Muted Light Pink + colord({ b: 160, g: 130, r: 130 }), // Muted Periwinkle + colord({ b: 120, g: 150, r: 160 }), // Muted Sand + colord({ b: 150, g: 160, r: 120 }), // Muted Aquamarine + colord({ b: 170, g: 150, r: 170 }), // Muted Orchid + colord({ b: 120, g: 160, r: 150 }), // Muted Yellow Green + colord({ b: 140, g: 130, r: 120 }), // Muted Steel Blue + colord({ b: 140, g: 140, r: 180 }), // Muted Salmon + colord({ b: 170, g: 160, r: 140 }), // Muted Light Blue + colord({ b: 130, g: 150, r: 170 }), // Muted Tan + colord({ b: 160, g: 130, r: 160 }), // Muted Plum + colord({ b: 130, g: 170, r: 130 }), // Muted Light Sea Green + colord({ b: 130, g: 130, r: 170 }), // Muted Coral + colord({ b: 170, g: 150, r: 130 }), // Muted Cornflower Blue + colord({ b: 140, g: 170, r: 170 }), // Muted Khaki + colord({ b: 150, g: 130, r: 150 }), // Muted Purple Gray + colord({ b: 140, g: 160, r: 140 }), // Muted Dark Sea Green + colord({ b: 120, g: 130, r: 170 }), // Muted Dark Salmon + colord({ b: 160, g: 150, r: 130 }), // Muted Cadet Blue + colord({ b: 150, g: 160, r: 160 }), // Muted Tan Gray + colord({ b: 160, g: 140, r: 150 }), // Muted Medium Purple + colord({ b: 150, g: 170, r: 150 }), // Muted Pale Green + colord({ b: 130, g: 140, r: 160 }), // Muted Rosy Brown + colord({ b: 160, g: 150, r: 140 }), // Muted Light Slate Gray + colord({ b: 140, g: 150, r: 160 }), // Muted Dark Khaki + colord({ b: 140, g: 130, r: 140 }), // Muted Thistle + colord({ b: 160, g: 160, r: 150 }), // Muted Pale Blue Green + colord({ b: 150, g: 140, r: 160 }), // Muted Puce + colord({ b: 150, g: 160, r: 130 }), // Muted Medium Aquamarine + colord({ b: 160, g: 150, r: 160 }), // Muted Mauve + colord({ b: 140, g: 160, r: 150 }), // Muted Dark Olive Green + colord({ b: 150, g: 140, r: 150 }), // Muted Dusty Rose ]; // Fallback colors for when the color palette is exhausted. Currently 100 colors. export const fallbackColors: Colord[] = [ - colord({ r: 0, g: 5, b: 0 }), // Black Mint - colord({ r: 0, g: 15, b: 0 }), // Deep Forest - colord({ r: 0, g: 25, b: 0 }), // Jungle - colord({ r: 0, g: 35, b: 0 }), // Dark Emerald - colord({ r: 0, g: 45, b: 0 }), // Green Moss - colord({ r: 0, g: 55, b: 0 }), // Moss Shadow - colord({ r: 0, g: 65, b: 0 }), // Dark Meadow - colord({ r: 0, g: 75, b: 0 }), // Forest Fern - colord({ r: 0, g: 85, b: 0 }), // Pine Leaf - colord({ r: 0, g: 95, b: 0 }), // Shadow Grass - colord({ r: 0, g: 105, b: 0 }), // Classic Green - colord({ r: 0, g: 115, b: 0 }), // Deep Lime - colord({ r: 0, g: 125, b: 0 }), // Dense Leaf - colord({ r: 0, g: 135, b: 0 }), // Basil Green - colord({ r: 0, g: 145, b: 0 }), // Organic Green - colord({ r: 0, g: 155, b: 0 }), // Bitter Herb - colord({ r: 0, g: 165, b: 0 }), // Raw Spinach - colord({ r: 0, g: 175, b: 0 }), // Woodland - colord({ r: 0, g: 185, b: 0 }), // Spring Weed - colord({ r: 0, g: 195, b: 5 }), // Apple Stem - colord({ r: 0, g: 205, b: 10 }), // Crisp Lettuce - colord({ r: 0, g: 215, b: 15 }), // Vibrant Green - colord({ r: 0, g: 225, b: 20 }), // Bright Herb - colord({ r: 0, g: 235, b: 25 }), // Green Splash - colord({ r: 0, g: 245, b: 30 }), // Mint Leaf - colord({ r: 0, g: 255, b: 35 }), // Fresh Mint - colord({ r: 10, g: 255, b: 45 }), // Neon Grass - colord({ r: 20, g: 255, b: 55 }), // Lemon Balm - colord({ r: 30, g: 255, b: 65 }), // Juicy Green - colord({ r: 40, g: 255, b: 75 }), // Pear Tint - colord({ r: 50, g: 255, b: 85 }), // Avocado Pastel - colord({ r: 60, g: 255, b: 95 }), // Lime Glow - colord({ r: 70, g: 255, b: 105 }), // Light Leaf - colord({ r: 80, g: 255, b: 115 }), // Soft Fern - colord({ r: 90, g: 255, b: 125 }), // Pastel Green - colord({ r: 100, g: 255, b: 135 }), // Green Melon - colord({ r: 110, g: 255, b: 145 }), // Herbal Mist - colord({ r: 120, g: 255, b: 155 }), // Kiwi Foam - colord({ r: 130, g: 255, b: 165 }), // Aloe Fresh - colord({ r: 140, g: 255, b: 175 }), // Light Mint - colord({ r: 150, g: 200, b: 255 }), // Cornflower Mist - colord({ r: 150, g: 255, b: 185 }), // Green Sorbet - colord({ r: 160, g: 215, b: 255 }), // Powder Blue - colord({ r: 160, g: 255, b: 195 }), // Pastel Apple - colord({ r: 170, g: 190, b: 255 }), // Periwinkle Ice - colord({ r: 170, g: 225, b: 255 }), // Baby Sky - colord({ r: 170, g: 255, b: 205 }), // Aloe Breeze - colord({ r: 180, g: 180, b: 255 }), // Pale Indigo - colord({ r: 180, g: 235, b: 250 }), // Aqua Pastel - colord({ r: 180, g: 255, b: 215 }), // Pale Mint - colord({ r: 190, g: 140, b: 195 }), // Fuchsia Tint - colord({ r: 190, g: 245, b: 240 }), // Ice Mint - colord({ r: 190, g: 255, b: 225 }), // Mint Water - colord({ r: 195, g: 145, b: 200 }), // Dusky Rose - colord({ r: 200, g: 150, b: 205 }), // Plum Frost - colord({ r: 200, g: 170, b: 255 }), // Lilac Bloom - colord({ r: 200, g: 255, b: 215 }), // Cool Aloe - colord({ r: 200, g: 255, b: 235 }), // Cool Mist - colord({ r: 205, g: 155, b: 210 }), // Berry Foam - colord({ r: 210, g: 160, b: 215 }), // Grape Cloud - colord({ r: 210, g: 255, b: 245 }), // Sea Mist - colord({ r: 215, g: 165, b: 220 }), // Light Bloom - colord({ r: 215, g: 255, b: 200 }), // Fresh Mint - colord({ r: 220, g: 160, b: 255 }), // Violet Mist - colord({ r: 220, g: 170, b: 225 }), // Cherry Blossom - colord({ r: 220, g: 255, b: 255 }), // Pale Aqua - colord({ r: 225, g: 175, b: 230 }), // Faded Rose - colord({ r: 225, g: 255, b: 175 }), // Soft Lime - colord({ r: 230, g: 180, b: 235 }), // Dreamy Mauve - colord({ r: 230, g: 250, b: 255 }), // Sky Haze - colord({ r: 235, g: 150, b: 255 }), // Orchid Glow - colord({ r: 235, g: 185, b: 240 }), // Powder Violet - colord({ r: 240, g: 190, b: 245 }), // Pastel Violet - colord({ r: 240, g: 240, b: 255 }), // Frosted Lilac - colord({ r: 240, g: 250, b: 160 }), // Citrus Wash - colord({ r: 245, g: 160, b: 240 }), // Rose Lilac - colord({ r: 245, g: 195, b: 250 }), // Soft Magenta - colord({ r: 245, g: 245, b: 175 }), // Lemon Mist - colord({ r: 250, g: 200, b: 255 }), // Lilac Cream - colord({ r: 250, g: 230, b: 255 }), // Misty Mauve - colord({ r: 255, g: 170, b: 225 }), // Bubblegum Pink - colord({ r: 255, g: 185, b: 215 }), // Blush Mist - colord({ r: 255, g: 195, b: 235 }), // Faded Fuchsia - colord({ r: 255, g: 200, b: 220 }), // Cotton Rose - colord({ r: 255, g: 205, b: 245 }), // Pastel Orchid - colord({ r: 255, g: 205, b: 255 }), // Violet Bloom - colord({ r: 255, g: 210, b: 230 }), // Pastel Blush - colord({ r: 255, g: 210, b: 250 }), // Lavender Mist - colord({ r: 255, g: 210, b: 255 }), // Orchid Mist - colord({ r: 255, g: 215, b: 195 }), // Apricot Glow - colord({ r: 255, g: 215, b: 245 }), // Rose Whisper - colord({ r: 255, g: 220, b: 235 }), // Pink Mist - colord({ r: 255, g: 220, b: 250 }), // Powder Petal - colord({ r: 255, g: 225, b: 180 }), // Butter Peach - colord({ r: 255, g: 225, b: 255 }), // Petal Mist - colord({ r: 255, g: 230, b: 245 }), // Light Rose - colord({ r: 255, g: 235, b: 200 }), // Cream Peach - colord({ r: 255, g: 235, b: 235 }), // Blushed Petal - colord({ r: 255, g: 240, b: 220 }), // Pastel Sand - colord({ r: 255, g: 245, b: 210 }), // Soft Banana + colord({ b: 0, g: 5, r: 0 }), // Black Mint + colord({ b: 0, g: 15, r: 0 }), // Deep Forest + colord({ b: 0, g: 25, r: 0 }), // Jungle + colord({ b: 0, g: 35, r: 0 }), // Dark Emerald + colord({ b: 0, g: 45, r: 0 }), // Green Moss + colord({ b: 0, g: 55, r: 0 }), // Moss Shadow + colord({ b: 0, g: 65, r: 0 }), // Dark Meadow + colord({ b: 0, g: 75, r: 0 }), // Forest Fern + colord({ b: 0, g: 85, r: 0 }), // Pine Leaf + colord({ b: 0, g: 95, r: 0 }), // Shadow Grass + colord({ b: 0, g: 105, r: 0 }), // Classic Green + colord({ b: 0, g: 115, r: 0 }), // Deep Lime + colord({ b: 0, g: 125, r: 0 }), // Dense Leaf + colord({ b: 0, g: 135, r: 0 }), // Basil Green + colord({ b: 0, g: 145, r: 0 }), // Organic Green + colord({ b: 0, g: 155, r: 0 }), // Bitter Herb + colord({ b: 0, g: 165, r: 0 }), // Raw Spinach + colord({ b: 0, g: 175, r: 0 }), // Woodland + colord({ b: 0, g: 185, r: 0 }), // Spring Weed + colord({ b: 5, g: 195, r: 0 }), // Apple Stem + colord({ b: 10, g: 205, r: 0 }), // Crisp Lettuce + colord({ b: 15, g: 215, r: 0 }), // Vibrant Green + colord({ b: 20, g: 225, r: 0 }), // Bright Herb + colord({ b: 25, g: 235, r: 0 }), // Green Splash + colord({ b: 30, g: 245, r: 0 }), // Mint Leaf + colord({ b: 35, g: 255, r: 0 }), // Fresh Mint + colord({ b: 45, g: 255, r: 10 }), // Neon Grass + colord({ b: 55, g: 255, r: 20 }), // Lemon Balm + colord({ b: 65, g: 255, r: 30 }), // Juicy Green + colord({ b: 75, g: 255, r: 40 }), // Pear Tint + colord({ b: 85, g: 255, r: 50 }), // Avocado Pastel + colord({ b: 95, g: 255, r: 60 }), // Lime Glow + colord({ b: 105, g: 255, r: 70 }), // Light Leaf + colord({ b: 115, g: 255, r: 80 }), // Soft Fern + colord({ b: 125, g: 255, r: 90 }), // Pastel Green + colord({ b: 135, g: 255, r: 100 }), // Green Melon + colord({ b: 145, g: 255, r: 110 }), // Herbal Mist + colord({ b: 155, g: 255, r: 120 }), // Kiwi Foam + colord({ b: 165, g: 255, r: 130 }), // Aloe Fresh + colord({ b: 175, g: 255, r: 140 }), // Light Mint + colord({ b: 255, g: 200, r: 150 }), // Cornflower Mist + colord({ b: 185, g: 255, r: 150 }), // Green Sorbet + colord({ b: 255, g: 215, r: 160 }), // Powder Blue + colord({ b: 195, g: 255, r: 160 }), // Pastel Apple + colord({ b: 255, g: 190, r: 170 }), // Periwinkle Ice + colord({ b: 255, g: 225, r: 170 }), // Baby Sky + colord({ b: 205, g: 255, r: 170 }), // Aloe Breeze + colord({ b: 255, g: 180, r: 180 }), // Pale Indigo + colord({ b: 250, g: 235, r: 180 }), // Aqua Pastel + colord({ b: 215, g: 255, r: 180 }), // Pale Mint + colord({ b: 195, g: 140, r: 190 }), // Fuchsia Tint + colord({ b: 240, g: 245, r: 190 }), // Ice Mint + colord({ b: 225, g: 255, r: 190 }), // Mint Water + colord({ b: 200, g: 145, r: 195 }), // Dusky Rose + colord({ b: 205, g: 150, r: 200 }), // Plum Frost + colord({ b: 255, g: 170, r: 200 }), // Lilac Bloom + colord({ b: 215, g: 255, r: 200 }), // Cool Aloe + colord({ b: 235, g: 255, r: 200 }), // Cool Mist + colord({ b: 210, g: 155, r: 205 }), // Berry Foam + colord({ b: 215, g: 160, r: 210 }), // Grape Cloud + colord({ b: 245, g: 255, r: 210 }), // Sea Mist + colord({ b: 220, g: 165, r: 215 }), // Light Bloom + colord({ b: 200, g: 255, r: 215 }), // Fresh Mint + colord({ b: 255, g: 160, r: 220 }), // Violet Mist + colord({ b: 225, g: 170, r: 220 }), // Cherry Blossom + colord({ b: 255, g: 255, r: 220 }), // Pale Aqua + colord({ b: 230, g: 175, r: 225 }), // Faded Rose + colord({ b: 175, g: 255, r: 225 }), // Soft Lime + colord({ b: 235, g: 180, r: 230 }), // Dreamy Mauve + colord({ b: 255, g: 250, r: 230 }), // Sky Haze + colord({ b: 255, g: 150, r: 235 }), // Orchid Glow + colord({ b: 240, g: 185, r: 235 }), // Powder Violet + colord({ b: 245, g: 190, r: 240 }), // Pastel Violet + colord({ b: 255, g: 240, r: 240 }), // Frosted Lilac + colord({ b: 160, g: 250, r: 240 }), // Citrus Wash + colord({ b: 240, g: 160, r: 245 }), // Rose Lilac + colord({ b: 250, g: 195, r: 245 }), // Soft Magenta + colord({ b: 175, g: 245, r: 245 }), // Lemon Mist + colord({ b: 255, g: 200, r: 250 }), // Lilac Cream + colord({ b: 255, g: 230, r: 250 }), // Misty Mauve + colord({ b: 225, g: 170, r: 255 }), // Bubblegum Pink + colord({ b: 215, g: 185, r: 255 }), // Blush Mist + colord({ b: 235, g: 195, r: 255 }), // Faded Fuchsia + colord({ b: 220, g: 200, r: 255 }), // Cotton Rose + colord({ b: 245, g: 205, r: 255 }), // Pastel Orchid + colord({ b: 255, g: 205, r: 255 }), // Violet Bloom + colord({ b: 230, g: 210, r: 255 }), // Pastel Blush + colord({ b: 250, g: 210, r: 255 }), // Lavender Mist + colord({ b: 255, g: 210, r: 255 }), // Orchid Mist + colord({ b: 195, g: 215, r: 255 }), // Apricot Glow + colord({ b: 245, g: 215, r: 255 }), // Rose Whisper + colord({ b: 235, g: 220, r: 255 }), // Pink Mist + colord({ b: 250, g: 220, r: 255 }), // Powder Petal + colord({ b: 180, g: 225, r: 255 }), // Butter Peach + colord({ b: 255, g: 225, r: 255 }), // Petal Mist + colord({ b: 245, g: 230, r: 255 }), // Light Rose + colord({ b: 200, g: 235, r: 255 }), // Cream Peach + colord({ b: 235, g: 235, r: 255 }), // Blushed Petal + colord({ b: 220, g: 240, r: 255 }), // Pastel Sand + colord({ b: 210, g: 245, r: 255 }), // Soft Banana ]; diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 2522651a5..6a3eb2404 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -376,7 +376,6 @@ export class DefaultConfig implements Config { return 1_000_000; } - /* eslint-disable sort-keys */ unitInfo(type: UnitType): UnitInfo { switch (type) { case UnitType.TransportShip: @@ -389,14 +388,14 @@ export class DefaultConfig implements Config { cost: this.costWrapper(UnitType.Warship, (numUnits: number) => Math.min(1_000_000, (numUnits + 1) * 250_000), ), - territoryBound: false, maxHealth: 1000, + territoryBound: false, }; case UnitType.Shell: return { cost: () => 0n, - territoryBound: false, damage: 250, + territoryBound: false, }; case UnitType.SAMMissile: return { @@ -405,13 +404,13 @@ export class DefaultConfig implements Config { }; case UnitType.Port: return { + canBuildTrainStation: true, + constructionDuration: this.instantBuild() ? 0 : 2 * 10, cost: this.costWrapper(UnitType.Port, (numUnits: number) => Math.min(1_000_000, Math.pow(2, numUnits) * 125_000), ), territoryBound: true, - constructionDuration: this.instantBuild() ? 0 : 2 * 10, upgradable: true, - canBuildTrainStation: true, }; case UnitType.AtomBomb: return { @@ -440,47 +439,47 @@ export class DefaultConfig implements Config { }; case UnitType.MissileSilo: return { + constructionDuration: this.instantBuild() ? 0 : 10 * 10, cost: this.costWrapper(UnitType.MissileSilo, () => 1_000_000), territoryBound: true, - constructionDuration: this.instantBuild() ? 0 : 10 * 10, upgradable: true, }; case UnitType.DefensePost: return { + constructionDuration: this.instantBuild() ? 0 : 5 * 10, cost: this.costWrapper(UnitType.DefensePost, (numUnits: number) => Math.min(250_000, (numUnits + 1) * 50_000), ), territoryBound: true, - constructionDuration: this.instantBuild() ? 0 : 5 * 10, }; case UnitType.SAMLauncher: return { + constructionDuration: this.instantBuild() ? 0 : 30 * 10, cost: this.costWrapper(UnitType.SAMLauncher, (numUnits: number) => Math.min(3_000_000, (numUnits + 1) * 1_500_000), ), territoryBound: true, - constructionDuration: this.instantBuild() ? 0 : 30 * 10, upgradable: true, }; case UnitType.City: return { + canBuildTrainStation: true, + constructionDuration: this.instantBuild() ? 0 : 2 * 10, cost: this.costWrapper(UnitType.City, (numUnits: number) => Math.min(1_000_000, Math.pow(2, numUnits) * 125_000), ), territoryBound: true, - constructionDuration: this.instantBuild() ? 0 : 2 * 10, upgradable: true, - canBuildTrainStation: true, }; case UnitType.Factory: return { + canBuildTrainStation: true, + constructionDuration: this.instantBuild() ? 0 : 2 * 10, cost: this.costWrapper(UnitType.Factory, (numUnits: number) => Math.min(1_000_000, Math.pow(2, numUnits) * 125_000), ), - territoryBound: true, - constructionDuration: this.instantBuild() ? 0 : 2 * 10, - canBuildTrainStation: true, experimental: true, + territoryBound: true, upgradable: true, }; case UnitType.Construction: @@ -491,14 +490,13 @@ export class DefaultConfig implements Config { case UnitType.Train: return { cost: () => 0n, - territoryBound: false, experimental: true, + territoryBound: false, }; default: assertNever(type); } } - /* eslint-enable sort-keys */ private costWrapper( type: UnitType, diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts index 72db7689e..29964a26c 100644 --- a/src/core/configuration/PastelTheme.ts +++ b/src/core/configuration/PastelTheme.ts @@ -26,26 +26,24 @@ export class PastelTheme implements Theme { nationColors, ); - /* eslint-disable sort-keys */ - private readonly background = colord({ r: 60, g: 60, b: 60 }); - private readonly shore = colord({ r: 204, g: 203, b: 158 }); + private readonly background = colord({ b: 60, g: 60, r: 60 }); + private readonly shore = colord({ b: 158, g: 203, r: 204 }); private readonly falloutColors = [ - colord({ r: 120, g: 255, b: 71 }), // Original color - colord({ r: 130, g: 255, b: 85 }), // Slightly lighter - colord({ r: 110, g: 245, b: 65 }), // Slightly darker - colord({ r: 125, g: 255, b: 75 }), // Warmer tint - colord({ r: 115, g: 250, b: 68 }), // Cooler tint + colord({ b: 71, g: 255, r: 120 }), // Original color + colord({ b: 85, g: 255, r: 130 }), // Slightly lighter + colord({ b: 65, g: 245, r: 110 }), // Slightly darker + colord({ b: 75, g: 255, r: 125 }), // Warmer tint + colord({ b: 68, g: 250, r: 115 }), // Cooler tint ]; - private readonly water = colord({ r: 70, g: 132, b: 180 }); - private readonly shorelineWater = colord({ r: 100, g: 143, b: 255 }); + private readonly water = colord({ b: 180, g: 132, r: 70 }); + private readonly shorelineWater = colord({ b: 255, g: 143, r: 100 }); - private readonly _selfColor = colord({ r: 0, g: 255, b: 0 }); - private readonly _allyColor = colord({ r: 255, g: 255, b: 0 }); - private readonly _neutralColor = colord({ r: 128, g: 128, b: 128 }); - private readonly _enemyColor = colord({ r: 255, g: 0, b: 0 }); + private readonly _selfColor = colord({ b: 0, g: 255, r: 0 }); + private readonly _allyColor = colord({ b: 0, g: 255, r: 255 }); + private readonly _neutralColor = colord({ b: 128, g: 128, r: 128 }); + private readonly _enemyColor = colord({ b: 0, g: 0, r: 255 }); - private readonly _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }); - /* eslint-enable sort-keys */ + private readonly _spawnHighlightColor = colord({ b: 79, g: 213, r: 255 }); teamColor(team: Team): Colord { return this.teamColorAllocator.assignTeamColor(team); @@ -71,24 +69,23 @@ export class PastelTheme implements Theme { specialBuildingColor(player: PlayerView): Colord { const tc = this.territoryColor(player).rgba; - /* eslint-disable sort-keys */ + return colord({ - r: Math.max(tc.r - 50, 0), - g: Math.max(tc.g - 50, 0), b: Math.max(tc.b - 50, 0), + g: Math.max(tc.g - 50, 0), + r: Math.max(tc.r - 50, 0), }); - /* eslint-enable sort-keys */ } railroadColor(player: PlayerView): Colord { const tc = this.territoryColor(player).rgba; - /* eslint-disable sort-keys */ + const color = colord({ - r: Math.max(tc.r - 10, 0), - g: Math.max(tc.g - 10, 0), b: Math.max(tc.b - 10, 0), + g: Math.max(tc.g - 10, 0), + r: Math.max(tc.r - 10, 0), }); - /* eslint-enable sort-keys */ + return color; } @@ -97,28 +94,26 @@ export class PastelTheme implements Theme { if (cached !== undefined) return cached; const tc = this.territoryColor(player).rgba; - /* eslint-disable sort-keys */ + const color = colord({ - r: Math.max(tc.r - 40, 0), - g: Math.max(tc.g - 40, 0), b: Math.max(tc.b - 40, 0), + g: Math.max(tc.g - 40, 0), + r: Math.max(tc.r - 40, 0), }); - /* eslint-enable sort-keys */ this.borderColorCache.set(player.id(), color); return color; } - /* eslint-disable sort-keys */ defendedBorderColors(player: PlayerView): { light: Colord; dark: Colord } { return { - light: this.territoryColor(player).darken(0.2), dark: this.territoryColor(player).darken(0.4), + light: this.territoryColor(player).darken(0.2), }; } focusedBorderColor(): Colord { - return colord({ r: 230, g: 230, b: 230 }); + return colord({ b: 230, g: 230, r: 230 }); } terrainColor(gm: GameMap, tile: TileRef): Colord { @@ -134,32 +129,31 @@ export class PastelTheme implements Theme { return this.shorelineWater; } return colord({ - r: Math.max(w.r - 10 + (11 - Math.min(mag, 10)), 0), - g: Math.max(w.g - 10 + (11 - Math.min(mag, 10)), 0), b: Math.max(w.b - 10 + (11 - Math.min(mag, 10)), 0), + g: Math.max(w.g - 10 + (11 - Math.min(mag, 10)), 0), + r: Math.max(w.r - 10 + (11 - Math.min(mag, 10)), 0), }); case TerrainType.Plains: return colord({ - r: 190, - g: 220 - 2 * mag, b: 138, + g: 220 - 2 * mag, + r: 190, }); case TerrainType.Highland: return colord({ - r: 200 + 2 * mag, - g: 183 + 2 * mag, b: 138 + 2 * mag, + g: 183 + 2 * mag, + r: 200 + 2 * mag, }); case TerrainType.Mountain: return colord({ - r: 230 + mag / 2, - g: 230 + mag / 2, b: 230 + mag / 2, + g: 230 + mag / 2, + r: 230 + mag / 2, }); } } - /* eslint-enable sort-keys */ backgroundColor(): Colord { return this.background; diff --git a/src/core/configuration/PastelThemeDark.ts b/src/core/configuration/PastelThemeDark.ts index 8c5ba3ca5..9d12b5d94 100644 --- a/src/core/configuration/PastelThemeDark.ts +++ b/src/core/configuration/PastelThemeDark.ts @@ -26,26 +26,24 @@ export class PastelThemeDark implements Theme { nationColors, ); - /* eslint-disable sort-keys */ - private readonly background = colord({ r: 0, g: 0, b: 0 }); - private readonly shore = colord({ r: 134, g: 133, b: 88 }); + private readonly background = colord({ b: 0, g: 0, r: 0 }); + private readonly shore = colord({ b: 88, g: 133, r: 134 }); private readonly falloutColors = [ - colord({ r: 120, g: 255, b: 71 }), // Original color - colord({ r: 130, g: 255, b: 85 }), // Slightly lighter - colord({ r: 110, g: 245, b: 65 }), // Slightly darker - colord({ r: 125, g: 255, b: 75 }), // Warmer tint - colord({ r: 115, g: 250, b: 68 }), // Cooler tint + colord({ b: 71, g: 255, r: 120 }), // Original color + colord({ b: 85, g: 255, r: 130 }), // Slightly lighter + colord({ b: 65, g: 245, r: 110 }), // Slightly darker + colord({ b: 75, g: 255, r: 125 }), // Warmer tint + colord({ b: 68, g: 250, r: 115 }), // Cooler tint ]; - private readonly water = colord({ r: 14, g: 11, b: 30 }); - private readonly shorelineWater = colord({ r: 50, g: 50, b: 50 }); + private readonly water = colord({ b: 30, g: 11, r: 14 }); + private readonly shorelineWater = colord({ b: 50, g: 50, r: 50 }); - private readonly _selfColor = colord({ r: 0, g: 255, b: 0 }); - private readonly _allyColor = colord({ r: 255, g: 255, b: 0 }); - private readonly _neutralColor = colord({ r: 128, g: 128, b: 128 }); - private readonly _enemyColor = colord({ r: 255, g: 0, b: 0 }); + private readonly _selfColor = colord({ b: 0, g: 255, r: 0 }); + private readonly _allyColor = colord({ b: 0, g: 255, r: 255 }); + private readonly _neutralColor = colord({ b: 128, g: 128, r: 128 }); + private readonly _enemyColor = colord({ b: 0, g: 0, r: 255 }); - private readonly _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }); - /* eslint-enable sort-keys */ + private readonly _spawnHighlightColor = colord({ b: 79, g: 213, r: 255 }); teamColor(team: Team): Colord { return this.teamColorAllocator.assignTeamColor(team); @@ -69,22 +67,21 @@ export class PastelThemeDark implements Theme { return player.type() === PlayerType.Human ? "#ffffff" : "#e6e6e6"; } - /* eslint-disable sort-keys */ specialBuildingColor(player: PlayerView): Colord { const tc = this.territoryColor(player).rgba; return colord({ - r: Math.max(tc.r - 50, 0), - g: Math.max(tc.g - 50, 0), b: Math.max(tc.b - 50, 0), + g: Math.max(tc.g - 50, 0), + r: Math.max(tc.r - 50, 0), }); } railroadColor(player: PlayerView): Colord { const tc = this.territoryColor(player).rgba; const color = colord({ - r: Math.max(tc.r - 10, 0), - g: Math.max(tc.g - 10, 0), b: Math.max(tc.b - 10, 0), + g: Math.max(tc.g - 10, 0), + r: Math.max(tc.r - 10, 0), }); return color; } @@ -95,9 +92,9 @@ export class PastelThemeDark implements Theme { const tc = this.territoryColor(player).rgba; const color = colord({ - r: Math.max(tc.r - 40, 0), - g: Math.max(tc.g - 40, 0), b: Math.max(tc.b - 40, 0), + g: Math.max(tc.g - 40, 0), + r: Math.max(tc.r - 40, 0), }); this.borderColorCache.set(player.id(), color); @@ -106,13 +103,13 @@ export class PastelThemeDark implements Theme { defendedBorderColors(player: PlayerView): { light: Colord; dark: Colord } { return { - light: this.territoryColor(player).darken(0.2), dark: this.territoryColor(player).darken(0.4), + light: this.territoryColor(player).darken(0.2), }; } focusedBorderColor(): Colord { - return colord({ r: 255, g: 255, b: 255 }); + return colord({ b: 255, g: 255, r: 255 }); } terrainColor(gm: GameMap, tile: TileRef): Colord { @@ -129,33 +126,32 @@ export class PastelThemeDark implements Theme { } if (gm.magnitude(tile) < 10) { return colord({ - r: Math.max(w.r + 9 - mag, 0), - g: Math.max(w.g + 9 - mag, 0), b: Math.max(w.b + 9 - mag, 0), + g: Math.max(w.g + 9 - mag, 0), + r: Math.max(w.r + 9 - mag, 0), }); } return this.water; case TerrainType.Plains: return colord({ - r: 140, - g: 170 - 2 * mag, b: 88, + g: 170 - 2 * mag, + r: 140, }); case TerrainType.Highland: return colord({ - r: 150 + 2 * mag, - g: 133 + 2 * mag, b: 88 + 2 * mag, + g: 133 + 2 * mag, + r: 150 + 2 * mag, }); case TerrainType.Mountain: return colord({ - r: 180 + mag / 2, - g: 180 + mag / 2, b: 180 + mag / 2, + g: 180 + mag / 2, + r: 180 + mag / 2, }); } } - /* eslint-enable sort-keys */ backgroundColor(): Colord { return this.background; diff --git a/src/core/execution/RailroadExecution.ts b/src/core/execution/RailroadExecution.ts index c3e2ca0b4..1f3bc8d29 100644 --- a/src/core/execution/RailroadExecution.ts +++ b/src/core/execution/RailroadExecution.ts @@ -18,17 +18,16 @@ export class RailroadExecution implements Execution { return this.active; } - /* eslint-disable sort-keys */ init(mg: Game, ticks: number): void { this.mg = mg; const { tiles } = this.railRoad; // Inverse direction computation for the first tile this.railTiles.push({ - tile: tiles[0], railType: tiles.length > 0 ? this.computeExtremityDirection(tiles[0], tiles[1]) : RailType.VERTICAL, + tile: tiles[0], }); for (let i = 1; i < tiles.length - 1; i++) { const direction = this.computeDirection( @@ -36,10 +35,9 @@ export class RailroadExecution implements Execution { tiles[i], tiles[i + 1], ); - this.railTiles.push({ tile: tiles[i], railType: direction }); + this.railTiles.push({ railType: direction, tile: tiles[i] }); } this.railTiles.push({ - tile: tiles[tiles.length - 1], railType: tiles.length > 0 ? this.computeExtremityDirection( @@ -47,9 +45,9 @@ export class RailroadExecution implements Execution { tiles[tiles.length - 2], ) : RailType.VERTICAL, + tile: tiles[tiles.length - 1], }); } - /* eslint-enable sort-keys */ private computeExtremityDirection(tile: TileRef, next: TileRef): RailType { if (this.mg === undefined) throw new Error("Not initialized"); diff --git a/src/core/execution/SAMLauncherExecution.ts b/src/core/execution/SAMLauncherExecution.ts index 1b193b621..ef1b5fdfa 100644 --- a/src/core/execution/SAMLauncherExecution.ts +++ b/src/core/execution/SAMLauncherExecution.ts @@ -97,8 +97,7 @@ class SAMTargetingSystem { } const interceptionTile = this.computeInterceptionTile(nuke.unit); if (interceptionTile !== undefined) { - // eslint-disable-next-line sort-keys - targets.push({ unit: nuke.unit, tile: interceptionTile }); + targets.push({ tile: interceptionTile, unit: nuke.unit }); } else { // Store unreachable nukes in order to prevent useless interception computation this.storeUnreachableNukes(nuke.unit.id()); diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 3f90c909c..3dcd4af83 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -44,18 +44,16 @@ export const Duos = "Duos" as const; export const Trios = "Trios" as const; export const Quads = "Quads" as const; -/* eslint-disable sort-keys */ export const ColoredTeams: Record = { - Red: "Red", Blue: "Blue", - Teal: "Teal", - Purple: "Purple", - Yellow: "Yellow", - Orange: "Orange", - Green: "Green", Bot: "Bot", + Green: "Green", + Orange: "Orange", + Purple: "Purple", + Red: "Red", + Teal: "Teal", + Yellow: "Yellow", } as const; -/* eslint-enable sort-keys */ export enum GameMapType { World = "World", @@ -103,6 +101,14 @@ export const mapCategories: Record = { GameMapType.Africa, GameMapType.Oceania, ], + + fantasy: [ + GameMapType.Pangaea, + GameMapType.Pluto, + GameMapType.MarsRevised, + GameMapType.Mars, + GameMapType.DeglaciatedAntarctica, + ], regional: [ GameMapType.BlackSea, GameMapType.Britannia, @@ -120,14 +126,6 @@ export const mapCategories: Record = { GameMapType.Italia, GameMapType.Yenisei, ], - // eslint-disable-next-line sort-keys - fantasy: [ - GameMapType.Pangaea, - GameMapType.Pluto, - GameMapType.MarsRevised, - GameMapType.Mars, - GameMapType.DeglaciatedAntarctica, - ], }; export enum GameType { diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index a4d08df29..2851e99b3 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -128,58 +128,56 @@ export class PlayerImpl implements Player { ); const stats = this.mg.stats().getPlayerStats(this); - /* eslint-disable sort-keys */ return { - type: GameUpdateType.Player, - clientID: this.clientID(), - name: this.name(), - displayName: this.displayName(), - id: this.id(), - team: this.team() ?? undefined, - smallID: this.smallID(), - playerType: this.type(), - isAlive: this.isAlive(), - isDisconnected: this.isDisconnected(), - tilesOwned: this.numTilesOwned(), - gold: this._gold, - troops: this.troops(), - allies: this.alliances().map((a) => a.other(this).smallID()), - embargoes: new Set([...this.embargoes.keys()].map((p) => p.toString())), - isTraitor: this.isTraitor(), - targets: this.targets().map((p) => p.smallID()), - outgoingEmojis: this.outgoingEmojis(), - outgoingAttacks: this._outgoingAttacks.map((a) => { - return { - attackerID: a.attacker().smallID(), - targetID: a.target().smallID(), - troops: a.troops(), - id: a.id(), - retreating: a.retreating(), - } satisfies AttackUpdate; - }), - incomingAttacks: this._incomingAttacks.map((a) => { - return { - attackerID: a.attacker().smallID(), - targetID: a.target().smallID(), - troops: a.troops(), - id: a.id(), - retreating: a.retreating(), - } satisfies AttackUpdate; - }), - outgoingAllianceRequests, alliances: this.alliances().map( (a) => ({ - id: a.id(), - other: a.other(this).id(), createdAt: a.createdAt(), expiresAt: a.expiresAt(), + id: a.id(), + other: a.other(this).id(), }) satisfies AllianceView, ), - hasSpawned: this.hasSpawned(), + allies: this.alliances().map((a) => a.other(this).smallID()), betrayals: stats?.betrayals, + clientID: this.clientID(), + displayName: this.displayName(), + embargoes: new Set([...this.embargoes.keys()].map((p) => p.toString())), + gold: this._gold, + hasSpawned: this.hasSpawned(), + id: this.id(), + incomingAttacks: this._incomingAttacks.map((a) => { + return { + attackerID: a.attacker().smallID(), + id: a.id(), + retreating: a.retreating(), + targetID: a.target().smallID(), + troops: a.troops(), + } satisfies AttackUpdate; + }), + isAlive: this.isAlive(), + isDisconnected: this.isDisconnected(), + isTraitor: this.isTraitor(), + name: this.name(), + outgoingAllianceRequests, + outgoingAttacks: this._outgoingAttacks.map((a) => { + return { + attackerID: a.attacker().smallID(), + id: a.id(), + retreating: a.retreating(), + targetID: a.target().smallID(), + troops: a.troops(), + } satisfies AttackUpdate; + }), + outgoingEmojis: this.outgoingEmojis(), + playerType: this.type(), + smallID: this.smallID(), + targets: this.targets().map((p) => p.smallID()), + team: this.team() ?? undefined, + tilesOwned: this.numTilesOwned(), + troops: this.troops(), + type: GameUpdateType.Player, }; - /* eslint-enable sort-keys */ } smallID(): number { @@ -512,8 +510,7 @@ export class PlayerImpl implements Player { } target(other: Player): void { - // eslint-disable-next-line sort-keys - this.targets_.push({ tick: this.mg.ticks(), target: other }); + this.targets_.push({ target: other, tick: this.mg.ticks() }); this.mg.target(this, other); } diff --git a/src/core/game/RailNetworkImpl.ts b/src/core/game/RailNetworkImpl.ts index cb9cd432b..5cb2a300c 100644 --- a/src/core/game/RailNetworkImpl.ts +++ b/src/core/game/RailNetworkImpl.ts @@ -216,8 +216,7 @@ export class RailNetworkImpl implements RailNetwork { const visited = new Set(); const queue: Array<{ station: TrainStation; distance: number }> = [ - // eslint-disable-next-line sort-keys - { station: start, distance: 0 }, + { distance: 0, station: start }, ]; let head = 0; @@ -231,8 +230,7 @@ export class RailNetworkImpl implements RailNetwork { for (const neighbor of station.neighbors()) { if (neighbor === dest) return distance + 1; if (!visited.has(neighbor)) { - // eslint-disable-next-line sort-keys - queue.push({ station: neighbor, distance: distance + 1 }); + queue.push({ distance: distance + 1, station: neighbor }); } } } diff --git a/src/core/game/UnitGrid.ts b/src/core/game/UnitGrid.ts index 103a654b0..0a965eaa0 100644 --- a/src/core/game/UnitGrid.ts +++ b/src/core/game/UnitGrid.ts @@ -159,8 +159,8 @@ export class UnitGrid { if (!unit.isActive()) continue; const distSquared = this.squaredDistanceFromTile(unit, tile); if (distSquared > rangeSquared) continue; - // eslint-disable-next-line sort-keys - const value = { unit, distSquared }; + + const value = { distSquared, unit }; if (predicate !== undefined && !predicate(value)) continue; nearby.push(value); } diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts index 7ce475469..df5819d2e 100644 --- a/src/core/game/UnitImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -114,33 +114,31 @@ export class UnitImpl implements Unit { return this._id; } - /* eslint-disable sort-keys */ toUpdate(): UnitUpdate { return { - type: GameUpdateType.Unit, - unitType: this._type, + constructionType: this._constructionType, + hasTrainStation: this._hasTrainStation, + health: this.hasHealth() ? Number(this._health) : undefined, id: this._id, - troops: this._troops, - ownerID: this._owner.smallID(), - lastOwnerID: this._lastOwner?.smallID(), isActive: this._active, + lastOwnerID: this._lastOwner?.smallID(), + lastPos: this._lastTile, + level: this.level(), + loaded: this._loaded, + missileTimerQueue: this._missileTimerQueue, + ownerID: this._owner.smallID(), + pos: this._tile, reachedTarget: this._reachedTarget, retreating: this._retreating, - pos: this._tile, targetable: this._targetable, - lastPos: this._lastTile, - health: this.hasHealth() ? Number(this._health) : undefined, - constructionType: this._constructionType, - targetUnitId: this._targetUnit?.id() ?? undefined, targetTile: this.targetTile() ?? undefined, - missileTimerQueue: this._missileTimerQueue, - level: this.level(), - hasTrainStation: this._hasTrainStation, + targetUnitId: this._targetUnit?.id() ?? undefined, trainType: this._trainType, - loaded: this._loaded, + troops: this._troops, + type: GameUpdateType.Unit, + unitType: this._type, }; } - /* eslint-enable sort-keys */ type(): UnitType { return this._type; diff --git a/src/core/pathfinding/PathFinding.ts b/src/core/pathfinding/PathFinding.ts index 51efc3570..e788a5985 100644 --- a/src/core/pathfinding/PathFinding.ts +++ b/src/core/pathfinding/PathFinding.ts @@ -148,8 +148,7 @@ export class PathFinder { } if (this.game.manhattanDist(curr, dst) < dist) { - // eslint-disable-next-line sort-keys - return { type: PathFindResultType.Completed, node: curr }; + return { node: curr, type: PathFindResultType.Completed }; } if (this.computeFinished) { @@ -165,8 +164,8 @@ export class PathFinder { if (tile === undefined) { throw new Error("missing tile"); } - // eslint-disable-next-line sort-keys - return { type: PathFindResultType.NextTile, node: tile }; + + return { node: tile, type: PathFindResultType.NextTile }; } } diff --git a/src/core/pathfinding/SerialAStar.ts b/src/core/pathfinding/SerialAStar.ts index e69f111ed..703cca73a 100644 --- a/src/core/pathfinding/SerialAStar.ts +++ b/src/core/pathfinding/SerialAStar.ts @@ -48,18 +48,16 @@ export class SerialAStar implements AStar { this.sources.forEach((startPoint) => { this.fwdGScore.set(startPoint, 0); this.fwdOpenSet.add({ - tile: startPoint, - // eslint-disable-next-line sort-keys fScore: this.heuristic(startPoint, dst), + tile: startPoint, }); }); // Initialize backward search from destination this.bwdGScore.set(dst, 0); this.bwdOpenSet.add({ - tile: dst, - // eslint-disable-next-line sort-keys fScore: this.heuristic(dst, this.findClosestSource(dst)), + tile: dst, }); } @@ -151,8 +149,8 @@ export class SerialAStar implements AStar { const fScore = totalG + this.heuristic(neighbor, isForward ? this.dst : this.closestSource); - // eslint-disable-next-line sort-keys - openSet.add({ tile: neighbor, fScore }); + + openSet.add({ fScore, tile: neighbor }); } } } diff --git a/src/core/validations/username.ts b/src/core/validations/username.ts index 6463b31cd..6e73dd296 100644 --- a/src/core/validations/username.ts +++ b/src/core/validations/username.ts @@ -50,8 +50,7 @@ export function validateUsername(username: string): { error?: string; } { if (typeof username !== "string") { - // eslint-disable-next-line sort-keys - return { isValid: false, error: translateText("username.not_string") }; + return { error: translateText("username.not_string"), isValid: false }; } if (username.length < MIN_USERNAME_LENGTH) { diff --git a/src/server/Archive.ts b/src/server/Archive.ts index d6ebfae85..ecc4f958b 100644 --- a/src/server/Archive.ts +++ b/src/server/Archive.ts @@ -10,14 +10,13 @@ const log = logger.child({ component: "Archive" }); // R2 client configuration const r2 = new S3({ - region: "auto", // R2 ignores region, but it's required by the SDK - /* eslint-disable sort-keys */ - endpoint: config.r2Endpoint(), credentials: { accessKeyId: config.r2AccessKey(), secretAccessKey: config.r2SecretKey(), }, - /* eslint-disable sort-keys */ + + endpoint: config.r2Endpoint(), + region: "auto", // R2 ignores region, but it's required by the SDK }); const bucket = config.r2Bucket(); @@ -49,8 +48,8 @@ export async function archive(gameRecord: GameRecord) { const { message, stack, name } = error; log.error(`${gameRecord.info.gameID}: Final archive error: ${error}`, { message, - stack, name, + stack, ...(error && typeof error === "object" ? error : {}), }); } @@ -60,11 +59,11 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) { // Create analytics data object const { info, version, gitCommit, subdomain, domain } = gameRecord; const analyticsData: AnalyticsRecord = { - info, - version, - gitCommit, - subdomain, domain, + gitCommit, + info, + subdomain, + version, }; try { @@ -72,10 +71,10 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) { const analyticsKey = `${info.gameID}.json`; await r2.putObject({ - Bucket: bucket, - Key: `${analyticsFolder}/${analyticsKey}`, Body: JSON.stringify(analyticsData, replacer), + Bucket: bucket, ContentType: "application/json", + Key: `${analyticsFolder}/${analyticsKey}`, }); log.info(`${info.gameID}: successfully wrote game analytics to R2`); @@ -91,8 +90,8 @@ async function archiveAnalyticsToR2(gameRecord: GameRecord) { const { message, stack, name } = error; log.error(`${info.gameID}: Error writing game analytics to R2: ${error}`, { message, - stack, name, + stack, ...(error && typeof error === "object" ? error : {}), }); throw error; @@ -110,10 +109,10 @@ async function archiveFullGameToR2(gameRecord: GameRecord) { try { await r2.putObject({ - Bucket: bucket, - Key: `${gameFolder}/${recordCopy.info.gameID}`, Body: JSON.stringify(recordCopy, replacer), + Bucket: bucket, ContentType: "application/json", + Key: `${gameFolder}/${recordCopy.info.gameID}`, }); } catch (error) { log.error(`error saving game ${gameRecord.info.gameID}`); @@ -148,8 +147,8 @@ export async function readGameRecord( // Log the error for monitoring purposes log.error(`${gameId}: Error reading game record from R2: ${error}`, { message, - stack, name, + stack, ...(error && typeof error === "object" ? error : {}), }); @@ -179,8 +178,8 @@ export async function gameRecordExists(gameId: GameID): Promise { } log.error(`${gameId}: Error checking archive existence: ${error}`, { message, - stack, name, + stack, ...(error && typeof error === "object" ? error : {}), }); return false; diff --git a/src/server/GameManager.ts b/src/server/GameManager.ts index a71d859ef..f9f941ef1 100644 --- a/src/server/GameManager.ts +++ b/src/server/GameManager.ts @@ -41,8 +41,8 @@ export class GameManager { { bots: 400, difficulty: Difficulty.Medium, - disableNPCs: false, disabledUnits: [], + disableNPCs: false, donateGold: false, donateTroops: false, gameMap: GameMapType.World, diff --git a/src/server/Logger.ts b/src/server/Logger.ts index 39fa6034c..5a4de59a7 100644 --- a/src/server/Logger.ts +++ b/src/server/Logger.ts @@ -29,9 +29,8 @@ if (config.otelEnabled()) { // Add OTLP exporter for logs const logExporter = new OTLPLogExporter({ - url: `${config.otelEndpoint()}/v1/logs`, - // eslint-disable-next-line sort-keys headers, + url: `${config.otelEndpoint()}/v1/logs`, }); // Add a log processor with the exporter @@ -57,18 +56,18 @@ const addSeverityFormat = winston.format((info) => { // Define your base/parent logger const logger = winston.createLogger({ - level: "info", - /* eslint-disable sort-keys */ + defaultMeta: { + environment: process.env.GAME_ENV ?? "prod", + service: "openfront", + }, + format: winston.format.combine( winston.format.timestamp(), addSeverityFormat(), winston.format.json(), ), - defaultMeta: { - service: "openfront", - environment: process.env.GAME_ENV ?? "prod", - }, - /* eslint-enable sort-keys */ + level: "info", + transports: [ new winston.transports.Console(), new OpenTelemetryTransportV3(), diff --git a/src/server/MapPlaylist.ts b/src/server/MapPlaylist.ts index 80baee9e3..66538895d 100644 --- a/src/server/MapPlaylist.ts +++ b/src/server/MapPlaylist.ts @@ -79,8 +79,8 @@ export class MapPlaylist { return { bots: 400, difficulty: Difficulty.Medium, - disableNPCs: mode === GameMode.Team, disabledUnits: [], + disableNPCs: mode === GameMode.Team, donateGold: true, donateTroops: true, gameMap: map, diff --git a/src/server/OtelResource.ts b/src/server/OtelResource.ts index 7bb93bfa8..6d48fb442 100644 --- a/src/server/OtelResource.ts +++ b/src/server/OtelResource.ts @@ -17,15 +17,14 @@ export function getOtelResource() { export function getPromLabels() { return { - "service.instance.id": process.env.HOSTNAME, - /* eslint-disable sort-keys */ - "openfront.environment": config.env(), - "openfront.host": process.env.HOST, - "openfront.domain": process.env.DOMAIN, - "openfront.subdomain": process.env.SUBDOMAIN, "openfront.component": process.env.WORKER_ID ? "Worker " + process.env.WORKER_ID : "Master", - /* eslint-enable sort-keys */ + "openfront.domain": process.env.DOMAIN, + + "openfront.environment": config.env(), + "openfront.host": process.env.HOST, + "openfront.subdomain": process.env.SUBDOMAIN, + "service.instance.id": process.env.HOSTNAME, }; } diff --git a/src/server/WorkerMetrics.ts b/src/server/WorkerMetrics.ts index 2539546bf..4af92f551 100644 --- a/src/server/WorkerMetrics.ts +++ b/src/server/WorkerMetrics.ts @@ -31,8 +31,8 @@ export function initWorkerMetrics(gameManager: GameManager): void { // Configure the metric reader const metricReader = new PeriodicExportingMetricReader({ - exportIntervalMillis: 15000, // Export metrics every 15 seconds exporter: metricExporter, + exportIntervalMillis: 15000, // Export metrics every 15 seconds }); // Create a meter provider diff --git a/src/server/jwt.ts b/src/server/jwt.ts index 98ebb518f..a1ea941d5 100644 --- a/src/server/jwt.ts +++ b/src/server/jwt.ts @@ -21,8 +21,7 @@ export async function verifyClientToken( config: ServerConfig, ): Promise { if (PersistentIdSchema.safeParse(token).success) { - // eslint-disable-next-line sort-keys - return { persistentId: token, claims: null }; + return { claims: null, persistentId: token }; } try { const issuer = config.jwtIssuer(); diff --git a/tests/AllianceExtensionExecution.test.ts b/tests/AllianceExtensionExecution.test.ts index 6ae6340ed..35fc3fe82 100644 --- a/tests/AllianceExtensionExecution.test.ts +++ b/tests/AllianceExtensionExecution.test.ts @@ -15,8 +15,8 @@ describe("AllianceExtensionExecution", () => { "ocean_and_land", { infiniteGold: true, - instantBuild: true, infiniteTroops: true, + instantBuild: true, }, [ playerInfo("player1", PlayerType.Human), diff --git a/tests/Attack.test.ts b/tests/Attack.test.ts index d5ff1e6a0..4c83f5717 100644 --- a/tests/Attack.test.ts +++ b/tests/Attack.test.ts @@ -29,8 +29,8 @@ describe("Attack", () => { beforeEach(async () => { game = await setup("ocean_and_land", { infiniteGold: true, - instantBuild: true, infiniteTroops: true, + instantBuild: true, }); const attackerInfo = new PlayerInfo( "attacker dude", @@ -130,8 +130,8 @@ describe("Attack race condition with alliance requests", () => { beforeEach(async () => { game = await setup("ocean_and_land", { infiniteGold: true, - instantBuild: true, infiniteTroops: true, + instantBuild: true, }); const playerAInfo = new PlayerInfo( diff --git a/tests/BotBehavior.test.ts b/tests/BotBehavior.test.ts index 71b14ac0b..701b66958 100644 --- a/tests/BotBehavior.test.ts +++ b/tests/BotBehavior.test.ts @@ -77,11 +77,11 @@ describe("BotBehavior.handleAllianceRequests", () => { .mockReturnValue(new Array(alliancesCount)); const mockRequest = { - requestor: () => requestor, - recipient: () => player, - createdAt: () => 0 as unknown as Tick, accept: jest.fn(), + createdAt: () => 0 as unknown as Tick, + recipient: () => player, reject: jest.fn(), + requestor: () => requestor, } as unknown as AllianceRequest; jest @@ -120,8 +120,8 @@ describe("BotBehavior.handleAllianceRequests", () => { test("should accept alliance if requestor is much larger (> 3 times size of recipient) and has too many alliances (>= 3)", () => { const request = setupAllianceRequest({ - numTilesRequestor: 40, alliancesCount: 4, + numTilesRequestor: 40, }); botBehavior.handleAllianceRequests(); @@ -132,8 +132,8 @@ describe("BotBehavior.handleAllianceRequests", () => { test("should accept alliance if requestor is much larger (> 3 times size of recipient) and does not have too many alliances (< 3)", () => { const request = setupAllianceRequest({ - numTilesRequestor: 40, alliancesCount: 2, + numTilesRequestor: 40, }); botBehavior.handleAllianceRequests(); @@ -171,8 +171,8 @@ describe("BotBehavior.handleAllianceExtensionRequests", () => { mockPlayer = { alliances: jest.fn(() => [mockAlliance]), - relation: jest.fn(), id: jest.fn(() => "bot_id"), + relation: jest.fn(), type: jest.fn(() => PlayerType.FakeHuman), }; diff --git a/tests/Censor.test.ts b/tests/Censor.test.ts index 1e7067fc3..165c74765 100644 --- a/tests/Censor.test.ts +++ b/tests/Censor.test.ts @@ -1,6 +1,9 @@ // Mocking the obscenity library to control its behavior in tests. jest.mock("obscenity", () => { return { + collapseDuplicatesTransformer: () => ({}), + englishDataset: { build: () => ({}) }, + englishRecommendedTransformers: {}, RegExpMatcher: class { private readonly dummy: string[] = ["foo", "bar", "leet", "code"]; constructor(_opts: any) {} @@ -16,9 +19,6 @@ jest.mock("obscenity", () => { return this.dummy.some((token) => decoded.includes(token)); } }, - collapseDuplicatesTransformer: () => ({}), - englishRecommendedTransformers: {}, - englishDataset: { build: () => ({}) }, resolveConfusablesTransformer: () => ({}), resolveLeetSpeakTransformer: () => ({}), skipNonAlphabeticTransformer: () => ({}), @@ -53,14 +53,14 @@ describe("username.ts functions", () => { describe("isProfaneUsername & fixProfaneUsername with leet decoding (mocked)", () => { test.each([ - { username: "l33t", profane: true }, // decodes to "leet" - { username: "L33T", profane: true }, - { username: "l33tc0de", profane: true }, // decodes to "leetcode", contains "leet" and "code" - { username: "L33TC0DE", profane: true }, - { username: "foo123", profane: true }, // contains "foo" - { username: "b4r", profane: true }, // decodes to "bar" - { username: "safeName", profane: false }, - { username: "s4f3", profane: false }, // decodes to "safe" but "safe" not in dummy list + { profane: true, username: "l33t" }, // decodes to "leet" + { profane: true, username: "L33T" }, + { profane: true, username: "l33tc0de" }, // decodes to "leetcode", contains "leet" and "code" + { profane: true, username: "L33TC0DE" }, + { profane: true, username: "foo123" }, // contains "foo" + { profane: true, username: "b4r" }, // decodes to "bar" + { profane: false, username: "safeName" }, + { profane: false, username: "s4f3" }, // decodes to "safe" but "safe" not in dummy list ])('isProfaneUsername("%s") → %s', ({ username, profane }) => { expect(isProfaneUsername(username)).toBe(profane); }); @@ -113,17 +113,17 @@ describe("username.ts functions", () => { describe("sanitizeUsername", () => { test.each([ - { input: "GoodName", expected: "GoodName" }, - { input: "a!", expected: "axx" }, - { input: "a$%b", expected: "abx" }, + { expected: "GoodName", input: "GoodName" }, + { expected: "axx", input: "a!" }, + { expected: "abx", input: "a$%b" }, { - input: "abc".repeat(10), expected: "abc" .repeat(Math.floor(MAX_USERNAME_LENGTH / 3)) .slice(0, MAX_USERNAME_LENGTH), + input: "abc".repeat(10), }, - { input: "", expected: "xxx" }, - { input: "Ünicode🐈Test!", expected: "Ünicode🐈Test" }, + { expected: "xxx", input: "" }, + { expected: "Ünicode🐈Test", input: "Ünicode🐈Test!" }, ])('sanitizeUsername("%s") → "%s"', ({ input, expected }) => { const out = sanitizeUsername(input); expect(out).toBe(expected); diff --git a/tests/Colors.test.ts b/tests/Colors.test.ts index c702d19c0..762eea9c9 100644 --- a/tests/Colors.test.ts +++ b/tests/Colors.test.ts @@ -16,14 +16,14 @@ import { import { ColoredTeams } from "../src/core/game/Game"; const mockColors: Colord[] = [ - colord({ r: 255, g: 0, b: 0 }), - colord({ r: 0, g: 255, b: 0 }), - colord({ r: 0, g: 0, b: 255 }), + colord({ b: 0, g: 0, r: 255 }), + colord({ b: 0, g: 255, r: 0 }), + colord({ b: 255, g: 0, r: 0 }), ]; const fallbackMockColors: Colord[] = [ - colord({ r: 0, g: 0, b: 0 }), - colord({ r: 255, g: 255, b: 255 }), + colord({ b: 0, g: 0, r: 0 }), + colord({ b: 255, g: 255, r: 255 }), ]; const fallbackColors = [...fallbackMockColors, ...mockColors]; @@ -148,19 +148,19 @@ describe("ColorAllocator", () => { describe("selectDistinctColor", () => { test("returns the most distant color", () => { - const assignedColors = [colord({ r: 255, g: 0, b: 0 })]; // bright red + const assignedColors = [colord({ b: 0, g: 0, r: 255 })]; // bright red const availableColors = [ - colord({ r: 254, g: 1, b: 1 }), // too close - colord({ r: 0, g: 255, b: 0 }), // distinct green - colord({ r: 0, g: 0, b: 255 }), // distinct blue + colord({ b: 1, g: 1, r: 254 }), // too close + colord({ b: 0, g: 255, r: 0 }), // distinct green + colord({ b: 255, g: 0, r: 0 }), // distinct blue ]; const result = selectDistinctColorIndex(availableColors, assignedColors); expect(result).not.toBeNull(); const rgb = availableColors[result!].toRgb(); expect([ - { r: 0, g: 255, b: 0, a: 1 }, - { r: 0, g: 0, b: 255, a: 1 }, + { a: 1, b: 0, g: 255, r: 0 }, + { a: 1, b: 255, g: 0, r: 0 }, ]).toContainEqual(rgb); }); }); diff --git a/tests/DeleteUnitExecution.test.ts b/tests/DeleteUnitExecution.test.ts index c8486a1fe..f2ad5cc55 100644 --- a/tests/DeleteUnitExecution.test.ts +++ b/tests/DeleteUnitExecution.test.ts @@ -20,8 +20,8 @@ describe("DeleteUnitExecution Security Tests", () => { beforeEach(async () => { game = await setup("plains", { infiniteGold: true, - instantBuild: true, infiniteTroops: true, + instantBuild: true, }); const player1Info = new PlayerInfo( diff --git a/tests/Donate.test.ts b/tests/Donate.test.ts index bbbccd4f9..6634b564d 100644 --- a/tests/Donate.test.ts +++ b/tests/Donate.test.ts @@ -7,8 +7,8 @@ import { setup } from "./util/Setup"; describe("Donate troops to an ally", () => { it("Troops should be successfully donated", async () => { const game = await setup("ocean_and_land", { - infiniteTroops: false, donateTroops: true, + infiniteTroops: false, }); const donorInfo = new PlayerInfo( @@ -70,8 +70,8 @@ describe("Donate troops to an ally", () => { describe("Donate gold to an ally", () => { it("Gold should be successfully donated", async () => { const game = await setup("ocean_and_land", { - infiniteGold: false, donateGold: true, + infiniteGold: false, }); const donorInfo = new PlayerInfo( @@ -134,8 +134,8 @@ describe("Donate gold to an ally", () => { describe("Donate troops to a non ally", () => { it("Troops should not be donated", async () => { const game = await setup("ocean_and_land", { - infiniteTroops: false, donateTroops: true, + infiniteTroops: false, }); const donorInfo = new PlayerInfo( @@ -194,8 +194,8 @@ describe("Donate troops to a non ally", () => { describe("Donate Gold to a non ally", () => { it("Gold should not be donated", async () => { const game = await setup("ocean_and_land", { - infiniteGold: false, donateGold: true, + infiniteGold: false, }); const donorInfo = new PlayerInfo( diff --git a/tests/client/graphics/RadialMenuElements.test.ts b/tests/client/graphics/RadialMenuElements.test.ts index df8c796d4..2fc297d33 100644 --- a/tests/client/graphics/RadialMenuElements.test.ts +++ b/tests/client/graphics/RadialMenuElements.test.ts @@ -14,8 +14,8 @@ import { TileRef } from "../../../src/core/game/GameMap"; import { GameView, PlayerView } from "../../../src/core/game/GameView"; jest.mock("../../../src/client/Utils", () => ({ - translateText: jest.fn((key: string) => key), renderNumber: jest.fn((num: number) => num.toString()), + translateText: jest.fn((key: string) => key), })); jest.mock("../../../src/client/graphics/layers/BuildMenu", () => { @@ -23,46 +23,46 @@ jest.mock("../../../src/client/graphics/layers/BuildMenu", () => { return { flattenedBuildTable: [ { - unitType: UnitType.City, - key: "unit_type.city", + countable: true, description: "unit_type.city_desc", icon: "city-icon", - countable: true, + key: "unit_type.city", + unitType: UnitType.City, }, { - unitType: UnitType.Factory, - key: "unit_type.factory", + countable: true, description: "unit_type.factory_desc", icon: "factory-icon", - countable: true, + key: "unit_type.factory", + unitType: UnitType.Factory, }, { - unitType: UnitType.AtomBomb, - key: "unit_type.atom_bomb", + countable: false, description: "unit_type.atom_bomb_desc", icon: "atom-bomb-icon", - countable: false, + key: "unit_type.atom_bomb", + unitType: UnitType.AtomBomb, }, { - unitType: UnitType.Warship, - key: "unit_type.warship", + countable: true, description: "unit_type.warship_desc", icon: "warship-icon", - countable: true, + key: "unit_type.warship", + unitType: UnitType.Warship, }, { - unitType: UnitType.HydrogenBomb, - key: "unit_type.hydrogen_bomb", + countable: false, description: "unit_type.hydrogen_bomb_desc", icon: "hydrogen-bomb-icon", - countable: false, + key: "unit_type.hydrogen_bomb", + unitType: UnitType.HydrogenBomb, }, { - unitType: UnitType.MIRV, - key: "unit_type.mirv", + countable: false, description: "unit_type.mirv_desc", icon: "mirv-icon", - countable: false, + key: "unit_type.mirv", + unitType: UnitType.MIRV, }, ], }; @@ -95,17 +95,17 @@ describe("RadialMenuElements", () => { } as unknown as PlayerView; mockGame = { - inSpawnPhase: jest.fn(() => false), - owner: jest.fn(() => mockPlayer), - isLand: jest.fn(() => true), config: jest.fn(() => ({ + isUnitDisabled: jest.fn(() => false), theme: () => ({ territoryColor: () => ({ lighten: () => ({ alpha: () => ({ toRgbString: () => "#fff" }) }), }), }), - isUnitDisabled: jest.fn(() => false), })), + inSpawnPhase: jest.fn(() => false), + isLand: jest.fn(() => true), + owner: jest.fn(() => mockPlayer), } as unknown as GameView; mockBuildMenu = { @@ -117,38 +117,38 @@ describe("RadialMenuElements", () => { mockPlayerActions = { buildableUnits: [ - { type: UnitType.City, canBuild: true }, - { type: UnitType.Factory, canBuild: true }, - { type: UnitType.AtomBomb, canBuild: true }, - { type: UnitType.Warship, canBuild: true }, - { type: UnitType.HydrogenBomb, canBuild: true }, - { type: UnitType.MIRV, canBuild: true }, - { type: UnitType.TransportShip, canBuild: true }, + { canBuild: true, type: UnitType.City }, + { canBuild: true, type: UnitType.Factory }, + { canBuild: true, type: UnitType.AtomBomb }, + { canBuild: true, type: UnitType.Warship }, + { canBuild: true, type: UnitType.HydrogenBomb }, + { canBuild: true, type: UnitType.MIRV }, + { canBuild: true, type: UnitType.TransportShip }, ], canAttack: true, interaction: { - canSendAllianceRequest: true, canBreakAlliance: false, - canDonateTroops: true, canDonateGold: true, + canDonateTroops: true, + canSendAllianceRequest: true, }, }; mockTile = {} as TileRef; mockParams = { + buildMenu: mockBuildMenu, + chatIntegration: {} as any, + closeMenu: jest.fn(), + emojiTable: {} as any, + eventBus: {} as any, + game: mockGame, myPlayer: mockPlayer, + playerActionHandler: {} as any, + playerActions: mockPlayerActions, + playerPanel: {} as any, selected: mockPlayer, tile: mockTile, - playerActions: mockPlayerActions, - game: mockGame, - buildMenu: mockBuildMenu, - emojiTable: {} as any, - playerActionHandler: {} as any, - playerPanel: {} as any, - chatIntegration: {} as any, - eventBus: {} as any, - closeMenu: jest.fn(), }; }); diff --git a/tests/client/graphics/UILayer.test.ts b/tests/client/graphics/UILayer.test.ts index 6a25048a5..81b5ec98c 100644 --- a/tests/client/graphics/UILayer.test.ts +++ b/tests/client/graphics/UILayer.test.ts @@ -11,8 +11,6 @@ describe("UILayer", () => { beforeEach(() => { game = { - width: () => 100, - height: () => 100, config: () => ({ theme: () => ({ territoryColor: () => ({ @@ -20,12 +18,14 @@ describe("UILayer", () => { }), }), }), - x: () => 10, - y: () => 10, - unitInfo: () => ({ maxHealth: 10, constructionDuration: 5 }), + height: () => 100, myPlayer: () => ({ id: () => 1 }), ticks: () => 1, + unitInfo: () => ({ constructionDuration: 5, maxHealth: 10 }), updatesSinceLastTick: () => undefined, + width: () => 100, + x: () => 10, + y: () => 10, }; eventBus = { on: jest.fn() }; }); @@ -46,10 +46,10 @@ describe("UILayer", () => { const ui = new UILayer(game, eventBus); ui.redraw(); const unit = { - type: () => "Warship", isActive: () => true, - tile: () => ({}), owner: () => ({}), + tile: () => ({}), + type: () => "Warship", }; const event = { isSelected: true, unit }; ui.drawSelectionBox = jest.fn(); @@ -61,13 +61,13 @@ describe("UILayer", () => { const ui = new UILayer(game, eventBus); ui.redraw(); const unit = { - id: () => 1, - type: () => "Warship", - health: () => 5, - tile: () => ({}), - owner: () => ({}), - isActive: () => true, createdAt: () => 1, + health: () => 5, + id: () => 1, + isActive: () => true, + owner: () => ({}), + tile: () => ({}), + type: () => "Warship", } as unknown as UnitView; ui.drawHealthBar(unit); expect(ui["allHealthBars"].has(1)).toBe(true); @@ -90,12 +90,12 @@ describe("UILayer", () => { const ui = new UILayer(game, eventBus); ui.redraw(); const unit = { - id: () => 1, - type: () => "Warship", health: () => 5, - tile: () => ({}), - owner: () => ({}), + id: () => 1, isActive: () => true, + owner: () => ({}), + tile: () => ({}), + type: () => "Warship", } as unknown as UnitView; ui.drawHealthBar(unit); expect(ui["allHealthBars"].has(1)).toBe(true); @@ -111,8 +111,8 @@ describe("UILayer", () => { ui.redraw(); const unit = { id: () => 2, - tile: () => ({}), isActive: () => true, + tile: () => ({}), } as unknown as UnitView; ui.createLoadingBar(unit); expect(ui["allProgressBars"].has(2)).toBe(true); @@ -122,12 +122,12 @@ describe("UILayer", () => { const ui = new UILayer(game, eventBus); ui.redraw(); const unit = { - id: () => 2, - type: () => "Construction", constructionType: () => "City", + id: () => 2, + isActive: () => true, owner: () => ({ id: () => 1 }), tile: () => ({}), - isActive: () => true, + type: () => "Construction", } as unknown as UnitView; ui.onUnitEvent(unit); expect(ui["allProgressBars"].has(2)).toBe(true); @@ -142,13 +142,13 @@ describe("UILayer", () => { const ui = new UILayer(game, eventBus); ui.redraw(); const unit = { - id: () => 2, - type: () => "Construction", constructionType: () => "City", + createdAt: () => 1, + id: () => 2, + isActive: () => true, owner: () => ({ id: () => 1 }), tile: () => ({}), - isActive: () => true, - createdAt: () => 1, + type: () => "Construction", } as unknown as UnitView; ui.onUnitEvent(unit); expect(ui["allProgressBars"].has(2)).toBe(true); diff --git a/tests/core/executions/SAMLauncherExecution.test.ts b/tests/core/executions/SAMLauncherExecution.test.ts index c4f5ad557..41822bc98 100644 --- a/tests/core/executions/SAMLauncherExecution.test.ts +++ b/tests/core/executions/SAMLauncherExecution.test.ts @@ -86,9 +86,9 @@ describe("SAM", () => { const nuke = attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 1), { targetTile: game.ref(3, 1), trajectory: [ - { tile: game.ref(1, 1), targetable: true }, - { tile: game.ref(2, 1), targetable: true }, - { tile: game.ref(3, 1), targetable: true }, + { targetable: true, tile: game.ref(1, 1) }, + { targetable: true, tile: game.ref(2, 1) }, + { targetable: true, tile: game.ref(3, 1) }, ], }); executeTicks(game, 3); @@ -102,17 +102,17 @@ describe("SAM", () => { attacker.buildUnit(UnitType.AtomBomb, game.ref(2, 1), { targetTile: game.ref(3, 1), trajectory: [ - { tile: game.ref(1, 1), targetable: true }, - { tile: game.ref(2, 1), targetable: true }, - { tile: game.ref(3, 1), targetable: true }, + { targetable: true, tile: game.ref(1, 1) }, + { targetable: true, tile: game.ref(2, 1) }, + { targetable: true, tile: game.ref(3, 1) }, ], }); attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 2), { targetTile: game.ref(1, 3), trajectory: [ - { tile: game.ref(1, 1), targetable: true }, - { tile: game.ref(1, 2), targetable: true }, - { tile: game.ref(1, 3), targetable: true }, + { targetable: true, tile: game.ref(1, 1) }, + { targetable: true, tile: game.ref(1, 2) }, + { targetable: true, tile: game.ref(1, 3) }, ], }); expect(attacker.units(UnitType.AtomBomb)).toHaveLength(2); @@ -130,9 +130,9 @@ describe("SAM", () => { const nuke = attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 1), { targetTile: game.ref(1, 3), trajectory: [ - { tile: game.ref(1, 1), targetable: true }, - { tile: game.ref(2, 1), targetable: true }, - { tile: game.ref(3, 1), targetable: true }, + { targetable: true, tile: game.ref(1, 1) }, + { targetable: true, tile: game.ref(2, 1) }, + { targetable: true, tile: game.ref(3, 1) }, ], }); @@ -158,9 +158,9 @@ describe("SAM", () => { const nuke = attacker.buildUnit(UnitType.AtomBomb, game.ref(1, 1), { targetTile: game.ref(1, 3), trajectory: [ - { tile: game.ref(1, 1), targetable: true }, - { tile: game.ref(1, 2), targetable: true }, - { tile: game.ref(1, 3), targetable: true }, + { targetable: true, tile: game.ref(1, 1) }, + { targetable: true, tile: game.ref(1, 2) }, + { targetable: true, tile: game.ref(1, 3) }, ], }); diff --git a/tests/core/executions/TradeShipExecution.test.ts b/tests/core/executions/TradeShipExecution.test.ts index 0aab3fbce..c23443dc3 100644 --- a/tests/core/executions/TradeShipExecution.test.ts +++ b/tests/core/executions/TradeShipExecution.test.ts @@ -22,66 +22,66 @@ describe("TradeShipExecution", () => { }); game.displayMessage = jest.fn(); origOwner = { - canBuild: jest.fn(() => true), - buildUnit: jest.fn((type, spawn, opts) => tradeShip), - displayName: jest.fn(() => "Origin"), addGold: jest.fn(), - units: jest.fn(() => [dstPort]), - unitCount: jest.fn(() => 1), - id: jest.fn(() => 1), + buildUnit: jest.fn((type, spawn, opts) => tradeShip), + canBuild: jest.fn(() => true), canTrade: jest.fn(() => true), + displayName: jest.fn(() => "Origin"), + id: jest.fn(() => 1), + unitCount: jest.fn(() => 1), + units: jest.fn(() => [dstPort]), } as any; dstOwner = { - id: jest.fn(() => 2), addGold: jest.fn(), - displayName: jest.fn(() => "Destination"), - units: jest.fn(() => [dstPort]), - unitCount: jest.fn(() => 1), canTrade: jest.fn(() => true), + displayName: jest.fn(() => "Destination"), + id: jest.fn(() => 2), + unitCount: jest.fn(() => 1), + units: jest.fn(() => [dstPort]), } as any; pirate = { - id: jest.fn(() => 3), addGold: jest.fn(), - displayName: jest.fn(() => "Destination"), - units: jest.fn(() => [piratePort]), - unitCount: jest.fn(() => 1), canTrade: jest.fn(() => true), + displayName: jest.fn(() => "Destination"), + id: jest.fn(() => 3), + unitCount: jest.fn(() => 1), + units: jest.fn(() => [piratePort]), } as any; piratePort = { - tile: jest.fn(() => 40011), - owner: jest.fn(() => pirate), isActive: jest.fn(() => true), + owner: jest.fn(() => pirate), + tile: jest.fn(() => 40011), } as any; srcPort = { - tile: jest.fn(() => 20011), - owner: jest.fn(() => origOwner), isActive: jest.fn(() => true), + owner: jest.fn(() => origOwner), + tile: jest.fn(() => 20011), } as any; dstPort = { - tile: jest.fn(() => 30015), // 15x15 - owner: jest.fn(() => dstOwner), isActive: jest.fn(() => true), + owner: jest.fn(() => dstOwner), + tile: jest.fn(() => 30015), // 15x15 } as any; tradeShip = { - isActive: jest.fn(() => true), - owner: jest.fn(() => origOwner), - move: jest.fn(), - setTargetUnit: jest.fn(), - setSafeFromPirates: jest.fn(), delete: jest.fn(), + isActive: jest.fn(() => true), + move: jest.fn(), + owner: jest.fn(() => origOwner), + setSafeFromPirates: jest.fn(), + setTargetUnit: jest.fn(), tile: jest.fn(() => 2001), } as any; tradeShipExecution = new TradeShipExecution(origOwner, srcPort, dstPort); tradeShipExecution.init(game, 0); tradeShipExecution["pathFinder"] = { - nextTile: jest.fn(() => ({ type: 0, node: 2001 })), + nextTile: jest.fn(() => ({ node: 2001, type: 0 })), } as any; tradeShipExecution["tradeShip"] = tradeShip; }); @@ -112,7 +112,7 @@ describe("TradeShipExecution", () => { it("should complete trade and award gold", () => { tradeShipExecution["pathFinder"] = { - nextTile: jest.fn(() => ({ type: 2, node: 2001 })), + nextTile: jest.fn(() => ({ node: 2001, type: 2 })), } as any; tradeShipExecution.tick(1); expect(tradeShip.delete).toHaveBeenCalledWith(false); diff --git a/tests/core/game/Cluster.test.ts b/tests/core/game/Cluster.test.ts index 95758f1fc..1cb36dd19 100644 --- a/tests/core/game/Cluster.test.ts +++ b/tests/core/game/Cluster.test.ts @@ -2,9 +2,9 @@ import { Cluster, TrainStation } from "../../../src/core/game/TrainStation"; const createMockStation = (id: string): jest.Mocked => { return { + getCluster: jest.fn(() => null), id, setCluster: jest.fn(), - getCluster: jest.fn(() => null), } as any; }; diff --git a/tests/core/game/GameImpl.test.ts b/tests/core/game/GameImpl.test.ts index aabcf5c0f..20f9c253c 100644 --- a/tests/core/game/GameImpl.test.ts +++ b/tests/core/game/GameImpl.test.ts @@ -21,8 +21,8 @@ describe("GameImpl", () => { beforeEach(async () => { game = await setup("ocean_and_land", { infiniteGold: true, - instantBuild: true, infiniteTroops: true, + instantBuild: true, }); const attackerInfo = new PlayerInfo( "attacker dude", diff --git a/tests/core/game/RailNetwork.test.ts b/tests/core/game/RailNetwork.test.ts index f900552ef..a25355965 100644 --- a/tests/core/game/RailNetwork.test.ts +++ b/tests/core/game/RailNetwork.test.ts @@ -11,17 +11,17 @@ const createMockStation = (unitId: number): any => { const cluster = new Cluster(); const railroads = new Set(); return { + addRailroad: jest.fn(), + clearRailroads: jest.fn(), + getCluster: jest.fn(() => cluster), + getRailroads: jest.fn(() => railroads), + neighbors: jest.fn(() => []), + setCluster: jest.fn(), + tile: jest.fn(), unit: { id: unitId, setTrainStation: jest.fn(), }, - tile: jest.fn(), - neighbors: jest.fn(() => []), - getCluster: jest.fn(() => cluster), - setCluster: jest.fn(), - addRailroad: jest.fn(), - getRailroads: jest.fn(() => railroads), - clearRailroads: jest.fn(), }; }; @@ -55,22 +55,22 @@ describe("RailNetworkImpl", () => { beforeEach(() => { stationManager = { addStation: jest.fn(), - removeStation: jest.fn(), findStation: jest.fn(), getAll: jest.fn(() => new Set()), + removeStation: jest.fn(), }; pathService = { - findTilePath: jest.fn(() => [0]), findStationsPath: jest.fn(() => [0]), + findTilePath: jest.fn(() => [0]), }; game = { - nearbyUnits: jest.fn(() => []), addExecution: jest.fn(), config: () => ({ + railroadMaxSize: () => 100, trainStationMaxRange: () => 80, trainStationMinRange: () => 10, - railroadMaxSize: () => 100, }), + nearbyUnits: jest.fn(() => []), }; network = new RailNetworkImpl(game, stationManager, pathService); @@ -153,7 +153,7 @@ describe("RailNetworkImpl", () => { neighborStation.getCluster = jest.fn(() => cluster); cluster.has = jest.fn(() => false); - const neighborUnit = { unit: neighborStation.unit, distSquared: 20 }; + const neighborUnit = { distSquared: 20, unit: neighborStation.unit }; game.nearbyUnits.mockReturnValue([neighborUnit]); stationManager.findStation.mockReturnValue(neighborStation); diff --git a/tests/core/game/TrainStation.test.ts b/tests/core/game/TrainStation.test.ts index b0ed06165..549d7e2f2 100644 --- a/tests/core/game/TrainStation.test.ts +++ b/tests/core/game/TrainStation.test.ts @@ -14,34 +14,34 @@ describe("TrainStation", () => { beforeEach(() => { game = { - ticks: jest.fn().mockReturnValue(123), + addExecution: jest.fn(), + addUpdate: jest.fn(), config: jest.fn().mockReturnValue({ trainGold: (isFriendly: boolean) => isFriendly ? BigInt(1000) : BigInt(500), }), - addUpdate: jest.fn(), - addExecution: jest.fn(), + ticks: jest.fn().mockReturnValue(123), } as any; player = { addGold: jest.fn(), - id: 1, canTrade: jest.fn().mockReturnValue(true), + id: 1, isFriendly: jest.fn().mockReturnValue(false), } as any; unit = { - owner: jest.fn().mockReturnValue(player), + isActive: jest.fn().mockReturnValue(true), level: jest.fn().mockReturnValue(1), + owner: jest.fn().mockReturnValue(player), tile: jest.fn().mockReturnValue({ x: 0, y: 0 }), type: jest.fn(), - isActive: jest.fn().mockReturnValue(true), } as any; trainExecution = { + level: jest.fn(), loadCargo: jest.fn(), owner: jest.fn().mockReturnValue(player), - level: jest.fn(), } as any; }); @@ -82,7 +82,7 @@ describe("TrainStation", () => { it("adds and retrieves neighbors", () => { const stationA = new TrainStation(game, unit); const stationB = new TrainStation(game, unit); - const railRoad = { from: stationA, to: stationB, tiles: [] } as any; + const railRoad = { from: stationA, tiles: [], to: stationB } as any; stationA.addRailroad(railRoad); @@ -96,8 +96,8 @@ describe("TrainStation", () => { const railRoad = { from: stationA, - to: stationB, tiles: [{ x: 1, y: 1 }], + to: stationB, } as any; stationA.addRailroad(railRoad); diff --git a/tests/server/Privilege.customFlag.test.ts b/tests/server/Privilege.customFlag.test.ts index b314b499f..ce5908fa2 100644 --- a/tests/server/Privilege.customFlag.test.ts +++ b/tests/server/Privilege.customFlag.test.ts @@ -7,22 +7,22 @@ describe("PrivilegeChecker.isCustomFlagAllowed (with mock cosmetics)", () => { }; const mockCosmetics: Cosmetics = { - patterns: {}, flag: { + color: { + a: { color: "#ff0000", flares: ["cosmetic:red"], name: "red" }, + b: { color: "#00ff00", name: "green" }, + c: { color: "#0000ff", flares: ["cosmetic:blue"], name: "blue" }, + }, layers: { a: { - name: "chocolate", flares: ["cosmetic:flags"], + name: "chocolate", }, b: { name: "center_hline" }, c: { name: "admin_layer" }, }, - color: { - a: { color: "#ff0000", name: "red", flares: ["cosmetic:red"] }, - b: { color: "#00ff00", name: "green" }, - c: { color: "#0000ff", name: "blue", flares: ["cosmetic:blue"] }, - }, }, + patterns: {}, }; const checker = new PrivilegeCheckerImpl(mockCosmetics, dummyPatternDecoder);