mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-01 14:33:25 +00:00
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
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -196,13 +196,13 @@ export class ClientGameRunner {
|
||||
private connectionCheckInterval: ReturnType<typeof setTimeout> | 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<typeof setTimeout> | 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();
|
||||
|
||||
@@ -121,7 +121,7 @@ export class InputHandler {
|
||||
private lastPointerDownX = 0;
|
||||
private lastPointerDownY = 0;
|
||||
|
||||
private pointers: Map<number, PointerEvent> = new Map();
|
||||
private readonly pointers: Map<number, PointerEvent> = new Map();
|
||||
|
||||
private lastPinchDistance = 0;
|
||||
|
||||
@@ -130,17 +130,17 @@ export class InputHandler {
|
||||
private alternateView = false;
|
||||
|
||||
private moveInterval: ReturnType<typeof setTimeout> | null = null;
|
||||
private activeKeys = new Set<string>();
|
||||
private readonly activeKeys = new Set<string>();
|
||||
private keybinds: Record<string, string> = {};
|
||||
|
||||
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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -47,7 +47,7 @@ export class LangSelector extends LitElement {
|
||||
private debugKeyPressed = false;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private languageMap: Record<string, any> = {
|
||||
private readonly languageMap: Record<string, any> = {
|
||||
ar,
|
||||
bg,
|
||||
bn,
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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<typeof setTimeout>;
|
||||
|
||||
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() {
|
||||
|
||||
+2
-2
@@ -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() {}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<GameID, string> = new Map();
|
||||
@state() private readonly mapImages: Map<GameID, string> = new Map();
|
||||
private lobbiesInterval: number | null = null;
|
||||
private currLobby: GameInfo | null = null;
|
||||
private debounceDelay = 750;
|
||||
private lobbyIDToStart = new Map<GameID, number>();
|
||||
private readonly debounceDelay = 750;
|
||||
private readonly lobbyIDToStart = new Map<GameID, number>();
|
||||
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<string, string> = {};
|
||||
@@ -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") {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -128,9 +128,9 @@ const ANIMATED_SPRITE_CONFIG: Partial<Record<FxType, AnimatedSpriteConfig>> = {
|
||||
};
|
||||
|
||||
export class AnimatedSpriteLoader {
|
||||
private animatedSpriteImageMap: Map<FxType, HTMLCanvasElement> = new Map();
|
||||
private readonly animatedSpriteImageMap: Map<FxType, HTMLCanvasElement> = new Map();
|
||||
// Do not color the same sprite twice
|
||||
private coloredAnimatedSpriteCache: Map<string, HTMLCanvasElement> =
|
||||
private readonly coloredAnimatedSpriteCache: Map<string, HTMLCanvasElement> =
|
||||
new Map();
|
||||
|
||||
public async loadAllAnimatedSpriteImages(): Promise<void> {
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 = [
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ export class EventsDisplay extends LitElement implements Layer {
|
||||
private events: GameEvent[] = [];
|
||||
|
||||
// allianceID -> last checked at tick
|
||||
private alliancesCheckedAt = new Map<number, Tick>();
|
||||
private readonly alliancesCheckedAt = new Map<number, Tick>();
|
||||
@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<typeof setTimeout> | null = null;
|
||||
@state() private eventsFilters: Map<MessageCategory, boolean> = new Map([
|
||||
@state() private readonly eventsFilters: Map<MessageCategory, boolean> = 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)],
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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<PlayerView> = 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<PlayerView> = 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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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<SVGGElement, unknown, null, undefined>
|
||||
> = new Map();
|
||||
private menuPaths: Map<
|
||||
private readonly menuPaths: Map<
|
||||
string,
|
||||
d3.Selection<SVGPathElement, unknown, null, undefined>
|
||||
> = new Map();
|
||||
private menuIcons: Map<
|
||||
private readonly menuIcons: Map<
|
||||
string,
|
||||
d3.Selection<SVGImageElement, unknown, null, undefined>
|
||||
> = 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);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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<TileRef, RailRef>();
|
||||
private readonly existingRailroads = new Map<TileRef, RailRef>();
|
||||
private nextRailIndexToCheck = 0;
|
||||
private railTileList: TileRef[] = [];
|
||||
|
||||
constructor(private game: GameView) {
|
||||
constructor(private readonly game: GameView) {
|
||||
this.theme = game.config().theme();
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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() {}
|
||||
|
||||
@@ -59,12 +59,12 @@ export class StructureIconsLayer implements Layer {
|
||||
private levelsStage: PIXI.Container;
|
||||
private dotsStage: PIXI.Container;
|
||||
private shouldRedraw = true;
|
||||
private textureCache: Map<string, PIXI.Texture> = new Map();
|
||||
private theme: Theme;
|
||||
private readonly textureCache: Map<string, PIXI.Texture> = new Map();
|
||||
private readonly theme: Theme;
|
||||
private renderer: PIXI.Renderer;
|
||||
private renders: StructureRenderInfo[] = [];
|
||||
private seenUnits: Set<UnitView> = new Set();
|
||||
private structures: Map<
|
||||
private readonly seenUnits: Set<UnitView> = 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));
|
||||
|
||||
@@ -31,10 +31,10 @@ type UnitRenderConfig = {
|
||||
export class StructureLayer implements Layer {
|
||||
private canvas: HTMLCanvasElement;
|
||||
private context: CanvasRenderingContext2D;
|
||||
private unitIcons: Map<string, HTMLImageElement> = new Map();
|
||||
private theme: Theme;
|
||||
private tempCanvas: HTMLCanvasElement;
|
||||
private tempContext: CanvasRenderingContext2D;
|
||||
private readonly unitIcons: Map<string, HTMLImageElement> = new Map();
|
||||
private readonly theme: Theme;
|
||||
private readonly tempCanvas: HTMLCanvasElement;
|
||||
private readonly tempContext: CanvasRenderingContext2D;
|
||||
|
||||
// Configuration for supported unit types only
|
||||
private readonly unitConfigs: Partial<Record<UnitType, UnitRenderConfig>> = {
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<number, ProgressBar> = new Map();
|
||||
private readonly allHealthBars: Map<number, ProgressBar> = 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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -32,15 +32,15 @@ export class UnitLayer implements Layer {
|
||||
private transportShipTrailCanvas: HTMLCanvasElement;
|
||||
private unitTrailContext: CanvasRenderingContext2D;
|
||||
|
||||
private unitToTrail = new Map<UnitView, TileRef[]>();
|
||||
private readonly unitToTrail = new Map<UnitView, TileRef[]>();
|
||||
|
||||
private theme: Theme;
|
||||
private readonly theme: Theme;
|
||||
|
||||
private alternateView = false;
|
||||
|
||||
private oldShellTile = new Map<UnitView, TileRef>();
|
||||
private readonly oldShellTile = new Map<UnitView, TileRef>();
|
||||
|
||||
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();
|
||||
|
||||
@@ -6,7 +6,7 @@ export type EventConstructor<T extends GameEvent = GameEvent> = new (
|
||||
) => T;
|
||||
|
||||
export class EventBus {
|
||||
private listeners: Map<EventConstructor, Array<(event: GameEvent) => void>> =
|
||||
private readonly listeners: Map<EventConstructor, Array<(event: GameEvent) => void>> =
|
||||
new Map();
|
||||
|
||||
emit<T extends GameEvent>(event: T): void {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export class PatternDecoder {
|
||||
private bytes: Uint8Array;
|
||||
private readonly bytes: Uint8Array;
|
||||
|
||||
readonly height: number;
|
||||
readonly width: number;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -20,9 +20,9 @@ extend([labPlugin]);
|
||||
|
||||
export class ColorAllocator {
|
||||
private availableColors: Colord[];
|
||||
private fallbackColors: Colord[];
|
||||
private assigned = new Map<string, Colord>();
|
||||
private teamPlayerColors = new Map<string, Colord>();
|
||||
private readonly fallbackColors: Colord[];
|
||||
private readonly assigned = new Map<string, Colord>();
|
||||
private readonly teamPlayerColors = new Map<string, Colord>();
|
||||
|
||||
constructor(colors: Colord[], fallback: Colord[]) {
|
||||
this.availableColors = [...colors];
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -10,32 +10,32 @@ import { Theme } from "./Config";
|
||||
type ColorCache = Map<string, Colord>;
|
||||
|
||||
export class PastelTheme implements Theme {
|
||||
private borderColorCache: ColorCache = new Map<string, Colord>();
|
||||
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<string, Colord>();
|
||||
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 {
|
||||
|
||||
@@ -10,32 +10,32 @@ import { Theme } from "./Config";
|
||||
type ColorCache = Map<string, Colord>;
|
||||
|
||||
export class PastelThemeDark implements Theme {
|
||||
private borderColorCache: ColorCache = new Map<string, Colord>();
|
||||
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<string, Colord>();
|
||||
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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -10,11 +10,11 @@ export class DefensePostExecution implements Execution {
|
||||
private target: Unit | null = null;
|
||||
private lastShellAttack = 0;
|
||||
|
||||
private alreadySentShell = new Set<Unit>();
|
||||
private readonly alreadySentShell = new Set<Unit>();
|
||||
|
||||
constructor(
|
||||
private player: Player,
|
||||
private tile: TileRef,
|
||||
private readonly tile: TileRef,
|
||||
) {}
|
||||
|
||||
init(mg: Game, ticks: number): void {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -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,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -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",
|
||||
) {}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<Player, Tick>();
|
||||
private lastNukeSent: [Tick, TileRef][] = [];
|
||||
private embargoMalusApplied = new Set<PlayerID>();
|
||||
private heckleEmoji: number[];
|
||||
private readonly lastEmojiSent = new Map<Player, Tick>();
|
||||
private readonly lastNukeSent: [Tick, TileRef][] = [];
|
||||
private readonly embargoMalusApplied = new Set<PlayerID>();
|
||||
private readonly heckleEmoji: number[];
|
||||
|
||||
constructor(
|
||||
gameID: GameID,
|
||||
private nation: Nation,
|
||||
private readonly nation: Nation,
|
||||
) {
|
||||
this.random = new PseudoRandom(
|
||||
simpleHash(nation.playerInfo.id) + simpleHash(gameID),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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<number> = new Set();
|
||||
private readonly nukesToIgnore: Set<number> = 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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -9,7 +9,7 @@ export class SpawnExecution implements Execution {
|
||||
private mg: Game;
|
||||
|
||||
constructor(
|
||||
private playerInfo: PlayerInfo,
|
||||
private readonly playerInfo: PlayerInfo,
|
||||
public readonly tile: TileRef,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
) {}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -19,10 +19,10 @@ export class WarshipExecution implements Execution {
|
||||
private mg: Game;
|
||||
private pathfinder: PathFinder;
|
||||
private lastShellAttack = 0;
|
||||
private alreadySentShell = new Set<Unit>();
|
||||
private readonly alreadySentShell = new Set<Unit>();
|
||||
|
||||
constructor(
|
||||
private input: (UnitParams<UnitType.Warship> & OwnerComp) | Unit,
|
||||
private readonly input: (UnitParams<UnitType.Warship> & OwnerComp) | Unit,
|
||||
) {}
|
||||
|
||||
init(mg: Game, ticks: number): void {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user