From 9163f0d710870cd4266feb9d498ca392f3983b12 Mon Sep 17 00:00:00 2001 From: Scott Anderson <662325+scottanderson@users.noreply.github.com> Date: Mon, 18 Aug 2025 20:09:21 -0400 Subject: [PATCH] Enable the `@typescript-eslint/prefer-readonly` eslint rule (#1859) ## Description: Enable the `@typescript-eslint/prefer-readonly` eslint rule. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced --- eslint.config.js | 1 + src/client/ClientGameRunner.ts | 14 +++---- src/client/DarkModeButton.ts | 4 +- src/client/FlagInput.ts | 2 +- src/client/FlagInputModal.ts | 4 +- src/client/HelpModal.ts | 4 +- src/client/HostLobbyModal.ts | 6 +-- src/client/InputHandler.ts | 10 ++--- src/client/JoinPrivateLobbyModal.ts | 6 +-- src/client/LangSelector.ts | 2 +- src/client/LanguageModal.ts | 6 +-- src/client/LocalServer.ts | 12 +++--- src/client/Main.ts | 4 +- src/client/NewsModal.ts | 4 +- src/client/PublicLobby.ts | 6 +-- src/client/SinglePlayerModal.ts | 10 ++--- src/client/TerritoryPatternsModal.ts | 6 +-- src/client/Transport.ts | 6 +-- src/client/UserSettingModal.ts | 6 +-- src/client/UsernameInput.ts | 2 +- src/client/graphics/AnimatedSprite.ts | 12 +++--- src/client/graphics/AnimatedSpriteLoader.ts | 4 +- src/client/graphics/GameRenderer.ts | 12 +++--- src/client/graphics/ProgressBar.ts | 12 +++--- src/client/graphics/TransformHandler.ts | 6 +-- src/client/graphics/fx/NukeFx.ts | 8 ++-- src/client/graphics/fx/SpriteFx.ts | 6 +-- src/client/graphics/fx/TextFx.ts | 14 +++---- src/client/graphics/fx/Timeline.ts | 2 +- src/client/graphics/fx/UnitExplosionFx.ts | 8 ++-- src/client/graphics/layers/AlertFrame.ts | 2 +- src/client/graphics/layers/ChatDisplay.ts | 2 +- src/client/graphics/layers/ChatIntegration.ts | 6 +-- src/client/graphics/layers/ChatModal.ts | 2 +- src/client/graphics/layers/EventsDisplay.ts | 6 +-- src/client/graphics/layers/FPSDisplay.ts | 10 ++--- src/client/graphics/layers/FxLayer.ts | 8 ++-- .../graphics/layers/GameRightSidebar.ts | 2 +- src/client/graphics/layers/GutterAdModal.ts | 10 ++--- src/client/graphics/layers/MainRadialMenu.ts | 20 +++++----- src/client/graphics/layers/NameLayer.ts | 40 +++++++++---------- src/client/graphics/layers/OptionsMenu.ts | 2 +- .../graphics/layers/PlayerActionHandler.ts | 4 +- src/client/graphics/layers/RadialMenu.ts | 18 ++++----- src/client/graphics/layers/RailroadLayer.ts | 6 +-- src/client/graphics/layers/SettingsModal.ts | 6 +-- src/client/graphics/layers/SpawnTimer.ts | 4 +- .../graphics/layers/StructureIconsLayer.ts | 14 +++---- src/client/graphics/layers/StructureLayer.ts | 14 +++---- src/client/graphics/layers/TerrainLayer.ts | 4 +- src/client/graphics/layers/TerritoryLayer.ts | 20 +++++----- src/client/graphics/layers/UILayer.ts | 14 +++---- src/client/graphics/layers/UnitDisplay.ts | 2 +- src/client/graphics/layers/UnitLayer.ts | 12 +++--- src/core/EventBus.ts | 2 +- src/core/GameRunner.ts | 6 +-- src/core/PatternDecoder.ts | 2 +- src/core/PseudoRandom.ts | 2 +- src/core/configuration/ColorAllocator.ts | 6 +-- src/core/configuration/DefaultConfig.ts | 12 +++--- src/core/configuration/PastelTheme.ts | 32 +++++++-------- src/core/configuration/PastelThemeDark.ts | 32 +++++++-------- src/core/execution/AttackExecution.ts | 12 +++--- src/core/execution/BoatRetreatExecution.ts | 4 +- src/core/execution/BotExecution.ts | 14 +++---- src/core/execution/BotSpawner.ts | 6 +-- src/core/execution/CityExecution.ts | 2 +- src/core/execution/ConstructionExecution.ts | 4 +- src/core/execution/DefensePostExecution.ts | 4 +- src/core/execution/DeleteUnitExecution.ts | 4 +- src/core/execution/DonateGoldExecution.ts | 4 +- src/core/execution/DonateTroopExecution.ts | 4 +- src/core/execution/EmbargoExecution.ts | 4 +- src/core/execution/EmojiExecution.ts | 6 +-- src/core/execution/ExecutionManager.ts | 8 ++-- src/core/execution/FactoryExecution.ts | 2 +- src/core/execution/FakeHumanExecution.ts | 22 +++++----- src/core/execution/MIRVExecution.ts | 8 ++-- .../execution/MarkDisconnectedExecution.ts | 4 +- src/core/execution/MissileSiloExecution.ts | 2 +- src/core/execution/NukeExecution.ts | 6 +-- src/core/execution/PlayerExecution.ts | 2 +- src/core/execution/PortExecution.ts | 2 +- src/core/execution/QuickChatExecution.ts | 8 ++-- src/core/execution/RailroadExecution.ts | 6 +-- src/core/execution/RetreatExecution.ts | 4 +- src/core/execution/SAMLauncherExecution.ts | 12 +++--- src/core/execution/SAMMissileExecution.ts | 10 ++--- src/core/execution/ShellExecution.ts | 8 ++-- src/core/execution/SpawnExecution.ts | 2 +- src/core/execution/TargetPlayerExecution.ts | 4 +- src/core/execution/TradeShipExecution.ts | 4 +- src/core/execution/TrainExecution.ts | 18 ++++----- src/core/execution/TrainStationExecution.ts | 8 ++-- src/core/execution/TransportShipExecution.ts | 8 ++-- .../execution/UpgradeStructureExecution.ts | 6 +-- src/core/execution/WarshipExecution.ts | 4 +- .../alliance/AllianceRequestExecution.ts | 4 +- .../alliance/AllianceRequestReplyExecution.ts | 6 +-- .../alliance/BreakAllianceExecution.ts | 4 +- src/core/execution/utils/BotBehavior.ts | 14 +++---- src/core/game/AllianceRequestImpl.ts | 8 ++-- src/core/game/AttackImpl.ts | 12 +++--- src/core/game/BinaryLoaderGameMapLoader.ts | 2 +- src/core/game/FetchGameMapLoader.ts | 2 +- src/core/game/Game.ts | 2 +- src/core/game/GameImpl.ts | 22 +++++----- src/core/game/GameMap.ts | 2 +- src/core/game/GameView.ts | 32 +++++++-------- src/core/game/PlayerImpl.ts | 20 +++++----- src/core/game/RailNetworkImpl.ts | 12 +++--- src/core/game/Railroad.ts | 6 +-- src/core/game/TerrainSearchMap.ts | 6 +-- src/core/game/TrainStation.ts | 8 ++-- src/core/game/UnitGrid.ts | 4 +- src/core/game/UnitImpl.ts | 12 +++--- src/core/pathfinding/MiniAStar.ts | 14 +++---- src/core/pathfinding/PathFinding.ts | 10 ++--- src/core/pathfinding/SerialAStar.ts | 24 +++++------ src/core/utilities/Line.ts | 20 +++++----- src/core/worker/WorkerClient.ts | 8 ++-- src/server/Cloudflare.ts | 10 ++--- src/server/GameManager.ts | 4 +- src/server/GameServer.ts | 18 ++++----- src/server/Gatekeeper.ts | 2 +- src/server/Privilege.ts | 6 +-- src/server/PrivilegeRefresher.ts | 8 ++-- tests/Censor.test.ts | 2 +- 128 files changed, 526 insertions(+), 525 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index 730888658..5cedff2f8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -86,6 +86,7 @@ export default [ "@typescript-eslint/prefer-includes": "error", "@typescript-eslint/prefer-literal-enum-member": "error", "@typescript-eslint/prefer-nullish-coalescing": "error", + "@typescript-eslint/prefer-readonly": "error", "eqeqeq": "error", "indent": "off", // @stylistic/indent "sort-keys": "error", diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index a24f6a2ec..fb52dfdcd 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -196,13 +196,13 @@ export class ClientGameRunner { private connectionCheckInterval: ReturnType | null = null; constructor( - private lobby: LobbyConfig, - private eventBus: EventBus, - private renderer: GameRenderer, - private input: InputHandler, - private transport: Transport, - private worker: WorkerClient, - private gameView: GameView, + private readonly lobby: LobbyConfig, + private readonly eventBus: EventBus, + private readonly renderer: GameRenderer, + private readonly input: InputHandler, + private readonly transport: Transport, + private readonly worker: WorkerClient, + private readonly gameView: GameView, ) { this.lastMessageTime = Date.now(); } diff --git a/src/client/DarkModeButton.ts b/src/client/DarkModeButton.ts index 5284ca323..e3544f8ff 100644 --- a/src/client/DarkModeButton.ts +++ b/src/client/DarkModeButton.ts @@ -4,7 +4,7 @@ import { UserSettings } from "../core/game/UserSettings"; @customElement("dark-mode-button") export class DarkModeButton extends LitElement { - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); @state() private darkMode: boolean = this.userSettings.darkMode(); createRenderRoot() { @@ -21,7 +21,7 @@ export class DarkModeButton extends LitElement { window.removeEventListener("dark-mode-changed", this.handleDarkModeChanged); } - private handleDarkModeChanged = (e: Event) => { + private readonly handleDarkModeChanged = (e: Event) => { const event = e as CustomEvent<{ darkMode: boolean }>; this.darkMode = event.detail.darkMode; }; diff --git a/src/client/FlagInput.ts b/src/client/FlagInput.ts index 0e5b77e80..e5aeabc21 100644 --- a/src/client/FlagInput.ts +++ b/src/client/FlagInput.ts @@ -43,7 +43,7 @@ export class FlagInput extends LitElement { ); } - private updateFlag = (ev: Event) => { + private readonly updateFlag = (ev: Event) => { const e = ev as CustomEvent<{ flag: string }>; if (!FlagSchema.safeParse(e.detail.flag).success) return; if (this.flag !== e.detail.flag) { diff --git a/src/client/FlagInputModal.ts b/src/client/FlagInputModal.ts index 0be8ccf52..c207383ed 100644 --- a/src/client/FlagInputModal.ts +++ b/src/client/FlagInputModal.ts @@ -4,7 +4,7 @@ import Countries from "./data/countries.json"; @customElement("flag-input-modal") export class FlagInputModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; @@ -108,7 +108,7 @@ export class FlagInputModal extends LitElement { super.disconnectedCallback(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/HelpModal.ts b/src/client/HelpModal.ts index ba75a2fda..e7ec2d181 100644 --- a/src/client/HelpModal.ts +++ b/src/client/HelpModal.ts @@ -6,7 +6,7 @@ import { getAltKey, getModifierKey, translateText } from "../client/Utils"; @customElement("help-modal") export class HelpModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; @@ -25,7 +25,7 @@ export class HelpModal extends LitElement { super.disconnectedCallback(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index df63aca3c..b4d2b4179 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -32,7 +32,7 @@ import { translateText } from "../client/Utils"; @customElement("host-lobby-modal") export class HostLobbyModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; @@ -58,7 +58,7 @@ export class HostLobbyModal extends LitElement { private playersInterval: ReturnType | null = null; // Add a new timer for debouncing bot changes private botsUpdateTimer: number | null = null; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); connectedCallback() { super.connectedCallback(); @@ -70,7 +70,7 @@ export class HostLobbyModal extends LitElement { super.disconnectedCallback(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 8e85cbbf5..8ff2db2f0 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -121,7 +121,7 @@ export class InputHandler { private lastPointerDownX = 0; private lastPointerDownY = 0; - private pointers: Map = new Map(); + private readonly pointers: Map = new Map(); private lastPinchDistance = 0; @@ -130,17 +130,17 @@ export class InputHandler { private alternateView = false; private moveInterval: ReturnType | null = null; - private activeKeys = new Set(); + private readonly activeKeys = new Set(); private keybinds: Record = {}; private readonly PAN_SPEED = 5; private readonly ZOOM_SPEED = 10; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); constructor( - private canvas: HTMLCanvasElement, - private eventBus: EventBus, + private readonly canvas: HTMLCanvasElement, + private readonly eventBus: EventBus, ) {} initialize() { diff --git a/src/client/JoinPrivateLobbyModal.ts b/src/client/JoinPrivateLobbyModal.ts index 8f4d3a4fe..4f4aa2989 100644 --- a/src/client/JoinPrivateLobbyModal.ts +++ b/src/client/JoinPrivateLobbyModal.ts @@ -14,11 +14,11 @@ import { translateText } from "../client/Utils"; @customElement("join-private-lobby-modal") export class JoinPrivateLobbyModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; - @query("#lobbyIdInput") private lobbyIdInput!: HTMLInputElement; + @query("#lobbyIdInput") private readonly lobbyIdInput!: HTMLInputElement; @state() private message = ""; @state() private hasJoined = false; @state() private players: string[] = []; @@ -35,7 +35,7 @@ export class JoinPrivateLobbyModal extends LitElement { super.disconnectedCallback(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/LangSelector.ts b/src/client/LangSelector.ts index 6c1d92a08..445479717 100644 --- a/src/client/LangSelector.ts +++ b/src/client/LangSelector.ts @@ -47,7 +47,7 @@ export class LangSelector extends LitElement { private debugKeyPressed = false; // eslint-disable-next-line @typescript-eslint/no-explicit-any - private languageMap: Record = { + private readonly languageMap: Record = { ar, bg, bn, diff --git a/src/client/LanguageModal.ts b/src/client/LanguageModal.ts index 1b3726b27..4b5c5e34d 100644 --- a/src/client/LanguageModal.ts +++ b/src/client/LanguageModal.ts @@ -14,7 +14,7 @@ export class LanguageModal extends LitElement { return this; // Use Light DOM for TailwindCSS classes } - private close = () => { + private readonly close = () => { this.dispatchEvent( new CustomEvent("close-modal", { bubbles: true, @@ -44,14 +44,14 @@ export class LanguageModal extends LitElement { document.body.style.overflow = "auto"; } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); } }; - private selectLanguage = (lang: string) => { + private readonly selectLanguage = (lang: string) => { this.dispatchEvent( new CustomEvent("language-selected", { detail: { lang }, diff --git a/src/client/LocalServer.ts b/src/client/LocalServer.ts index 45b5d036d..12cbb78dd 100644 --- a/src/client/LocalServer.ts +++ b/src/client/LocalServer.ts @@ -21,7 +21,7 @@ export class LocalServer { // All turns from the game record on replay. private replayTurns: Turn[] = []; - private turns: Turn[] = []; + private readonly turns: Turn[] = []; private intents: Intent[] = []; private startedAt: number; @@ -38,11 +38,11 @@ export class LocalServer { private turnCheckInterval: ReturnType; constructor( - private lobbyConfig: LobbyConfig, - private clientConnect: () => void, - private clientMessage: (message: ServerMessage) => void, - private isReplay: boolean, - private eventBus: EventBus, + private readonly lobbyConfig: LobbyConfig, + private readonly clientConnect: () => void, + private readonly clientMessage: (message: ServerMessage) => void, + private readonly isReplay: boolean, + private readonly eventBus: EventBus, ) {} start() { diff --git a/src/client/Main.ts b/src/client/Main.ts index b7d683408..3c0fa501a 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -83,7 +83,7 @@ export type KickPlayerEvent = { class Client { private gameStop: (() => void) | null = null; - private eventBus: EventBus = new EventBus(); + private readonly eventBus: EventBus = new EventBus(); private usernameInput: UsernameInput | null = null; private flagInput: FlagInput | null = null; @@ -91,7 +91,7 @@ class Client { private joinModal: JoinPrivateLobbyModal; private publicLobby: PublicLobby; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); constructor() {} diff --git a/src/client/NewsModal.ts b/src/client/NewsModal.ts index c5c617bbd..ed3c3f74e 100644 --- a/src/client/NewsModal.ts +++ b/src/client/NewsModal.ts @@ -8,7 +8,7 @@ import { translateText } from "../client/Utils"; @customElement("news-modal") export class NewsModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; @@ -23,7 +23,7 @@ export class NewsModal extends LitElement { super.disconnectedCallback(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/PublicLobby.ts b/src/client/PublicLobby.ts index 3012af80c..c194d0c2e 100644 --- a/src/client/PublicLobby.ts +++ b/src/client/PublicLobby.ts @@ -13,11 +13,11 @@ export class PublicLobby extends LitElement { @state() private lobbies: GameInfo[] = []; @state() public isLobbyHighlighted = false; @state() private isButtonDebounced = false; - @state() private mapImages: Map = new Map(); + @state() private readonly mapImages: Map = new Map(); private lobbiesInterval: number | null = null; private currLobby: GameInfo | null = null; - private debounceDelay = 750; - private lobbyIDToStart = new Map(); + private readonly debounceDelay = 750; + private readonly lobbyIDToStart = new Map(); createRenderRoot() { return this; diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index c6e0395c1..7d6497474 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -28,7 +28,7 @@ import { translateText } from "../client/Utils"; @customElement("single-player-modal") export class SinglePlayerModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; @@ -37,9 +37,9 @@ export class SinglePlayerModal extends LitElement { @state() private disableNPCs = false; @state() private bots = 400; @state() private infiniteGold = false; - @state() private donateGold = false; + @state() private readonly donateGold = false; @state() private infiniteTroops = false; - @state() private donateTroops = false; + @state() private readonly donateTroops = false; @state() private instantBuild = false; @state() private useRandomMap = false; @state() private gameMode: GameMode = GameMode.FFA; @@ -47,7 +47,7 @@ export class SinglePlayerModal extends LitElement { @state() private disabledUnits: UnitType[] = []; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); connectedCallback() { super.connectedCallback(); @@ -59,7 +59,7 @@ export class SinglePlayerModal extends LitElement { super.disconnectedCallback(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/TerritoryPatternsModal.ts b/src/client/TerritoryPatternsModal.ts index c171b630b..6715c85c0 100644 --- a/src/client/TerritoryPatternsModal.ts +++ b/src/client/TerritoryPatternsModal.ts @@ -13,7 +13,7 @@ import { translateText } from "./Utils"; @customElement("territory-patterns-modal") export class TerritoryPatternsModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; @@ -36,7 +36,7 @@ export class TerritoryPatternsModal extends LitElement { public resizeObserver: ResizeObserver; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); private isActive = false; @@ -71,7 +71,7 @@ export class TerritoryPatternsModal extends LitElement { this.requestUpdate(); } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (e.code === "Escape") { e.preventDefault(); this.close(); diff --git a/src/client/Transport.ts b/src/client/Transport.ts index ac27db411..e19eabd7a 100644 --- a/src/client/Transport.ts +++ b/src/client/Transport.ts @@ -174,7 +174,7 @@ export class Transport { private localServer: LocalServer; - private buffer: string[] = []; + private readonly buffer: string[] = []; private onconnect: () => void; private onmessage: (msg: ServerMessage) => void; @@ -182,8 +182,8 @@ export class Transport { private pingInterval: number | null = null; public readonly isLocal: boolean; constructor( - private lobbyConfig: LobbyConfig, - private eventBus: EventBus, + private readonly lobbyConfig: LobbyConfig, + private readonly eventBus: EventBus, ) { // If gameRecord is not null, we are replaying an archived game. // For multiplayer games, GameConfig is not known until game starts. diff --git a/src/client/UserSettingModal.ts b/src/client/UserSettingModal.ts index d1a6a40f3..2e46a7300 100644 --- a/src/client/UserSettingModal.ts +++ b/src/client/UserSettingModal.ts @@ -13,7 +13,7 @@ const KeybindSchema = z.record(z.string(), z.string()); @customElement("user-setting") export class UserSettingModal extends LitElement { - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); @state() private settingsMode: "basic" | "keybinds" = "basic"; @state() private keybinds: Record = {}; @@ -35,7 +35,7 @@ export class UserSettingModal extends LitElement { } } - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; isModalOpen: boolean; @@ -51,7 +51,7 @@ export class UserSettingModal extends LitElement { document.body.style.overflow = "auto"; } - private handleKeyDown = (e: KeyboardEvent) => { + private readonly handleKeyDown = (e: KeyboardEvent) => { if (!this.modalEl?.isModalOpen || this.showEasterEggSettings) return; if (e.code === "Escape") { diff --git a/src/client/UsernameInput.ts b/src/client/UsernameInput.ts index d530b8463..6b72ac448 100644 --- a/src/client/UsernameInput.ts +++ b/src/client/UsernameInput.ts @@ -15,7 +15,7 @@ export class UsernameInput extends LitElement { @state() private username = ""; @property({ type: String }) validationError = ""; private _isValid = true; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); // Remove static styles since we're using Tailwind diff --git a/src/client/graphics/AnimatedSprite.ts b/src/client/graphics/AnimatedSprite.ts index 0cf108292..603df5d1b 100644 --- a/src/client/graphics/AnimatedSprite.ts +++ b/src/client/graphics/AnimatedSprite.ts @@ -1,15 +1,15 @@ export class AnimatedSprite { - private frameHeight: number; + private readonly frameHeight: number; private currentFrame = 0; private elapsedTime = 0; private active = true; constructor( - private image: CanvasImageSource, - private frameWidth: number, - private frameCount: number, - private frameDuration: number, // in milliseconds - private looping = false, + private readonly image: CanvasImageSource, + private readonly frameWidth: number, + private readonly frameCount: number, + private readonly frameDuration: number, // in milliseconds + private readonly looping = false, private originX: number, private originY: number, ) { diff --git a/src/client/graphics/AnimatedSpriteLoader.ts b/src/client/graphics/AnimatedSpriteLoader.ts index df23c5d57..db949f872 100644 --- a/src/client/graphics/AnimatedSpriteLoader.ts +++ b/src/client/graphics/AnimatedSpriteLoader.ts @@ -128,9 +128,9 @@ const ANIMATED_SPRITE_CONFIG: Partial> = { }; export class AnimatedSpriteLoader { - private animatedSpriteImageMap: Map = new Map(); + private readonly animatedSpriteImageMap: Map = new Map(); // Do not color the same sprite twice - private coloredAnimatedSpriteCache: Map = + private readonly coloredAnimatedSpriteCache: Map = new Map(); public async loadAllAnimatedSpriteImages(): Promise { diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index 17d04c9bb..0e2343ebc 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -283,16 +283,16 @@ export function createRenderer( } export class GameRenderer { - private context: CanvasRenderingContext2D; + private readonly context: CanvasRenderingContext2D; constructor( - private game: GameView, - private eventBus: EventBus, - private canvas: HTMLCanvasElement, + private readonly game: GameView, + private readonly eventBus: EventBus, + private readonly canvas: HTMLCanvasElement, public transformHandler: TransformHandler, public uiState: UIState, - private layers: Layer[], - private fpsDisplay: FPSDisplay, + private readonly layers: Layer[], + private readonly fpsDisplay: FPSDisplay, ) { const context = canvas.getContext("2d"); if (context === null) throw new Error("2d context not supported"); diff --git a/src/client/graphics/ProgressBar.ts b/src/client/graphics/ProgressBar.ts index 5d186da6f..2a22ab7c9 100644 --- a/src/client/graphics/ProgressBar.ts +++ b/src/client/graphics/ProgressBar.ts @@ -1,12 +1,12 @@ export class ProgressBar { private static readonly CLEAR_PADDING = 2; constructor( - private colors: string[] = [], - private ctx: CanvasRenderingContext2D, - private x: number, - private y: number, - private w: number, - private h: number, + private readonly colors: string[] = [], + private readonly ctx: CanvasRenderingContext2D, + private readonly x: number, + private readonly y: number, + private readonly w: number, + private readonly h: number, private progress = 0, // Progress from 0 to 1 ) { this.setProgress(progress); diff --git a/src/client/graphics/TransformHandler.ts b/src/client/graphics/TransformHandler.ts index 60b840a04..ec4587456 100644 --- a/src/client/graphics/TransformHandler.ts +++ b/src/client/graphics/TransformHandler.ts @@ -24,9 +24,9 @@ export class TransformHandler { private changed = false; constructor( - private game: GameView, - private eventBus: EventBus, - private canvas: HTMLCanvasElement, + private readonly game: GameView, + private readonly eventBus: EventBus, + private readonly canvas: HTMLCanvasElement, ) { this._boundingRect = this.canvas.getBoundingClientRect(); this.eventBus.on(ZoomEvent, (e) => this.onZoom(e)); diff --git a/src/client/graphics/fx/NukeFx.ts b/src/client/graphics/fx/NukeFx.ts index 6e1694a23..d610d403c 100644 --- a/src/client/graphics/fx/NukeFx.ts +++ b/src/client/graphics/fx/NukeFx.ts @@ -9,10 +9,10 @@ import { GameView } from "../../../core/game/GameView"; export class ShockwaveFx implements Fx { private lifeTime = 0; constructor( - private x: number, - private y: number, - private duration: number, - private maxRadius: number, + private readonly x: number, + private readonly y: number, + private readonly duration: number, + private readonly maxRadius: number, ) {} renderTick(frameTime: number, ctx: CanvasRenderingContext2D): boolean { diff --git a/src/client/graphics/fx/SpriteFx.ts b/src/client/graphics/fx/SpriteFx.ts index 978da1142..7ef479daa 100644 --- a/src/client/graphics/fx/SpriteFx.ts +++ b/src/client/graphics/fx/SpriteFx.ts @@ -20,9 +20,9 @@ function fadeInOut(t: number, fadeIn = 0.3, fadeOut = 0.7): number { */ export class FadeFx implements Fx { constructor( - private fxToFade: SpriteFx, - private fadeIn: number, - private fadeOut: number, + private readonly fxToFade: SpriteFx, + private readonly fadeIn: number, + private readonly fadeOut: number, ) {} renderTick(duration: number, ctx: CanvasRenderingContext2D): boolean { diff --git a/src/client/graphics/fx/TextFx.ts b/src/client/graphics/fx/TextFx.ts index 47eb68e32..cfc7288f8 100644 --- a/src/client/graphics/fx/TextFx.ts +++ b/src/client/graphics/fx/TextFx.ts @@ -4,13 +4,13 @@ export class TextFx implements Fx { private lifeTime = 0; constructor( - private text: string, - private x: number, - private y: number, - private duration: number, - private riseDistance = 30, - private font = "11px sans-serif", - private color: { r: number; g: number; b: number } = { + private readonly text: string, + private readonly x: number, + private readonly y: number, + private readonly duration: number, + 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, diff --git a/src/client/graphics/fx/Timeline.ts b/src/client/graphics/fx/Timeline.ts index 32310244e..d500a1f33 100644 --- a/src/client/graphics/fx/Timeline.ts +++ b/src/client/graphics/fx/Timeline.ts @@ -8,7 +8,7 @@ type TimedTask = { * Basic timeline to chain actions */ export class Timeline { - private tasks: TimedTask[] = []; + private readonly tasks: TimedTask[] = []; private timeElapsed = 0; add(delay: number, action: () => void): Timeline { diff --git a/src/client/graphics/fx/UnitExplosionFx.ts b/src/client/graphics/fx/UnitExplosionFx.ts index 9cc4f7502..8971e057d 100644 --- a/src/client/graphics/fx/UnitExplosionFx.ts +++ b/src/client/graphics/fx/UnitExplosionFx.ts @@ -8,13 +8,13 @@ import { Timeline } from "./Timeline"; * Explosion Effect: a few timed explosions */ export class UnitExplosionFx implements Fx { - private timeline = new Timeline(); - private explosions: Fx[] = []; + private readonly timeline = new Timeline(); + private readonly explosions: Fx[] = []; constructor( animatedSpriteLoader: AnimatedSpriteLoader, - private x: number, - private y: number, + private readonly x: number, + private readonly y: number, game: GameView, ) { const config = [ diff --git a/src/client/graphics/layers/AlertFrame.ts b/src/client/graphics/layers/AlertFrame.ts index 44f5d7aaf..515d6e34b 100644 --- a/src/client/graphics/layers/AlertFrame.ts +++ b/src/client/graphics/layers/AlertFrame.ts @@ -15,7 +15,7 @@ const ALERT_COUNT = 2; @customElement("alert-frame") export class AlertFrame extends LitElement implements Layer { public game: GameView; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); @state() private isActive = false; diff --git a/src/client/graphics/layers/ChatDisplay.ts b/src/client/graphics/layers/ChatDisplay.ts index af4727602..6679f2979 100644 --- a/src/client/graphics/layers/ChatDisplay.ts +++ b/src/client/graphics/layers/ChatDisplay.ts @@ -24,7 +24,7 @@ export class ChatDisplay extends LitElement implements Layer { public eventBus: EventBus; public game: GameView; - private active = false; + private readonly active = false; @state() private _hidden = false; @state() private newEvents = 0; diff --git a/src/client/graphics/layers/ChatIntegration.ts b/src/client/graphics/layers/ChatIntegration.ts index 597628ec0..f8993604b 100644 --- a/src/client/graphics/layers/ChatIntegration.ts +++ b/src/client/graphics/layers/ChatIntegration.ts @@ -6,11 +6,11 @@ import { SendQuickChatEvent } from "../../Transport"; import { translateText } from "../../Utils"; export class ChatIntegration { - private ctModal: ChatModal; + private readonly ctModal: ChatModal; constructor( - private game: GameView, - private eventBus: EventBus, + private readonly game: GameView, + private readonly eventBus: EventBus, ) { this.ctModal = document.querySelector("chat-modal") as ChatModal; diff --git a/src/client/graphics/layers/ChatModal.ts b/src/client/graphics/layers/ChatModal.ts index f3e90732f..aed36bfa8 100644 --- a/src/client/graphics/layers/ChatModal.ts +++ b/src/client/graphics/layers/ChatModal.ts @@ -19,7 +19,7 @@ export const quickChatPhrases: QuickChatPhrases = quickChatData; @customElement("chat-modal") export class ChatModal extends LitElement { - @query("o-modal") private modalEl!: HTMLElement & { + @query("o-modal") private readonly modalEl!: HTMLElement & { open: () => void; close: () => void; }; diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index 1e7906bc8..efbac843f 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -76,7 +76,7 @@ export class EventsDisplay extends LitElement implements Layer { private events: GameEvent[] = []; // allianceID -> last checked at tick - private alliancesCheckedAt = new Map(); + private readonly alliancesCheckedAt = new Map(); @state() private incomingAttacks: AttackUpdate[] = []; @state() private outgoingAttacks: AttackUpdate[] = []; @state() private outgoingLandAttacks: AttackUpdate[] = []; @@ -87,7 +87,7 @@ export class EventsDisplay extends LitElement implements Layer { @state() private latestGoldAmount: bigint | null = null; @state() private goldAmountAnimating = false; private goldAmountTimeoutId: ReturnType | null = null; - @state() private eventsFilters: Map = new Map([ + @state() private readonly eventsFilters: Map = new Map([ [MessageCategory.ATTACK, false], [MessageCategory.TRADE, false], [MessageCategory.ALLIANCE, false], @@ -141,7 +141,7 @@ export class EventsDisplay extends LitElement implements Layer { this.requestUpdate(); } - private updateMap = [ + private readonly updateMap = [ [GameUpdateType.DisplayEvent, this.onDisplayMessageEvent.bind(this)], [GameUpdateType.DisplayChatEvent, this.onDisplayChatEvent.bind(this)], [GameUpdateType.AllianceRequest, this.onAllianceRequestEvent.bind(this)], diff --git a/src/client/graphics/layers/FPSDisplay.ts b/src/client/graphics/layers/FPSDisplay.ts index f61f1fec6..cb999ed51 100644 --- a/src/client/graphics/layers/FPSDisplay.ts +++ b/src/client/graphics/layers/FPSDisplay.ts @@ -33,8 +33,8 @@ export class FPSDisplay extends LitElement implements Layer { private frameCount = 0; private lastTime = 0; - private frameTimes: number[] = []; - private fpsHistory: number[] = []; + private readonly frameTimes: number[] = []; + private readonly fpsHistory: number[] = []; private lastSecondTime = 0; private framesThisSecond = 0; private dragStart: { x: number; y: number } = { x: 0, y: 0 }; @@ -118,7 +118,7 @@ export class FPSDisplay extends LitElement implements Layer { this.userSettings.togglePerformanceOverlay(); } - private handleMouseDown = (e: MouseEvent) => { + private readonly handleMouseDown = (e: MouseEvent) => { // Don't start dragging if clicking on close button if ((e.target as HTMLElement).classList.contains("close-button")) { return; @@ -135,7 +135,7 @@ export class FPSDisplay extends LitElement implements Layer { e.preventDefault(); }; - private handleMouseMove = (e: MouseEvent) => { + private readonly handleMouseMove = (e: MouseEvent) => { if (!this.isDragging) return; const newX = e.clientX - this.dragStart.x; @@ -153,7 +153,7 @@ export class FPSDisplay extends LitElement implements Layer { this.requestUpdate(); }; - private handleMouseUp = () => { + private readonly handleMouseUp = () => { this.isDragging = false; document.removeEventListener("mousemove", this.handleMouseMove); document.removeEventListener("mouseup", this.handleMouseUp); diff --git a/src/client/graphics/layers/FxLayer.ts b/src/client/graphics/layers/FxLayer.ts index 14cbf0acd..a6c1a04b7 100644 --- a/src/client/graphics/layers/FxLayer.ts +++ b/src/client/graphics/layers/FxLayer.ts @@ -22,14 +22,14 @@ export class FxLayer implements Layer { private context: CanvasRenderingContext2D; private lastRefresh = 0; - private refreshRate = 10; - private theme: Theme; - private animatedSpriteLoader: AnimatedSpriteLoader = + private readonly refreshRate = 10; + private readonly theme: Theme; + private readonly animatedSpriteLoader: AnimatedSpriteLoader = new AnimatedSpriteLoader(); private allFx: Fx[] = []; - constructor(private game: GameView) { + constructor(private readonly game: GameView) { this.theme = this.game.config().theme(); } diff --git a/src/client/graphics/layers/GameRightSidebar.ts b/src/client/graphics/layers/GameRightSidebar.ts index 3af8824ec..611b0d995 100644 --- a/src/client/graphics/layers/GameRightSidebar.ts +++ b/src/client/graphics/layers/GameRightSidebar.ts @@ -64,7 +64,7 @@ export class GameRightSidebar extends LitElement implements Layer { } } - private secondsToHms = (d: number): string => { + private readonly secondsToHms = (d: number): string => { const h = Math.floor(d / 3600); const m = Math.floor((d % 3600) / 60); const s = Math.floor((d % 3600) % 60); diff --git a/src/client/graphics/layers/GutterAdModal.ts b/src/client/graphics/layers/GutterAdModal.ts index a702f1b6b..809133971 100644 --- a/src/client/graphics/layers/GutterAdModal.ts +++ b/src/client/graphics/layers/GutterAdModal.ts @@ -18,11 +18,11 @@ export class GutterAdModal extends LitElement implements Layer { @state() private adLoaded = false; - private leftAdType = "left_rail"; - private rightAdType = "right_rail"; - private leftContainerId = "gutter-ad-container-left"; - private rightContainerId = "gutter-ad-container-right"; - private margin = "10px"; + private readonly leftAdType = "left_rail"; + private readonly rightAdType = "right_rail"; + private readonly leftContainerId = "gutter-ad-container-left"; + private readonly rightContainerId = "gutter-ad-container-right"; + private readonly margin = "10px"; // Override createRenderRoot to disable shadow DOM createRenderRoot() { diff --git a/src/client/graphics/layers/MainRadialMenu.ts b/src/client/graphics/layers/MainRadialMenu.ts index 05c9d1afb..2a49afd32 100644 --- a/src/client/graphics/layers/MainRadialMenu.ts +++ b/src/client/graphics/layers/MainRadialMenu.ts @@ -24,21 +24,21 @@ import swordIcon from "../../../../resources/images/SwordIconWhite.svg"; @customElement("main-radial-menu") export class MainRadialMenu extends LitElement implements Layer { - private radialMenu: RadialMenu; + private readonly radialMenu: RadialMenu; - private playerActionHandler: PlayerActionHandler; - private chatIntegration: ChatIntegration; + private readonly playerActionHandler: PlayerActionHandler; + private readonly chatIntegration: ChatIntegration; private clickedTile: TileRef | null = null; constructor( - private eventBus: EventBus, - private game: GameView, - private transformHandler: TransformHandler, - private emojiTable: EmojiTable, - private buildMenu: BuildMenu, - private uiState: UIState, - private playerPanel: PlayerPanel, + private readonly eventBus: EventBus, + private readonly game: GameView, + private readonly transformHandler: TransformHandler, + private readonly emojiTable: EmojiTable, + private readonly buildMenu: BuildMenu, + private readonly uiState: UIState, + private readonly playerPanel: PlayerPanel, ) { super(); diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 908b093b9..aff18436d 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -38,33 +38,33 @@ class RenderInfo { export class NameLayer implements Layer { private canvas: HTMLCanvasElement; private lastChecked = 0; - private renderCheckRate = 100; - private renderRefreshRate = 500; - private rand = new PseudoRandom(10); + private readonly renderCheckRate = 100; + private readonly renderRefreshRate = 500; + private readonly rand = new PseudoRandom(10); private renders: RenderInfo[] = []; - private seenPlayers: Set = new Set(); - private traitorIconImage: HTMLImageElement; - private disconnectedIconImage: HTMLImageElement; - private allianceRequestBlackIconImage: HTMLImageElement; - private allianceRequestWhiteIconImage: HTMLImageElement; - private allianceIconImage: HTMLImageElement; - private targetIconImage: HTMLImageElement; - private crownIconImage: HTMLImageElement; - private embargoBlackIconImage: HTMLImageElement; - private embargoWhiteIconImage: HTMLImageElement; - private nukeWhiteIconImage: HTMLImageElement; - private nukeRedIconImage: HTMLImageElement; - private shieldIconImage: HTMLImageElement; + private readonly seenPlayers: Set = new Set(); + private readonly traitorIconImage: HTMLImageElement; + private readonly disconnectedIconImage: HTMLImageElement; + private readonly allianceRequestBlackIconImage: HTMLImageElement; + private readonly allianceRequestWhiteIconImage: HTMLImageElement; + private readonly allianceIconImage: HTMLImageElement; + private readonly targetIconImage: HTMLImageElement; + private readonly crownIconImage: HTMLImageElement; + private readonly embargoBlackIconImage: HTMLImageElement; + private readonly embargoWhiteIconImage: HTMLImageElement; + private readonly nukeWhiteIconImage: HTMLImageElement; + private readonly nukeRedIconImage: HTMLImageElement; + private readonly shieldIconImage: HTMLImageElement; private container: HTMLDivElement; private firstPlace: PlayerView | null = null; private theme: Theme = this.game.config().theme(); - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); private isVisible = true; constructor( - private game: GameView, - private transformHandler: TransformHandler, - private eventBus: EventBus, + private readonly game: GameView, + private readonly transformHandler: TransformHandler, + private readonly eventBus: EventBus, ) { this.traitorIconImage = new Image(); this.traitorIconImage.src = traitorIcon; diff --git a/src/client/graphics/layers/OptionsMenu.ts b/src/client/graphics/layers/OptionsMenu.ts index 91f01c3a1..37b55c03a 100644 --- a/src/client/graphics/layers/OptionsMenu.ts +++ b/src/client/graphics/layers/OptionsMenu.ts @@ -45,7 +45,7 @@ const secondsToHms = (d: number): string => { export class OptionsMenu extends LitElement implements Layer { public game: GameView; public eventBus: EventBus; - private userSettings: UserSettings = new UserSettings(); + private readonly userSettings: UserSettings = new UserSettings(); @state() private showPauseButton = true; diff --git a/src/client/graphics/layers/PlayerActionHandler.ts b/src/client/graphics/layers/PlayerActionHandler.ts index 85a53279f..819cf1263 100644 --- a/src/client/graphics/layers/PlayerActionHandler.ts +++ b/src/client/graphics/layers/PlayerActionHandler.ts @@ -20,8 +20,8 @@ import { UIState } from "../UIState"; export class PlayerActionHandler { constructor( - private eventBus: EventBus, - private uiState: UIState, + private readonly eventBus: EventBus, + private readonly uiState: UIState, ) {} async getPlayerActions( diff --git a/src/client/graphics/layers/RadialMenu.ts b/src/client/graphics/layers/RadialMenu.ts index 65451f121..4ed69673c 100644 --- a/src/client/graphics/layers/RadialMenu.ts +++ b/src/client/graphics/layers/RadialMenu.ts @@ -56,20 +56,20 @@ export class RadialMenu implements Layer { private isTransitioning = false; private lastHideTime = 0; - private reopenCooldownMs = 300; + private readonly reopenCooldownMs = 300; private anchorX = 0; private anchorY = 0; - private menuGroups: Map< + private readonly menuGroups: Map< number, d3.Selection > = new Map(); - private menuPaths: Map< + private readonly menuPaths: Map< string, d3.Selection > = new Map(); - private menuIcons: Map< + private readonly menuIcons: Map< string, d3.Selection > = new Map(); @@ -78,14 +78,14 @@ export class RadialMenu implements Layer { private submenuHoverTimeout: number | null = null; private backButtonHoverTimeout: number | null = null; private navigationInProgress = false; - private originalCenterButtonIcon = ""; + private readonly originalCenterButtonIcon: string = ""; private params: MenuElementParams | null = null; constructor( - private eventBus: EventBus, - private rootMenu: MenuElement, - private centerButtonElement: CenterButtonElement, + private readonly eventBus: EventBus, + private readonly rootMenu: MenuElement, + private readonly centerButtonElement: CenterButtonElement, config: RadialMenuConfig = {}, ) { this.config = { @@ -1069,7 +1069,7 @@ export class RadialMenu implements Layer { .style("left", `${clampedX}px`); } - private handleResize = () => { + private readonly handleResize = () => { if (this.isVisible) this.clampAndSetMenuPositionForLevel(this.currentLevel); }; } diff --git a/src/client/graphics/layers/RailroadLayer.ts b/src/client/graphics/layers/RailroadLayer.ts index 55d4981d0..e829c879d 100644 --- a/src/client/graphics/layers/RailroadLayer.ts +++ b/src/client/graphics/layers/RailroadLayer.ts @@ -21,13 +21,13 @@ type RailRef = { export class RailroadLayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; - private theme: Theme; + private readonly theme: Theme; // Save the number of railroads per tiles. Delete when it reaches 0 - private existingRailroads = new Map(); + private readonly existingRailroads = new Map(); private nextRailIndexToCheck = 0; private railTileList: TileRef[] = []; - constructor(private game: GameView) { + constructor(private readonly game: GameView) { this.theme = game.config().theme(); } diff --git a/src/client/graphics/layers/SettingsModal.ts b/src/client/graphics/layers/SettingsModal.ts index 90041109f..5d0fe60d4 100644 --- a/src/client/graphics/layers/SettingsModal.ts +++ b/src/client/graphics/layers/SettingsModal.ts @@ -36,7 +36,7 @@ export class SettingsModal extends LitElement implements Layer { private alternateView = false; @query(".modal-overlay") - private modalOverlay!: HTMLElement; + private readonly modalOverlay!: HTMLElement; @property({ type: Boolean }) shouldPause = false; @@ -69,7 +69,7 @@ export class SettingsModal extends LitElement implements Layer { super.disconnectedCallback(); } - private handleOutsideClick = (event: MouseEvent) => { + private readonly handleOutsideClick = (event: MouseEvent) => { if ( this.isVisible && this.modalOverlay && @@ -79,7 +79,7 @@ export class SettingsModal extends LitElement implements Layer { } }; - private handleKeyDown = (event: KeyboardEvent) => { + private readonly handleKeyDown = (event: KeyboardEvent) => { if (this.isVisible && event.key === "Escape") { this.closeModal(); } diff --git a/src/client/graphics/layers/SpawnTimer.ts b/src/client/graphics/layers/SpawnTimer.ts index 2310d037f..bd21e3d40 100644 --- a/src/client/graphics/layers/SpawnTimer.ts +++ b/src/client/graphics/layers/SpawnTimer.ts @@ -8,8 +8,8 @@ export class SpawnTimer implements Layer { private colors = ["rgba(0, 128, 255, 0.7)", "rgba(0, 0, 0, 0.5)"]; constructor( - private game: GameView, - private transformHandler: TransformHandler, + private readonly game: GameView, + private readonly transformHandler: TransformHandler, ) {} init() {} diff --git a/src/client/graphics/layers/StructureIconsLayer.ts b/src/client/graphics/layers/StructureIconsLayer.ts index e4f3736d5..7b8ffd1d2 100644 --- a/src/client/graphics/layers/StructureIconsLayer.ts +++ b/src/client/graphics/layers/StructureIconsLayer.ts @@ -59,12 +59,12 @@ export class StructureIconsLayer implements Layer { private levelsStage: PIXI.Container; private dotsStage: PIXI.Container; private shouldRedraw = true; - private textureCache: Map = new Map(); - private theme: Theme; + private readonly textureCache: Map = new Map(); + private readonly theme: Theme; private renderer: PIXI.Renderer; private renders: StructureRenderInfo[] = []; - private seenUnits: Set = new Set(); - private structures: Map< + private readonly seenUnits: Set = new Set(); + private readonly structures: Map< UnitType, { visible: boolean; iconPath: string; image: HTMLImageElement | null } > = new Map([ @@ -87,9 +87,9 @@ export class StructureIconsLayer implements Layer { private renderSprites = true; constructor( - private game: GameView, - private eventBus: EventBus, - private transformHandler: TransformHandler, + private readonly game: GameView, + private readonly eventBus: EventBus, + private readonly transformHandler: TransformHandler, ) { this.theme = game.config().theme(); this.structures.forEach((u, unitType) => this.loadIcon(u, unitType)); diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts index 7705c4bad..623bda2df 100644 --- a/src/client/graphics/layers/StructureLayer.ts +++ b/src/client/graphics/layers/StructureLayer.ts @@ -31,10 +31,10 @@ type UnitRenderConfig = { export class StructureLayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; - private unitIcons: Map = new Map(); - private theme: Theme; - private tempCanvas: HTMLCanvasElement; - private tempContext: CanvasRenderingContext2D; + private readonly unitIcons: Map = new Map(); + private readonly theme: Theme; + private readonly tempCanvas: HTMLCanvasElement; + private readonly tempContext: CanvasRenderingContext2D; // Configuration for supported unit types only private readonly unitConfigs: Partial> = { @@ -71,9 +71,9 @@ export class StructureLayer implements Layer { }; constructor( - private game: GameView, - private eventBus: EventBus, - private transformHandler: TransformHandler, + private readonly game: GameView, + private readonly eventBus: EventBus, + private readonly transformHandler: TransformHandler, ) { this.theme = game.config().theme(); this.tempCanvas = document.createElement("canvas"); diff --git a/src/client/graphics/layers/TerrainLayer.ts b/src/client/graphics/layers/TerrainLayer.ts index 0ca543445..51ba72f2d 100644 --- a/src/client/graphics/layers/TerrainLayer.ts +++ b/src/client/graphics/layers/TerrainLayer.ts @@ -10,8 +10,8 @@ export class TerrainLayer implements Layer { private theme: Theme; constructor( - private game: GameView, - private transformHandler: TransformHandler, + private readonly game: GameView, + private readonly transformHandler: TransformHandler, ) {} shouldTransform(): boolean { return true; diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts index 5cae9e17b..3f82884c0 100644 --- a/src/client/graphics/layers/TerritoryLayer.ts +++ b/src/client/graphics/layers/TerritoryLayer.ts @@ -18,7 +18,7 @@ import { TransformHandler } from "../TransformHandler"; import { UserSettings } from "../../../core/game/UserSettings"; export class TerritoryLayer implements Layer { - private userSettings: UserSettings; + private readonly userSettings: UserSettings; private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D; private imageData: ImageData; @@ -26,14 +26,14 @@ export class TerritoryLayer implements Layer { private cachedTerritoryPatternsEnabled: boolean | undefined; - private tileToRenderQueue: PriorityQueue<{ + private readonly tileToRenderQueue: PriorityQueue<{ tile: TileRef; lastUpdate: number; }> = new PriorityQueue((a, b) => { return a.lastUpdate - b.lastUpdate; }); - private random = new PseudoRandom(123); - private theme: Theme; + private readonly random = new PseudoRandom(123); + private readonly theme: Theme; // Used for spawn highlighting private highlightCanvas: HTMLCanvasElement; @@ -42,19 +42,19 @@ export class TerritoryLayer implements Layer { private highlightedTerritory: PlayerView | null = null; private alternativeView = false; - private lastDragTime = 0; - private nodrawDragDuration = 200; + private readonly lastDragTime = 0; + private readonly nodrawDragDuration = 200; private lastMousePosition: { x: number; y: number } | null = null; - private refreshRate = 10; //refresh every 10ms + private readonly refreshRate = 10; //refresh every 10ms private lastRefresh = 0; private lastFocusedPlayer: PlayerView | null = null; constructor( - private game: GameView, - private eventBus: EventBus, - private transformHandler: TransformHandler, + private readonly game: GameView, + private readonly eventBus: EventBus, + private readonly transformHandler: TransformHandler, userSettings: UserSettings, ) { this.userSettings = userSettings; diff --git a/src/client/graphics/layers/UILayer.ts b/src/client/graphics/layers/UILayer.ts index a106dfe4c..8a6c26099 100644 --- a/src/client/graphics/layers/UILayer.ts +++ b/src/client/graphics/layers/UILayer.ts @@ -27,14 +27,14 @@ const PROGRESSBAR_HEIGHT = 3; // Height of a bar export class UILayer implements Layer { private canvas: HTMLCanvasElement; private context: CanvasRenderingContext2D | null; - private theme: Theme | null = null; - private userSettings: UserSettings = new UserSettings(); + private readonly theme: Theme | null = null; + private readonly userSettings: UserSettings = new UserSettings(); private selectionAnimTime = 0; - private allProgressBars: Map< + private readonly allProgressBars: Map< number, { unit: UnitView; progressBar: ProgressBar } > = new Map(); - private allHealthBars: Map = new Map(); + private readonly allHealthBars: Map = new Map(); // Keep track of currently selected unit private selectedUnit: UnitView | null = null; @@ -49,9 +49,9 @@ export class UILayer implements Layer { private readonly SELECTION_BOX_SIZE = 6; // Size of the selection box (should be larger than the warship) constructor( - private game: GameView, - private eventBus: EventBus, - private transformHandler: TransformHandler, + private readonly game: GameView, + private readonly eventBus: EventBus, + private readonly transformHandler: TransformHandler, ) { this.theme = game.config().theme(); } diff --git a/src/client/graphics/layers/UnitDisplay.ts b/src/client/graphics/layers/UnitDisplay.ts index cff1c0602..5dfbd319b 100644 --- a/src/client/graphics/layers/UnitDisplay.ts +++ b/src/client/graphics/layers/UnitDisplay.ts @@ -17,7 +17,7 @@ import samLauncherIcon from "../../../../resources/non-commercial/svg/SamLaunche export class UnitDisplay extends LitElement implements Layer { public game: GameView; public eventBus: EventBus; - private _selectedStructure: UnitType | null = null; + private readonly _selectedStructure: UnitType | null = null; private _cities = 0; private _factories = 0; private _missileSilo = 0; diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index 577a87206..2dedfe50c 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -32,15 +32,15 @@ export class UnitLayer implements Layer { private transportShipTrailCanvas: HTMLCanvasElement; private unitTrailContext: CanvasRenderingContext2D; - private unitToTrail = new Map(); + private readonly unitToTrail = new Map(); - private theme: Theme; + private readonly theme: Theme; private alternateView = false; - private oldShellTile = new Map(); + private readonly oldShellTile = new Map(); - private transformHandler: TransformHandler; + private readonly transformHandler: TransformHandler; // Selected unit property as suggested in the review comment private selectedUnit: UnitView | null = null; @@ -49,8 +49,8 @@ export class UnitLayer implements Layer { private readonly WARSHIP_SELECTION_RADIUS = 10; // Radius in game cells for warship selection hit zone constructor( - private game: GameView, - private eventBus: EventBus, + private readonly game: GameView, + private readonly eventBus: EventBus, transformHandler: TransformHandler, ) { this.theme = game.config().theme(); diff --git a/src/core/EventBus.ts b/src/core/EventBus.ts index d696ee013..2e0eacdc5 100644 --- a/src/core/EventBus.ts +++ b/src/core/EventBus.ts @@ -6,7 +6,7 @@ export type EventConstructor = new ( ) => T; export class EventBus { - private listeners: Map void>> = + private readonly listeners: Map void>> = new Map(); emit(event: T): void { diff --git a/src/core/GameRunner.ts b/src/core/GameRunner.ts index 6599d84dc..b9c23465f 100644 --- a/src/core/GameRunner.ts +++ b/src/core/GameRunner.ts @@ -83,7 +83,7 @@ export async function createGameRunner( } export class GameRunner { - private turns: Turn[] = []; + private readonly turns: Turn[] = []; private currTurn = 0; private isExecuting = false; @@ -91,8 +91,8 @@ export class GameRunner { constructor( public game: Game, - private execManager: Executor, - private callBack: (gu: GameUpdateViewData | ErrorUpdate) => void, + private readonly execManager: Executor, + private readonly callBack: (gu: GameUpdateViewData | ErrorUpdate) => void, ) {} init() { diff --git a/src/core/PatternDecoder.ts b/src/core/PatternDecoder.ts index c749b1615..60c924f8c 100644 --- a/src/core/PatternDecoder.ts +++ b/src/core/PatternDecoder.ts @@ -1,5 +1,5 @@ export class PatternDecoder { - private bytes: Uint8Array; + private readonly bytes: Uint8Array; readonly height: number; readonly width: number; diff --git a/src/core/PseudoRandom.ts b/src/core/PseudoRandom.ts index d0670ba5f..824e4ad85 100644 --- a/src/core/PseudoRandom.ts +++ b/src/core/PseudoRandom.ts @@ -1,7 +1,7 @@ import seedrandom from "seedrandom"; export class PseudoRandom { - private rng: seedrandom.PRNG; + private readonly rng: seedrandom.PRNG; private static readonly POW36_8 = Math.pow(36, 8); // Pre-compute 36^8 diff --git a/src/core/configuration/ColorAllocator.ts b/src/core/configuration/ColorAllocator.ts index ccd9d2876..d0e123147 100644 --- a/src/core/configuration/ColorAllocator.ts +++ b/src/core/configuration/ColorAllocator.ts @@ -20,9 +20,9 @@ extend([labPlugin]); export class ColorAllocator { private availableColors: Colord[]; - private fallbackColors: Colord[]; - private assigned = new Map(); - private teamPlayerColors = new Map(); + private readonly fallbackColors: Colord[]; + private readonly assigned = new Map(); + private readonly teamPlayerColors = new Map(); constructor(colors: Colord[], fallback: Colord[]) { this.availableColors = [...colors]; diff --git a/src/core/configuration/DefaultConfig.ts b/src/core/configuration/DefaultConfig.ts index 70063af15..a531bb2eb 100644 --- a/src/core/configuration/DefaultConfig.ts +++ b/src/core/configuration/DefaultConfig.ts @@ -209,13 +209,13 @@ export abstract class DefaultServerConfig implements ServerConfig { } export class DefaultConfig implements Config { - private pastelTheme: PastelTheme = new PastelTheme(); - private pastelThemeDark: PastelThemeDark = new PastelThemeDark(); + private readonly pastelTheme: PastelTheme = new PastelTheme(); + private readonly pastelThemeDark: PastelThemeDark = new PastelThemeDark(); constructor( - private _serverConfig: ServerConfig, - private _gameConfig: GameConfig, - private _userSettings: UserSettings | null, - private _isReplay: boolean, + private readonly _serverConfig: ServerConfig, + private readonly _gameConfig: GameConfig, + private readonly _userSettings: UserSettings | null, + private readonly _isReplay: boolean, ) {} stripePublishableKey(): string { diff --git a/src/core/configuration/PastelTheme.ts b/src/core/configuration/PastelTheme.ts index d9fac4954..61ba532ab 100644 --- a/src/core/configuration/PastelTheme.ts +++ b/src/core/configuration/PastelTheme.ts @@ -10,32 +10,32 @@ import { Theme } from "./Config"; type ColorCache = Map; export class PastelTheme implements Theme { - private borderColorCache: ColorCache = new Map(); - private rand = new PseudoRandom(123); - private humanColorAllocator = new ColorAllocator(humanColors, fallbackColors); - private botColorAllocator = new ColorAllocator(botColors, botColors); - private teamColorAllocator = new ColorAllocator(humanColors, fallbackColors); - private nationColorAllocator = new ColorAllocator(nationColors, nationColors); + private readonly borderColorCache: ColorCache = new Map(); + private readonly rand = new PseudoRandom(123); + private readonly humanColorAllocator = new ColorAllocator(humanColors, fallbackColors); + private readonly botColorAllocator = new ColorAllocator(botColors, botColors); + private readonly teamColorAllocator = new ColorAllocator(humanColors, fallbackColors); + private readonly nationColorAllocator = new ColorAllocator(nationColors, nationColors); /* eslint-disable sort-keys */ - private background = colord({ r: 60, g: 60, b: 60 }); - private shore = colord({ r: 204, g: 203, b: 158 }); - private falloutColors = [ + private readonly background = colord({ r: 60, g: 60, b: 60 }); + private readonly shore = colord({ r: 204, g: 203, b: 158 }); + 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 ]; - private water = colord({ r: 70, g: 132, b: 180 }); - private shorelineWater = colord({ r: 100, g: 143, b: 255 }); + private readonly water = colord({ r: 70, g: 132, b: 180 }); + private readonly shorelineWater = colord({ r: 100, g: 143, b: 255 }); - private _selfColor = colord({ r: 0, g: 255, b: 0 }); - private _allyColor = colord({ r: 255, g: 255, b: 0 }); - private _neutralColor = colord({ r: 128, g: 128, b: 128 }); - private _enemyColor = colord({ r: 255, g: 0, b: 0 }); + 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 _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }); + private readonly _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }); /* eslint-enable sort-keys */ teamColor(team: Team): Colord { diff --git a/src/core/configuration/PastelThemeDark.ts b/src/core/configuration/PastelThemeDark.ts index 17879e8fa..ded3093dd 100644 --- a/src/core/configuration/PastelThemeDark.ts +++ b/src/core/configuration/PastelThemeDark.ts @@ -10,32 +10,32 @@ import { Theme } from "./Config"; type ColorCache = Map; export class PastelThemeDark implements Theme { - private borderColorCache: ColorCache = new Map(); - private rand = new PseudoRandom(123); - private humanColorAllocator = new ColorAllocator(humanColors, fallbackColors); - private botColorAllocator = new ColorAllocator(botColors, botColors); - private teamColorAllocator = new ColorAllocator(humanColors, fallbackColors); - private nationColorAllocator = new ColorAllocator(nationColors, nationColors); + private readonly borderColorCache: ColorCache = new Map(); + private readonly rand = new PseudoRandom(123); + private readonly humanColorAllocator = new ColorAllocator(humanColors, fallbackColors); + private readonly botColorAllocator = new ColorAllocator(botColors, botColors); + private readonly teamColorAllocator = new ColorAllocator(humanColors, fallbackColors); + private readonly nationColorAllocator = new ColorAllocator(nationColors, nationColors); /* eslint-disable sort-keys */ - private background = colord({ r: 0, g: 0, b: 0 }); - private shore = colord({ r: 134, g: 133, b: 88 }); - private falloutColors = [ + private readonly background = colord({ r: 0, g: 0, b: 0 }); + private readonly shore = colord({ r: 134, g: 133, b: 88 }); + 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 ]; - private water = colord({ r: 14, g: 11, b: 30 }); - private shorelineWater = colord({ r: 50, g: 50, b: 50 }); + private readonly water = colord({ r: 14, g: 11, b: 30 }); + private readonly shorelineWater = colord({ r: 50, g: 50, b: 50 }); - private _selfColor = colord({ r: 0, g: 255, b: 0 }); - private _allyColor = colord({ r: 255, g: 255, b: 0 }); - private _neutralColor = colord({ r: 128, g: 128, b: 128 }); - private _enemyColor = colord({ r: 255, g: 0, b: 0 }); + 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 _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }); + private readonly _spawnHighlightColor = colord({ r: 255, g: 213, b: 79 }); /* eslint-enable sort-keys */ teamColor(team: Team): Colord { diff --git a/src/core/execution/AttackExecution.ts b/src/core/execution/AttackExecution.ts index 291468fe8..6dc11d425 100644 --- a/src/core/execution/AttackExecution.ts +++ b/src/core/execution/AttackExecution.ts @@ -19,9 +19,9 @@ export class AttackExecution implements Execution { private breakAlliance = false; private wasAlliedAtInit = false; // Store alliance state at initialization private active = true; - private toConquer = new FlatBinaryHeap(); + private readonly toConquer = new FlatBinaryHeap(); - private random = new PseudoRandom(123); + private readonly random = new PseudoRandom(123); private target: Player | TerraNullius; @@ -31,10 +31,10 @@ export class AttackExecution implements Execution { constructor( private startTroops: number | null = null, - private _owner: Player, - private _targetID: PlayerID | null, - private sourceTile: TileRef | null = null, - private removeTroops = true, + private readonly _owner: Player, + private readonly _targetID: PlayerID | null, + private readonly sourceTile: TileRef | null = null, + private readonly removeTroops = true, ) {} public targetID(): PlayerID | null { diff --git a/src/core/execution/BoatRetreatExecution.ts b/src/core/execution/BoatRetreatExecution.ts index c6afedff1..b4a7e9882 100644 --- a/src/core/execution/BoatRetreatExecution.ts +++ b/src/core/execution/BoatRetreatExecution.ts @@ -3,8 +3,8 @@ import { Execution, Game, Player, UnitType } from "../game/Game"; export class BoatRetreatExecution implements Execution { private active = true; constructor( - private player: Player, - private unitID: number, + private readonly player: Player, + private readonly unitID: number, ) {} init(mg: Game, ticks: number): void {} diff --git a/src/core/execution/BotExecution.ts b/src/core/execution/BotExecution.ts index 533fd8009..f2557c4d1 100644 --- a/src/core/execution/BotExecution.ts +++ b/src/core/execution/BotExecution.ts @@ -5,18 +5,18 @@ import { simpleHash } from "../Util"; export class BotExecution implements Execution { private active = true; - private random: PseudoRandom; + private readonly random: PseudoRandom; private mg: Game; private neighborsTerraNullius = true; private behavior: BotBehavior | null = null; - private attackRate: number; - private attackTick: number; - private triggerRatio: number; - private reserveRatio: number; - private expandRatio: number; + private readonly attackRate: number; + private readonly attackTick: number; + private readonly triggerRatio: number; + private readonly reserveRatio: number; + private readonly expandRatio: number; - constructor(private bot: Player) { + constructor(private readonly bot: Player) { this.random = new PseudoRandom(simpleHash(bot.id())); this.attackRate = this.random.nextInt(40, 80); this.attackTick = this.random.nextInt(0, this.attackRate); diff --git a/src/core/execution/BotSpawner.ts b/src/core/execution/BotSpawner.ts index 29bbaa5fb..a0e9eeaaf 100644 --- a/src/core/execution/BotSpawner.ts +++ b/src/core/execution/BotSpawner.ts @@ -7,11 +7,11 @@ import { TileRef } from "../game/GameMap"; import { simpleHash } from "../Util"; export class BotSpawner { - private random: PseudoRandom; - private bots: SpawnExecution[] = []; + private readonly random: PseudoRandom; + private readonly bots: SpawnExecution[] = []; constructor( - private gs: Game, + private readonly gs: Game, gameID: GameID, ) { this.random = new PseudoRandom(simpleHash(gameID)); diff --git a/src/core/execution/CityExecution.ts b/src/core/execution/CityExecution.ts index f21e19f62..93635258c 100644 --- a/src/core/execution/CityExecution.ts +++ b/src/core/execution/CityExecution.ts @@ -9,7 +9,7 @@ export class CityExecution implements Execution { constructor( private player: Player, - private tile: TileRef, + private readonly tile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/ConstructionExecution.ts b/src/core/execution/ConstructionExecution.ts index 9ed452fbb..9ee7a27d0 100644 --- a/src/core/execution/ConstructionExecution.ts +++ b/src/core/execution/ConstructionExecution.ts @@ -29,8 +29,8 @@ export class ConstructionExecution implements Execution { constructor( private player: Player, - private constructionType: UnitType, - private tile: TileRef, + private readonly constructionType: UnitType, + private readonly tile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/DefensePostExecution.ts b/src/core/execution/DefensePostExecution.ts index 494e59179..33b4776bc 100644 --- a/src/core/execution/DefensePostExecution.ts +++ b/src/core/execution/DefensePostExecution.ts @@ -10,11 +10,11 @@ export class DefensePostExecution implements Execution { private target: Unit | null = null; private lastShellAttack = 0; - private alreadySentShell = new Set(); + private readonly alreadySentShell = new Set(); constructor( private player: Player, - private tile: TileRef, + private readonly tile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/DeleteUnitExecution.ts b/src/core/execution/DeleteUnitExecution.ts index 4bf2f193a..20e7db02d 100644 --- a/src/core/execution/DeleteUnitExecution.ts +++ b/src/core/execution/DeleteUnitExecution.ts @@ -5,8 +5,8 @@ export class DeleteUnitExecution implements Execution { private mg: Game; constructor( - private player: Player, - private unitId: number, + private readonly player: Player, + private readonly unitId: number, ) {} activeDuringSpawnPhase(): boolean { diff --git a/src/core/execution/DonateGoldExecution.ts b/src/core/execution/DonateGoldExecution.ts index 214c7e915..e0b64db75 100644 --- a/src/core/execution/DonateGoldExecution.ts +++ b/src/core/execution/DonateGoldExecution.ts @@ -6,8 +6,8 @@ export class DonateGoldExecution implements Execution { private active = true; constructor( - private sender: Player, - private recipientID: PlayerID, + private readonly sender: Player, + private readonly recipientID: PlayerID, private gold: Gold | null, ) {} diff --git a/src/core/execution/DonateTroopExecution.ts b/src/core/execution/DonateTroopExecution.ts index 00af5de7c..424dd8809 100644 --- a/src/core/execution/DonateTroopExecution.ts +++ b/src/core/execution/DonateTroopExecution.ts @@ -6,8 +6,8 @@ export class DonateTroopsExecution implements Execution { private active = true; constructor( - private sender: Player, - private recipientID: PlayerID, + private readonly sender: Player, + private readonly recipientID: PlayerID, private troops: number | null, ) {} diff --git a/src/core/execution/EmbargoExecution.ts b/src/core/execution/EmbargoExecution.ts index 6c19b47e1..f4d8ed557 100644 --- a/src/core/execution/EmbargoExecution.ts +++ b/src/core/execution/EmbargoExecution.ts @@ -6,8 +6,8 @@ export class EmbargoExecution implements Execution { private target: Player; constructor( - private player: Player, - private targetID: PlayerID, + private readonly player: Player, + private readonly targetID: PlayerID, private readonly action: "start" | "stop", ) {} diff --git a/src/core/execution/EmojiExecution.ts b/src/core/execution/EmojiExecution.ts index 94f84e58d..cbd15f6c1 100644 --- a/src/core/execution/EmojiExecution.ts +++ b/src/core/execution/EmojiExecution.ts @@ -14,9 +14,9 @@ export class EmojiExecution implements Execution { private active = true; constructor( - private requestor: Player, - private recipientID: PlayerID | typeof AllPlayers, - private emoji: number, + private readonly requestor: Player, + private readonly recipientID: PlayerID | typeof AllPlayers, + private readonly emoji: number, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index 5c5e11a7f..122448eda 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -28,12 +28,12 @@ import { simpleHash } from "../Util"; export class Executor { // private random = new PseudoRandom(999) - private random: PseudoRandom; + private readonly random: PseudoRandom; constructor( - private mg: Game, - private gameID: GameID, - private clientID: ClientID, + private readonly mg: Game, + private readonly gameID: GameID, + private readonly clientID: ClientID, ) { // Add one to avoid id collisions with bots. this.random = new PseudoRandom(simpleHash(gameID) + 1); diff --git a/src/core/execution/FactoryExecution.ts b/src/core/execution/FactoryExecution.ts index f9065d0ef..598662ff0 100644 --- a/src/core/execution/FactoryExecution.ts +++ b/src/core/execution/FactoryExecution.ts @@ -8,7 +8,7 @@ export class FactoryExecution implements Execution { private game: Game; constructor( private player: Player, - private tile: TileRef, + private readonly tile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index 1bc782b27..86654e6e1 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -28,25 +28,25 @@ import { closestTwoTiles } from "./Util"; export class FakeHumanExecution implements Execution { private active = true; - private random: PseudoRandom; + private readonly random: PseudoRandom; private behavior: BotBehavior | null = null; private mg: Game; private player: Player | null = null; - private attackRate: number; - private attackTick: number; - private triggerRatio: number; - private reserveRatio: number; - private expandRatio: number; + private readonly attackRate: number; + private readonly attackTick: number; + private readonly triggerRatio: number; + private readonly reserveRatio: number; + private readonly expandRatio: number; - private lastEmojiSent = new Map(); - private lastNukeSent: [Tick, TileRef][] = []; - private embargoMalusApplied = new Set(); - private heckleEmoji: number[]; + private readonly lastEmojiSent = new Map(); + private readonly lastNukeSent: [Tick, TileRef][] = []; + private readonly embargoMalusApplied = new Set(); + private readonly heckleEmoji: number[]; constructor( gameID: GameID, - private nation: Nation, + private readonly nation: Nation, ) { this.random = new PseudoRandom( simpleHash(nation.playerInfo.id) + simpleHash(gameID), diff --git a/src/core/execution/MIRVExecution.ts b/src/core/execution/MIRVExecution.ts index db8de9f24..b6e0b1e9f 100644 --- a/src/core/execution/MIRVExecution.ts +++ b/src/core/execution/MIRVExecution.ts @@ -20,8 +20,8 @@ export class MirvExecution implements Execution { private nuke: Unit | null = null; - private mirvRange = 1500; - private warheadCount = 350; + private readonly mirvRange = 1500; + private readonly warheadCount = 350; private random: PseudoRandom; @@ -34,8 +34,8 @@ export class MirvExecution implements Execution { private speed = -1; constructor( - private player: Player, - private dst: TileRef, + private readonly player: Player, + private readonly dst: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/MarkDisconnectedExecution.ts b/src/core/execution/MarkDisconnectedExecution.ts index 95d530a4a..db0ad5632 100644 --- a/src/core/execution/MarkDisconnectedExecution.ts +++ b/src/core/execution/MarkDisconnectedExecution.ts @@ -2,8 +2,8 @@ import { Execution, Game, Player } from "../game/Game"; export class MarkDisconnectedExecution implements Execution { constructor( - private player: Player, - private isDisconnected: boolean, + private readonly player: Player, + private readonly isDisconnected: boolean, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/MissileSiloExecution.ts b/src/core/execution/MissileSiloExecution.ts index a7cd2bb6c..aa7dbba27 100644 --- a/src/core/execution/MissileSiloExecution.ts +++ b/src/core/execution/MissileSiloExecution.ts @@ -8,7 +8,7 @@ export class MissileSiloExecution implements Execution { constructor( private player: Player, - private tile: TileRef, + private readonly tile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts index d72d894bd..425ee5fc9 100644 --- a/src/core/execution/NukeExecution.ts +++ b/src/core/execution/NukeExecution.ts @@ -24,9 +24,9 @@ export class NukeExecution implements Execution { private pathFinder: ParabolaPathFinder; constructor( - private nukeType: NukeType, - private player: Player, - private dst: TileRef, + private readonly nukeType: NukeType, + private readonly player: Player, + private readonly dst: TileRef, private src?: TileRef | null, private speed = -1, private waitTicks = 0, diff --git a/src/core/execution/PlayerExecution.ts b/src/core/execution/PlayerExecution.ts index c4b60f7ac..bf8740019 100644 --- a/src/core/execution/PlayerExecution.ts +++ b/src/core/execution/PlayerExecution.ts @@ -12,7 +12,7 @@ export class PlayerExecution implements Execution { private mg: Game; private active = true; - constructor(private player: Player) {} + constructor(private readonly player: Player) {} activeDuringSpawnPhase(): boolean { return false; diff --git a/src/core/execution/PortExecution.ts b/src/core/execution/PortExecution.ts index 174681514..54de6ace0 100644 --- a/src/core/execution/PortExecution.ts +++ b/src/core/execution/PortExecution.ts @@ -13,7 +13,7 @@ export class PortExecution implements Execution { constructor( private player: Player, - private tile: TileRef, + private readonly tile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/QuickChatExecution.ts b/src/core/execution/QuickChatExecution.ts index bb4f5f525..5905245fe 100644 --- a/src/core/execution/QuickChatExecution.ts +++ b/src/core/execution/QuickChatExecution.ts @@ -7,10 +7,10 @@ export class QuickChatExecution implements Execution { private active = true; constructor( - private sender: Player, - private recipientID: PlayerID, - private quickChatKey: string, - private target: PlayerID | undefined, + private readonly sender: Player, + private readonly recipientID: PlayerID, + private readonly quickChatKey: string, + private readonly target: PlayerID | undefined, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/RailroadExecution.ts b/src/core/execution/RailroadExecution.ts index 00aef6682..436178b26 100644 --- a/src/core/execution/RailroadExecution.ts +++ b/src/core/execution/RailroadExecution.ts @@ -8,9 +8,9 @@ export class RailroadExecution implements Execution { private active = true; private headIndex = 0; private tailIndex = 0; - private increment = 3; - private railTiles: RailTile[] = []; - constructor(private railRoad: Railroad) { + private readonly increment = 3; + private readonly railTiles: RailTile[] = []; + constructor(private readonly railRoad: Railroad) { this.tailIndex = railRoad.tiles.length; } diff --git a/src/core/execution/RetreatExecution.ts b/src/core/execution/RetreatExecution.ts index 3383aec4c..7bd033081 100644 --- a/src/core/execution/RetreatExecution.ts +++ b/src/core/execution/RetreatExecution.ts @@ -8,8 +8,8 @@ export class RetreatExecution implements Execution { private startTick: number; private mg: Game; constructor( - private player: Player, - private attackID: string, + private readonly player: Player, + private readonly attackID: string, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/SAMLauncherExecution.ts b/src/core/execution/SAMLauncherExecution.ts index 552c2e29d..ae8f8f083 100644 --- a/src/core/execution/SAMLauncherExecution.ts +++ b/src/core/execution/SAMLauncherExecution.ts @@ -21,11 +21,11 @@ type Target = { */ class SAMTargetingSystem { // Store unreachable nukes so the SAM won't compute an interception point for them every frame - private nukesToIgnore: Set = new Set(); + private readonly nukesToIgnore: Set = new Set(); constructor( - private mg: Game, - private sam: Unit, + private readonly mg: Game, + private readonly sam: Unit, ) {} updateUnreachableNukes(nearbyUnits: { unit: Unit; distSquared: number }[]) { @@ -131,15 +131,15 @@ export class SAMLauncherExecution implements Execution { // As MIRV go very fast we have to detect them very early but we only // shoot the one targeting very close (MIRVWarheadProtectionRadius) - private MIRVWarheadSearchRadius = 400; - private MIRVWarheadProtectionRadius = 50; + private readonly MIRVWarheadSearchRadius = 400; + private readonly MIRVWarheadProtectionRadius = 50; private targetingSystem: SAMTargetingSystem; private pseudoRandom: PseudoRandom | undefined; constructor( private player: Player, - private tile: TileRef | null, + private readonly tile: TileRef | null, private sam: Unit | null = null, ) { if (sam !== null) { diff --git a/src/core/execution/SAMMissileExecution.ts b/src/core/execution/SAMMissileExecution.ts index 7871991ff..88babace7 100644 --- a/src/core/execution/SAMMissileExecution.ts +++ b/src/core/execution/SAMMissileExecution.ts @@ -19,11 +19,11 @@ export class SAMMissileExecution implements Execution { private speed = 0; constructor( - private spawn: TileRef, - private _owner: Player, - private ownerUnit: Unit, - private target: Unit, - private targetTile: TileRef, + private readonly spawn: TileRef, + private readonly _owner: Player, + private readonly ownerUnit: Unit, + private readonly target: Unit, + private readonly targetTile: TileRef, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/ShellExecution.ts b/src/core/execution/ShellExecution.ts index 5b5f7348f..3aabba1d5 100644 --- a/src/core/execution/ShellExecution.ts +++ b/src/core/execution/ShellExecution.ts @@ -12,10 +12,10 @@ export class ShellExecution implements Execution { private random: PseudoRandom; constructor( - private spawn: TileRef, - private _owner: Player, - private ownerUnit: Unit, - private target: Unit, + private readonly spawn: TileRef, + private readonly _owner: Player, + private readonly ownerUnit: Unit, + private readonly target: Unit, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/SpawnExecution.ts b/src/core/execution/SpawnExecution.ts index eaea6e539..64c4a0da3 100644 --- a/src/core/execution/SpawnExecution.ts +++ b/src/core/execution/SpawnExecution.ts @@ -9,7 +9,7 @@ export class SpawnExecution implements Execution { private mg: Game; constructor( - private playerInfo: PlayerInfo, + private readonly playerInfo: PlayerInfo, public readonly tile: TileRef, ) {} diff --git a/src/core/execution/TargetPlayerExecution.ts b/src/core/execution/TargetPlayerExecution.ts index e6e454534..a3ea4cb15 100644 --- a/src/core/execution/TargetPlayerExecution.ts +++ b/src/core/execution/TargetPlayerExecution.ts @@ -6,8 +6,8 @@ export class TargetPlayerExecution implements Execution { private active = true; constructor( - private requestor: Player, - private targetID: PlayerID, + private readonly requestor: Player, + private readonly targetID: PlayerID, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/TradeShipExecution.ts b/src/core/execution/TradeShipExecution.ts index 74a5e35fb..2a4bb90b2 100644 --- a/src/core/execution/TradeShipExecution.ts +++ b/src/core/execution/TradeShipExecution.ts @@ -21,8 +21,8 @@ export class TradeShipExecution implements Execution { private tilesTraveled = 0; constructor( - private origOwner: Player, - private srcPort: Unit, + private readonly origOwner: Player, + private readonly srcPort: Unit, private _dstPort: Unit, ) {} diff --git a/src/core/execution/TrainExecution.ts b/src/core/execution/TrainExecution.ts index 8465e44e7..2fafd2af3 100644 --- a/src/core/execution/TrainExecution.ts +++ b/src/core/execution/TrainExecution.ts @@ -15,21 +15,21 @@ export class TrainExecution implements Execution { private active = true; private mg: Game | null = null; private train: Unit | null = null; - private cars: Unit[] = []; + private readonly cars: Unit[] = []; private hasCargo = false; private currentTile = 0; - private spacing = 2; - private usedTiles: TileRef[] = []; // used for cars behind + private readonly spacing = 2; + private readonly usedTiles: TileRef[] = []; // used for cars behind private stations: TrainStation[] = []; private currentRailroad: OrientedRailroad | null = null; - private speed = 2; + private readonly speed = 2; constructor( - private railNetwork: RailNetwork, - private player: Player, - private source: TrainStation, - private destination: TrainStation, - private numCars: number, + private readonly railNetwork: RailNetwork, + private readonly player: Player, + private readonly source: TrainStation, + private readonly destination: TrainStation, + private readonly numCars: number, ) {} public owner(): Player { diff --git a/src/core/execution/TrainStationExecution.ts b/src/core/execution/TrainStationExecution.ts index cebe41591..8293bc745 100644 --- a/src/core/execution/TrainStationExecution.ts +++ b/src/core/execution/TrainStationExecution.ts @@ -8,12 +8,12 @@ export class TrainStationExecution implements Execution { private active = true; private random: PseudoRandom; private station: TrainStation | null = null; - private numCars = 5; + private readonly numCars = 5; private lastSpawnTick = 0; - private ticksCooldown = 10; // Minimum cooldown between two trains + private readonly ticksCooldown = 10; // Minimum cooldown between two trains constructor( - private unit: Unit, - private spawnTrains?: boolean, // If set, the station will spawn trains + private readonly unit: Unit, + private readonly spawnTrains?: boolean, // If set, the station will spawn trains ) { this.unit.setTrainStation(true); } diff --git a/src/core/execution/TransportShipExecution.ts b/src/core/execution/TransportShipExecution.ts index 6901c6116..ce0d4646d 100644 --- a/src/core/execution/TransportShipExecution.ts +++ b/src/core/execution/TransportShipExecution.ts @@ -18,7 +18,7 @@ export class TransportShipExecution implements Execution { private lastMove: number; // TODO: make this configurable - private ticksPerMove = 1; + private readonly ticksPerMove = 1; private active = true; @@ -34,9 +34,9 @@ export class TransportShipExecution implements Execution { private pathFinder: PathFinder; constructor( - private attacker: Player, - private targetID: PlayerID | null, - private ref: TileRef, + private readonly attacker: Player, + private readonly targetID: PlayerID | null, + private readonly ref: TileRef, private startTroops: number, private src: TileRef | null, ) {} diff --git a/src/core/execution/UpgradeStructureExecution.ts b/src/core/execution/UpgradeStructureExecution.ts index 04bf5d787..15f53c4e0 100644 --- a/src/core/execution/UpgradeStructureExecution.ts +++ b/src/core/execution/UpgradeStructureExecution.ts @@ -2,11 +2,11 @@ import { Execution, Game, Player, Unit } from "../game/Game"; export class UpgradeStructureExecution implements Execution { private structure: Unit | undefined; - private cost: bigint; + private readonly cost: bigint; constructor( - private player: Player, - private unitId: number, + private readonly player: Player, + private readonly unitId: number, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/WarshipExecution.ts b/src/core/execution/WarshipExecution.ts index ba323a3d5..5b67cff7c 100644 --- a/src/core/execution/WarshipExecution.ts +++ b/src/core/execution/WarshipExecution.ts @@ -19,10 +19,10 @@ export class WarshipExecution implements Execution { private mg: Game; private pathfinder: PathFinder; private lastShellAttack = 0; - private alreadySentShell = new Set(); + private readonly alreadySentShell = new Set(); constructor( - private input: (UnitParams & OwnerComp) | Unit, + private readonly input: (UnitParams & OwnerComp) | Unit, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/alliance/AllianceRequestExecution.ts b/src/core/execution/alliance/AllianceRequestExecution.ts index 419b8b92c..ee2e929a3 100644 --- a/src/core/execution/alliance/AllianceRequestExecution.ts +++ b/src/core/execution/alliance/AllianceRequestExecution.ts @@ -5,8 +5,8 @@ export class AllianceRequestExecution implements Execution { private recipient: Player | null = null; constructor( - private requestor: Player, - private recipientID: PlayerID, + private readonly requestor: Player, + private readonly recipientID: PlayerID, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/alliance/AllianceRequestReplyExecution.ts b/src/core/execution/alliance/AllianceRequestReplyExecution.ts index bd3d90a58..cceebbf1b 100644 --- a/src/core/execution/alliance/AllianceRequestReplyExecution.ts +++ b/src/core/execution/alliance/AllianceRequestReplyExecution.ts @@ -5,9 +5,9 @@ export class AllianceRequestReplyExecution implements Execution { private requestor: Player | null = null; constructor( - private requestorID: PlayerID, - private recipient: Player, - private accept: boolean, + private readonly requestorID: PlayerID, + private readonly recipient: Player, + private readonly accept: boolean, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/alliance/BreakAllianceExecution.ts b/src/core/execution/alliance/BreakAllianceExecution.ts index de614c1cc..5e875384b 100644 --- a/src/core/execution/alliance/BreakAllianceExecution.ts +++ b/src/core/execution/alliance/BreakAllianceExecution.ts @@ -6,8 +6,8 @@ export class BreakAllianceExecution implements Execution { private mg: Game | null = null; constructor( - private requestor: Player, - private recipientID: PlayerID, + private readonly requestor: Player, + private readonly recipientID: PlayerID, ) {} init(mg: Game, ticks: number): void { diff --git a/src/core/execution/utils/BotBehavior.ts b/src/core/execution/utils/BotBehavior.ts index dae59b5af..bf5c92a4e 100644 --- a/src/core/execution/utils/BotBehavior.ts +++ b/src/core/execution/utils/BotBehavior.ts @@ -18,15 +18,15 @@ export class BotBehavior { private enemy: Player | null = null; private enemyUpdated: Tick; - private assistAcceptEmoji = flattenedEmojiTable.indexOf("👍"); + private readonly assistAcceptEmoji = flattenedEmojiTable.indexOf("👍"); constructor( - private random: PseudoRandom, - private game: Game, - private player: Player, - private triggerRatio: number, - private reserveRatio: number, - private expandRatio: number, + private readonly random: PseudoRandom, + private readonly game: Game, + private readonly player: Player, + private readonly triggerRatio: number, + private readonly reserveRatio: number, + private readonly expandRatio: number, ) {} handleAllianceRequests() { diff --git a/src/core/game/AllianceRequestImpl.ts b/src/core/game/AllianceRequestImpl.ts index 9aa993686..6fbb7bd0c 100644 --- a/src/core/game/AllianceRequestImpl.ts +++ b/src/core/game/AllianceRequestImpl.ts @@ -4,10 +4,10 @@ import { GameImpl } from "./GameImpl"; export class AllianceRequestImpl implements AllianceRequest { constructor( - private requestor_: Player, - private recipient_: Player, - private tickCreated: number, - private game: GameImpl, + private readonly requestor_: Player, + private readonly recipient_: Player, + private readonly tickCreated: number, + private readonly game: GameImpl, ) {} requestor(): Player { diff --git a/src/core/game/AttackImpl.ts b/src/core/game/AttackImpl.ts index dc4e59681..a78b02e6e 100644 --- a/src/core/game/AttackImpl.ts +++ b/src/core/game/AttackImpl.ts @@ -10,13 +10,13 @@ export class AttackImpl implements Attack { public _retreated = false; constructor( - private _id: string, - private _target: Player | TerraNullius, - private _attacker: Player, + private readonly _id: string, + private readonly _target: Player | TerraNullius, + private readonly _attacker: Player, private _troops: number, - private _sourceTile: TileRef | null, - private _border: Set, - private _mg: GameImpl, + private readonly _sourceTile: TileRef | null, + private readonly _border: Set, + private readonly _mg: GameImpl, ) {} sourceTile(): TileRef | null { diff --git a/src/core/game/BinaryLoaderGameMapLoader.ts b/src/core/game/BinaryLoaderGameMapLoader.ts index 5649e8d1b..233adbd98 100644 --- a/src/core/game/BinaryLoaderGameMapLoader.ts +++ b/src/core/game/BinaryLoaderGameMapLoader.ts @@ -11,7 +11,7 @@ type NationMapModule = { }; export class BinaryLoaderGameMapLoader implements GameMapLoader { - private maps: Map; + private readonly maps: Map; constructor() { this.maps = new Map(); diff --git a/src/core/game/FetchGameMapLoader.ts b/src/core/game/FetchGameMapLoader.ts index 5b7407142..5bdeed62d 100644 --- a/src/core/game/FetchGameMapLoader.ts +++ b/src/core/game/FetchGameMapLoader.ts @@ -3,7 +3,7 @@ import { GameMapType } from "./Game"; import { MapManifestSchema } from "./TerrainMapLoader"; export class FetchGameMapLoader implements GameMapLoader { - private maps: Map; + private readonly maps: Map; public constructor( private readonly prefix: string, diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 983997c88..57f055937 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -285,7 +285,7 @@ export class Nation { export class Cell { public index: number; - private strRepr: string; + private readonly strRepr: string; constructor( public readonly x: number, diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index 4eb4e58f2..1a0d5541d 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -65,8 +65,8 @@ export class GameImpl implements Game { _playersBySmallID: Player[] = []; private execs: Execution[] = []; - private _width: number; - private _height: number; + private readonly _width: number; + private readonly _height: number; _terraNullius: TerraNulliusImpl; allianceRequests: AllianceRequestImpl[] = []; @@ -76,22 +76,22 @@ export class GameImpl implements Game { private _nextUnitID = 1; private updates: GameUpdates = createGameUpdatesMap(); - private unitGrid: UnitGrid; + private readonly unitGrid: UnitGrid; private playerTeams: Team[]; - private botTeam: Team = ColoredTeams.Bot; - private _railNetwork: RailNetwork = createRailNetwork(this); + private readonly botTeam: Team = ColoredTeams.Bot; + private readonly _railNetwork: RailNetwork = createRailNetwork(this); // Used to assign unique IDs to each new alliance private nextAllianceID = 0; constructor( - private _humans: PlayerInfo[], - private _nations: Nation[], - private _map: GameMap, - private miniGameMap: GameMap, - private _config: Config, - private _stats: Stats, + private readonly _humans: PlayerInfo[], + private readonly _nations: Nation[], + private readonly _map: GameMap, + private readonly miniGameMap: GameMap, + private readonly _config: Config, + private readonly _stats: Stats, ) { this._terraNullius = new TerraNulliusImpl(); this._width = _map.width(); diff --git a/src/core/game/GameMap.ts b/src/core/game/GameMap.ts index 995e3b5d4..e2e336a3b 100644 --- a/src/core/game/GameMap.ts +++ b/src/core/game/GameMap.ts @@ -79,7 +79,7 @@ export class GameMapImpl implements GameMap { width: number, height: number, terrainData: Uint8Array, - private numLandTiles_: number, + private readonly numLandTiles_: number, ) { if (terrainData.length !== width * height) { throw new Error( diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts index 779e0be37..01a08f59e 100644 --- a/src/core/game/GameView.ts +++ b/src/core/game/GameView.ts @@ -47,10 +47,10 @@ type PlayerCosmetics = { export class UnitView { public _wasUpdated = true; public lastPos: TileRef[] = []; - private _createdAt: Tick; + private readonly _createdAt: Tick; constructor( - private gameView: GameView, + private readonly gameView: GameView, private data: UnitUpdate, ) { this.lastPos.push(data.pos); @@ -179,10 +179,10 @@ export class UnitView { export class PlayerView { public anonymousName: string | null = null; - private decoder?: PatternDecoder; + private readonly decoder?: PatternDecoder; constructor( - private game: GameView, + private readonly game: GameView, public data: PlayerUpdate, public nameData: NameViewData, public cosmetics: PlayerCosmetics, @@ -363,29 +363,29 @@ export class PlayerView { export class GameView implements GameMap { private lastUpdate: GameUpdateViewData | null; - private smallIDToID = new Map(); - private _players = new Map(); - private _units = new Map(); + private readonly smallIDToID = new Map(); + private readonly _players = new Map(); + private readonly _units = new Map(); private updatedTiles: TileRef[] = []; private _myPlayer: PlayerView | null = null; private _focusedPlayer: PlayerView | null = null; - private unitGrid: UnitGrid; + private readonly unitGrid: UnitGrid; - private toDelete = new Set(); + private readonly toDelete = new Set(); - private _cosmetics: Map = new Map(); + private readonly _cosmetics: Map = new Map(); - private _map: GameMap; + private readonly _map: GameMap; constructor( public worker: WorkerClient, - private _config: Config, - private _mapData: TerrainMapData, - private _myClientID: ClientID, - private _gameID: GameID, - private _hunans: Player[], + private readonly _config: Config, + private readonly _mapData: TerrainMapData, + private readonly _myClientID: ClientID, + private readonly _gameID: GameID, + private readonly _hunans: Player[], ) { this._map = this._mapData.gameMap; this.lastUpdate = null; diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index babdca2b6..ad0dc676c 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -75,26 +75,26 @@ export class PlayerImpl implements Player { markedTraitorTick = -1; - private embargoes = new Map(); + private readonly embargoes = new Map(); public _borderTiles: Set = new Set(); public _units: Unit[] = []; public _tiles: Set = new Set(); - private _name: string; - private _displayName: string; + private readonly _name: string; + private readonly _displayName: string; public pastOutgoingAllianceRequests: AllianceRequest[] = []; - private _expiredAlliances: Alliance[] = []; + private readonly _expiredAlliances: Alliance[] = []; - private targets_: Target[] = []; + private readonly targets_: Target[] = []; - private outgoingEmojis_: EmojiMessage[] = []; + private readonly outgoingEmojis_: EmojiMessage[] = []; - private sentDonations: Donation[] = []; + private readonly sentDonations: Donation[] = []; - private relations = new Map(); + private readonly relations = new Map(); private lastDeleteUnitTick: Tick = -1; @@ -106,8 +106,8 @@ export class PlayerImpl implements Player { private _isDisconnected = false; constructor( - private mg: GameImpl, - private _smallID: number, + private readonly mg: GameImpl, + private readonly _smallID: number, private readonly playerInfo: PlayerInfo, startTroops: number, private readonly _team: Team | null, diff --git a/src/core/game/RailNetworkImpl.ts b/src/core/game/RailNetworkImpl.ts index bb7b03450..cca3cb3e6 100644 --- a/src/core/game/RailNetworkImpl.ts +++ b/src/core/game/RailNetworkImpl.ts @@ -21,7 +21,7 @@ export type StationManager = { }; export class StationManagerImpl implements StationManager { - private stations: Set = new Set(); + private readonly stations: Set = new Set(); addStation(station: TrainStation) { this.stations.add(station); @@ -49,7 +49,7 @@ export type RailPathFinderService = { }; class RailPathFinderServiceImpl implements RailPathFinderService { - constructor(private game: Game) {} + constructor(private readonly game: Game) {} findTilePath(from: TileRef, to: TileRef): TileRef[] { const astar = new MiniAStar( @@ -88,12 +88,12 @@ export function createRailNetwork(game: Game): RailNetwork { } export class RailNetworkImpl implements RailNetwork { - private maxConnectionDistance = 4; + private readonly maxConnectionDistance = 4; constructor( - private game: Game, - private stationManager: StationManager, - private pathService: RailPathFinderService, + private readonly game: Game, + private readonly stationManager: StationManager, + private readonly pathService: RailPathFinderService, ) {} connectStation(station: TrainStation) { diff --git a/src/core/game/Railroad.ts b/src/core/game/Railroad.ts index 2a6151663..f415eede3 100644 --- a/src/core/game/Railroad.ts +++ b/src/core/game/Railroad.ts @@ -43,10 +43,10 @@ export function getOrientedRailroad( * Wrap a railroad with a direction so it always starts at tiles[0] */ export class OrientedRailroad { - private tiles: TileRef[] = []; + private readonly tiles: TileRef[] = []; constructor( - private railroad: Railroad, - private forward: boolean, + private readonly railroad: Railroad, + private readonly forward: boolean, ) { this.tiles = this.forward ? this.railroad.tiles diff --git a/src/core/game/TerrainSearchMap.ts b/src/core/game/TerrainSearchMap.ts index bbcfe420a..4fc778952 100644 --- a/src/core/game/TerrainSearchMap.ts +++ b/src/core/game/TerrainSearchMap.ts @@ -5,9 +5,9 @@ export enum SearchMapTileType { } export class TerrainSearchMap { - private width: number; - private height: number; - private mapData: Uint8Array; + private readonly width: number; + private readonly height: number; + private readonly mapData: Uint8Array; constructor(buffer: SharedArrayBuffer) { this.mapData = new Uint8Array(buffer); diff --git a/src/core/game/TrainStation.ts b/src/core/game/TrainStation.ts index 69d420e4a..3d6856f9b 100644 --- a/src/core/game/TrainStation.ts +++ b/src/core/game/TrainStation.ts @@ -37,7 +37,7 @@ class CityStopHandler implements TrainStopHandler { } class PortStopHandler implements TrainStopHandler { - constructor(private random: PseudoRandom) {} + constructor(private readonly random: PseudoRandom) {} onStop( mg: Game, station: TrainStation, @@ -88,10 +88,10 @@ export class TrainStation { private readonly stopHandlers: Partial> = {}; private cluster: Cluster | null; - private railroads: Set = new Set(); + private readonly railroads: Set = new Set(); constructor( - private mg: Game, + private readonly mg: Game, public unit: Unit, ) { this.stopHandlers = createTrainStopHandlers(new PseudoRandom(mg.ticks())); @@ -173,7 +173,7 @@ export class TrainStation { * Make the trainstation usable with A* */ export class TrainStationMapAdapter implements GraphAdapter { - constructor(private game: Game) {} + constructor(private readonly game: Game) {} neighbors(node: TrainStation): TrainStation[] { return node.neighbors(); diff --git a/src/core/game/UnitGrid.ts b/src/core/game/UnitGrid.ts index f7bd2dabb..ceeef2ede 100644 --- a/src/core/game/UnitGrid.ts +++ b/src/core/game/UnitGrid.ts @@ -8,10 +8,10 @@ export type UnitPredicate = (value: { }) => boolean; export class UnitGrid { - private grid: Map>[][]; + private readonly grid: Map>[][]; private readonly cellSize = 100; - constructor(private gm: GameMap) { + constructor(private readonly gm: GameMap) { this.grid = Array(Math.ceil(gm.height() / this.cellSize)) .fill(null) .map(() => diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts index c7faa1650..037f0e23b 100644 --- a/src/core/game/UnitImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -29,22 +29,22 @@ export class UnitImpl implements Unit { private _lastOwner: PlayerImpl | null = null; private _troops: number; // Number of missiles in cooldown, if empty all missiles are ready. - private _missileTimerQueue: number[] = []; + private readonly _missileTimerQueue: number[] = []; private _hasTrainStation = false; private _patrolTile: TileRef | undefined; private _level = 1; private _targetable = true; private _loaded: boolean | undefined; - private _trainType: TrainType | undefined; + private readonly _trainType: TrainType | undefined; // Nuke only private _trajectoryIndex = 0; - private _trajectory: TrajectoryTile[]; + private readonly _trajectory: TrajectoryTile[]; constructor( - private _type: UnitType, - private mg: GameImpl, + private readonly _type: UnitType, + private readonly mg: GameImpl, private _tile: TileRef, - private _id: number, + private readonly _id: number, public _owner: PlayerImpl, params: AllUnitParams = {}, ) { diff --git a/src/core/pathfinding/MiniAStar.ts b/src/core/pathfinding/MiniAStar.ts index 5336e525a..c4c227b04 100644 --- a/src/core/pathfinding/MiniAStar.ts +++ b/src/core/pathfinding/MiniAStar.ts @@ -5,8 +5,8 @@ import { Cell } from "../game/Game"; export class GameMapAdapter implements GraphAdapter { constructor( - private gameMap: GameMap, - private waterPath: boolean, + private readonly gameMap: GameMap, + private readonly waterPath: boolean, ) {} neighbors(node: TileRef): TileRef[] { @@ -27,13 +27,13 @@ export class GameMapAdapter implements GraphAdapter { } } export class MiniAStar implements AStar { - private aStar: AStar; + private readonly aStar: AStar; constructor( - private gameMap: GameMap, - private miniMap: GameMap, - private src: TileRef | TileRef[], - private dst: TileRef, + private readonly gameMap: GameMap, + private readonly miniMap: GameMap, + private readonly src: TileRef | TileRef[], + private readonly dst: TileRef, iterations: number, maxTries: number, waterPath = true, diff --git a/src/core/pathfinding/PathFinding.ts b/src/core/pathfinding/PathFinding.ts index 79d527c88..ba5c32793 100644 --- a/src/core/pathfinding/PathFinding.ts +++ b/src/core/pathfinding/PathFinding.ts @@ -8,7 +8,7 @@ import { PseudoRandom } from "../PseudoRandom"; const parabolaMinHeight = 50; export class ParabolaPathFinder { - constructor(private mg: GameMap) {} + constructor(private readonly mg: GameMap) {} private curve: DistanceBasedBezierCurve | undefined; computeControlPoints( @@ -68,8 +68,8 @@ export class ParabolaPathFinder { export class AirPathFinder { constructor( - private mg: GameMap, - private random: PseudoRandom, + private readonly mg: GameMap, + private readonly random: PseudoRandom, ) {} nextTile(tile: TileRef, dst: TileRef): TileRef | true { @@ -110,8 +110,8 @@ export class PathFinder { private computeFinished = true; private constructor( - private game: Game, - private newAStar: (curr: TileRef, dst: TileRef) => AStar, + private readonly game: Game, + private readonly newAStar: (curr: TileRef, dst: TileRef) => AStar, ) {} public static Mini( diff --git a/src/core/pathfinding/SerialAStar.ts b/src/core/pathfinding/SerialAStar.ts index 01f166f72..e6590d59f 100644 --- a/src/core/pathfinding/SerialAStar.ts +++ b/src/core/pathfinding/SerialAStar.ts @@ -12,32 +12,32 @@ export type GraphAdapter = { }; export class SerialAStar implements AStar { - private fwdOpenSet: FastPriorityQueue<{ + private readonly fwdOpenSet: FastPriorityQueue<{ tile: NodeType; fScore: number; }>; - private bwdOpenSet: FastPriorityQueue<{ + private readonly bwdOpenSet: FastPriorityQueue<{ tile: NodeType; fScore: number; }>; - private fwdCameFrom = new Map(); - private bwdCameFrom = new Map(); - private fwdGScore = new Map(); - private bwdGScore = new Map(); + private readonly fwdCameFrom = new Map(); + private readonly bwdCameFrom = new Map(); + private readonly fwdGScore = new Map(); + private readonly bwdGScore = new Map(); private meetingPoint: NodeType | null = null; public completed = false; - private sources: NodeType[]; - private closestSource: NodeType; + private readonly sources: NodeType[]; + private readonly closestSource: NodeType; constructor( src: NodeType | NodeType[], - private dst: NodeType, - private iterations: number, + private readonly dst: NodeType, + private readonly iterations: number, private maxTries: number, - private graph: GraphAdapter, - private directionChangePenalty = 0, + private readonly graph: GraphAdapter, + private readonly directionChangePenalty = 0, ) { this.fwdOpenSet = new FastPriorityQueue((a, b) => a.fScore < b.fScore); this.bwdOpenSet = new FastPriorityQueue((a, b) => a.fScore < b.fScore); diff --git a/src/core/utilities/Line.ts b/src/core/utilities/Line.ts index 57aea1e6c..9f100b91a 100644 --- a/src/core/utilities/Line.ts +++ b/src/core/utilities/Line.ts @@ -2,8 +2,8 @@ type Point = { x: number; y: number }; export class BezenhamLine { constructor( - private p1: Point, - private p2: Point, + private readonly p1: Point, + private readonly p2: Point, ) { this.dx = Math.abs(p2.x - p1.x); this.dy = Math.abs(p2.y - p1.y); @@ -12,10 +12,10 @@ export class BezenhamLine { this.error = this.dx - this.dy; } - private dx: number; - private dy: number; - private sx: number; - private sy: number; + private readonly dx: number; + private readonly dy: number; + private readonly sx: number; + private readonly sy: number; private error: number; size() { @@ -45,10 +45,10 @@ export class BezenhamLine { export class CubicBezierCurve { constructor( - private p0: Point, - private p1: Point, - private p2: Point, - private p3: Point, + private readonly p0: Point, + private readonly p1: Point, + private readonly p2: Point, + private readonly p3: Point, ) {} getPointAt(t: number): Point { const T = 1 - t; diff --git a/src/core/worker/WorkerClient.ts b/src/core/worker/WorkerClient.ts index a41cf55f9..f6a1f8923 100644 --- a/src/core/worker/WorkerClient.ts +++ b/src/core/worker/WorkerClient.ts @@ -12,16 +12,16 @@ import { WorkerMessage } from "./WorkerMessages"; import { generateID } from "../Util"; export class WorkerClient { - private worker: Worker; + private readonly worker: Worker; private isInitialized = false; - private messageHandlers: Map void>; + private readonly messageHandlers: Map void>; private gameUpdateCallback?: ( update: GameUpdateViewData | ErrorUpdate, ) => void; constructor( - private gameStartInfo: GameStartInfo, - private clientID: ClientID, + private readonly gameStartInfo: GameStartInfo, + private readonly clientID: ClientID, ) { this.worker = new Worker(new URL("./Worker.worker.ts", import.meta.url)); this.messageHandlers = new Map(); diff --git a/src/server/Cloudflare.ts b/src/server/Cloudflare.ts index d3b2e2125..2de807f05 100644 --- a/src/server/Cloudflare.ts +++ b/src/server/Cloudflare.ts @@ -49,13 +49,13 @@ const CloudflareTunnelConfigSchema = z.object({ }); export class Cloudflare { - private baseUrl = "https://api.cloudflare.com/client/v4"; + private readonly baseUrl = "https://api.cloudflare.com/client/v4"; constructor( - private accountId: string, - private apiToken: string, - private configPath: string, - private credsPath: string, + private readonly accountId: string, + private readonly apiToken: string, + private readonly configPath: string, + private readonly credsPath: string, ) { log.info(`Using config: ${this.configPath}`); log.info(`Using credentials: ${this.credsPath}`); diff --git a/src/server/GameManager.ts b/src/server/GameManager.ts index 4551198ca..cf9865af1 100644 --- a/src/server/GameManager.ts +++ b/src/server/GameManager.ts @@ -9,8 +9,8 @@ export class GameManager { private games: Map = new Map(); constructor( - private config: ServerConfig, - private log: Logger, + private readonly config: ServerConfig, + private readonly log: Logger, ) { setInterval(() => this.tick(), 1000); } diff --git a/src/server/GameServer.ts b/src/server/GameServer.ts index 6260e24a5..a0d0736a2 100644 --- a/src/server/GameServer.ts +++ b/src/server/GameServer.ts @@ -33,18 +33,18 @@ export enum GamePhase { } export class GameServer { - private sentDesyncMessageClients = new Set(); + private readonly sentDesyncMessageClients = new Set(); - private maxGameDuration = 3 * 60 * 60 * 1000; // 3 hours + private readonly maxGameDuration = 3 * 60 * 60 * 1000; // 3 hours - private disconnectedTimeout = 1 * 30 * 1000; // 30 seconds + private readonly disconnectedTimeout = 1 * 30 * 1000; // 30 seconds - private turns: Turn[] = []; + private readonly turns: Turn[] = []; private intents: Intent[] = []; public activeClients: Client[] = []; lobbyCreatorID: string | undefined; - private allClients: Map = new Map(); - private clientsDisconnectedStatus: Map = new Map(); + private readonly allClients: Map = new Map(); + private readonly clientsDisconnectedStatus: Map = new Map(); private _hasStarted = false; private _startTime: number | null = null; @@ -57,14 +57,14 @@ export class GameServer { // Note: This can be undefined if accessed before the game starts. private gameStartInfo!: GameStartInfo; - private log: Logger; + private readonly log: Logger; private _hasPrestarted = false; kickedClients: Set = new Set(); outOfSyncClients: Set = new Set(); - private websockets: Set = new Set(); + private readonly websockets: Set = new Set(); winnerVotes: Map< string, @@ -75,7 +75,7 @@ export class GameServer { public readonly id: string, readonly log_: Logger, public readonly createdAt: number, - private config: ServerConfig, + private readonly config: ServerConfig, public gameConfig: GameConfig, lobbyCreatorID?: string, ) { diff --git a/src/server/Gatekeeper.ts b/src/server/Gatekeeper.ts index 8bdd236b1..047baa94b 100644 --- a/src/server/Gatekeeper.ts +++ b/src/server/Gatekeeper.ts @@ -94,7 +94,7 @@ async function getGatekeeper(): Promise { } export class GatekeeperWrapper implements Gatekeeper { - constructor(private getGK: () => Promise) {} + constructor(private readonly getGK: () => Promise) {} httpHandler( limiterType: LimiterType, diff --git a/src/server/Privilege.ts b/src/server/Privilege.ts index 6d7722020..8ef212420 100644 --- a/src/server/Privilege.ts +++ b/src/server/Privilege.ts @@ -13,11 +13,11 @@ export type PrivilegeChecker = { }; export class PrivilegeCheckerImpl implements PrivilegeChecker { - private b64ToPattern: Record = {}; + private readonly b64ToPattern: Record = {}; constructor( - private cosmetics: Cosmetics, - private b64urlDecode: (base64: string) => Uint8Array, + private readonly cosmetics: Cosmetics, + private readonly b64urlDecode: (base64: string) => Uint8Array, ) { for (const name in this.cosmetics.patterns) { const pattern = this.cosmetics.patterns[name]; diff --git a/src/server/PrivilegeRefresher.ts b/src/server/PrivilegeRefresher.ts index 6846293c1..a8043fd3d 100644 --- a/src/server/PrivilegeRefresher.ts +++ b/src/server/PrivilegeRefresher.ts @@ -11,15 +11,15 @@ import { base64url } from "jose"; // WARNING: This fails open if cosmetics.json is not available. export class PrivilegeRefresher { private privilegeChecker: PrivilegeChecker | null = null; - private failOpenPrivilegeChecker: PrivilegeChecker = + private readonly failOpenPrivilegeChecker: PrivilegeChecker = new FailOpenPrivilegeChecker(); - private log: Logger; + private readonly log: Logger; constructor( - private endpoint: string, + private readonly endpoint: string, parentLog: Logger, - private refreshInterval: number = 1000 * 60 * 3, + private readonly refreshInterval: number = 1000 * 60 * 3, ) { this.log = parentLog.child({ comp: "privilege-refresher" }); } diff --git a/tests/Censor.test.ts b/tests/Censor.test.ts index 436f07885..fc23b7172 100644 --- a/tests/Censor.test.ts +++ b/tests/Censor.test.ts @@ -2,7 +2,7 @@ jest.mock("obscenity", () => { return { RegExpMatcher: class { - private dummy: string[] = ["foo", "bar", "leet", "code"]; + private readonly dummy: string[] = ["foo", "bar", "leet", "code"]; constructor(_opts: any) {} hasMatch(input: string): boolean { const lower = input.toLowerCase();