Enable various eslint rules (#1773)

## Description:

Enable various eslint rules.

## 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:
Scott Anderson
2025-08-11 22:14:00 -04:00
committed by GitHub
parent 8a41919ed7
commit ce49599229
109 changed files with 471 additions and 460 deletions
+7 -7
View File
@@ -47,7 +47,7 @@ import {
import { createCanvas } from "./Utils";
import { createRenderer, GameRenderer } from "./graphics/GameRenderer";
export interface LobbyConfig {
export type LobbyConfig = {
serverConfig: ServerConfig;
pattern: string | undefined;
flag: string;
@@ -59,7 +59,7 @@ export interface LobbyConfig {
gameStartInfo?: GameStartInfo;
// GameRecord exists when replaying an archived game.
gameRecord?: GameRecord;
}
};
export function joinLobby(
eventBus: EventBus,
@@ -192,7 +192,7 @@ export class ClientGameRunner {
private lastMousePosition: { x: number; y: number } | null = null;
private lastMessageTime: number = 0;
private lastMessageTime = 0;
private connectionCheckInterval: NodeJS.Timeout | null = null;
constructor(
@@ -364,7 +364,7 @@ export class ClientGameRunner {
this.transport.connect(onconnect, onmessage);
}
public stop(saveFullGame: boolean = false) {
public stop(saveFullGame = false) {
if (!this.isActive) return;
this.isActive = false;
@@ -420,7 +420,7 @@ export class ClientGameRunner {
const owner = this.gameView.owner(tile);
if (owner.isPlayer()) {
this.gameView.setFocusedPlayer(owner as PlayerView);
this.gameView.setFocusedPlayer(owner);
} else {
this.gameView.setFocusedPlayer(null);
}
@@ -623,7 +623,7 @@ export class ClientGameRunner {
if (this.gameView.isLand(tile)) {
const owner = this.gameView.owner(tile);
if (owner.isPlayer()) {
this.gameView.setFocusedPlayer(owner as PlayerView);
this.gameView.setFocusedPlayer(owner);
} else {
this.gameView.setFocusedPlayer(null);
}
@@ -637,7 +637,7 @@ export class ClientGameRunner {
.sort((a, b) => a.distSquared - b.distSquared);
if (units.length > 0) {
this.gameView.setFocusedPlayer(units[0].unit.owner() as PlayerView);
this.gameView.setFocusedPlayer(units[0].unit.owner());
} else {
this.gameView.setFocusedPlayer(null);
}
+2 -2
View File
@@ -1,11 +1,11 @@
import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";
import { renderPlayerFlag } from "../core/CustomFlag";
const flagKey: string = "flag";
const flagKey = "flag";
@customElement("flag-input")
export class FlagInput extends LitElement {
@state() public flag: string = "";
@state() public flag = "";
static styles = css`
@media (max-width: 768px) {
+1 -1
View File
@@ -9,7 +9,7 @@ export class FlagInputModal extends LitElement {
close: () => void;
};
@state() private search: string = "";
@state() private search = "";
createRenderRoot() {
return this;
+2 -1
View File
@@ -2,6 +2,7 @@ import { LitElement, css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
declare global {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Window {
adsbygoogle: unknown[];
}
@@ -108,7 +109,7 @@ const isElectron = () => {
if (
typeof navigator === "object" &&
typeof navigator.userAgent === "string" &&
navigator.userAgent.indexOf("Electron") >= 0
navigator.userAgent.includes("Electron")
) {
return true;
}
+9 -9
View File
@@ -40,19 +40,19 @@ export class HostLobbyModal extends LitElement {
@state() private disableNPCs = false;
@state() private gameMode: GameMode = GameMode.FFA;
@state() private teamCount: TeamCountConfig = 2;
@state() private bots: number = 400;
@state() private infiniteGold: boolean = false;
@state() private donateGold: boolean = false;
@state() private infiniteTroops: boolean = false;
@state() private donateTroops: boolean = false;
@state() private instantBuild: boolean = false;
@state() private bots = 400;
@state() private infiniteGold = false;
@state() private donateGold = false;
@state() private infiniteTroops = false;
@state() private donateTroops = false;
@state() private instantBuild = false;
@state() private lobbyId = "";
@state() private copySuccess = false;
@state() private clients: ClientInfo[] = [];
@state() private useRandomMap: boolean = false;
@state() private useRandomMap = false;
@state() private disabledUnits: UnitType[] = [];
@state() private lobbyCreatorClientID: string = "";
@state() private lobbyIdVisible: boolean = true;
@state() private lobbyCreatorClientID = "";
@state() private lobbyIdVisible = true;
private playersInterval: NodeJS.Timeout | null = null;
// Add a new timer for debouncing bot changes
+7 -7
View File
@@ -115,17 +115,17 @@ export class AutoUpgradeEvent implements GameEvent {
}
export class InputHandler {
private lastPointerX: number = 0;
private lastPointerY: number = 0;
private lastPointerX = 0;
private lastPointerY = 0;
private lastPointerDownX: number = 0;
private lastPointerDownY: number = 0;
private lastPointerDownX = 0;
private lastPointerDownY = 0;
private pointers: Map<number, PointerEvent> = new Map();
private lastPinchDistance: number = 0;
private lastPinchDistance = 0;
private pointerDown: boolean = false;
private pointerDown = false;
private alternateView = false;
@@ -163,7 +163,7 @@ export class InputHandler {
};
// Mac users might have different keybinds
const isMac = /Mac/.test(navigator.userAgent);
const isMac = navigator.userAgent.includes("Mac");
if (isMac) {
this.keybinds.modifierKey = "MetaLeft"; // Use Command key on Mac
}
+2 -2
View File
@@ -19,7 +19,7 @@ export class JoinPrivateLobbyModal extends LitElement {
close: () => void;
};
@query("#lobbyIdInput") private lobbyIdInput!: HTMLInputElement;
@state() private message: string = "";
@state() private message = "";
@state() private hasJoined = false;
@state() private players: string[] = [];
@@ -110,7 +110,7 @@ export class JoinPrivateLobbyModal extends LitElement {
return this; // light DOM
}
public open(id: string = "") {
public open(id = "") {
this.modalEl?.open();
if (id) {
this.setLobbyId(id);
+4 -4
View File
@@ -35,12 +35,12 @@ import zh_CN from "../../resources/lang/zh-CN.json";
export class LangSelector extends LitElement {
@state() public translations: Record<string, string> | undefined;
@state() public defaultTranslations: Record<string, string> | undefined;
@state() public currentLang: string = "en";
@state() public currentLang = "en";
@state() private languageList: any[] = [];
@state() private showModal: boolean = false;
@state() private debugMode: boolean = false;
@state() private showModal = false;
@state() private debugMode = false;
private debugKeyPressed: boolean = false;
private debugKeyPressed = false;
private languageMap: Record<string, any> = {
ar,
+1 -1
View File
@@ -169,7 +169,7 @@ export class LocalServer {
});
}
public endGame(saveFullGame: boolean = false) {
public endGame(saveFullGame = false) {
console.log("local server ending game");
clearInterval(this.turnCheckInterval);
if (this.isReplay) {
+10 -4
View File
@@ -43,6 +43,7 @@ import { discordLogin, getUserMe, isLoggedIn, logOut } from "./jwt";
import "./styles.css";
declare global {
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface Window {
PageOS: {
session: {
@@ -62,13 +63,14 @@ declare global {
}
// Extend the global interfaces to include your custom events
// eslint-disable-next-line @typescript-eslint/consistent-type-definitions
interface DocumentEventMap {
"join-lobby": CustomEvent<JoinLobbyEvent>;
"kick-player": CustomEvent;
"kick-player": CustomEvent<KickPlayerEvent>;
}
}
export interface JoinLobbyEvent {
export type JoinLobbyEvent = {
clientID: string;
// Multiplayer games only have gameID, gameConfig is not known until game starts.
gameID: string;
@@ -76,7 +78,11 @@ export interface JoinLobbyEvent {
gameStartInfo?: GameStartInfo;
// GameRecord exists when replaying an archived game.
gameRecord?: GameRecord;
}
};
export type KickPlayerEvent = {
target: string;
};
class Client {
private gameStop: (() => void) | null = null;
@@ -548,7 +554,7 @@ class Client {
this.publicLobby.leaveLobby();
}
private handleKickPlayer(event: CustomEvent) {
private handleKickPlayer(event: CustomEvent<KickPlayerEvent>) {
const { target } = event.detail;
// Forward to eventBus if available
+1 -1
View File
@@ -32,7 +32,7 @@ export class NewsModal extends LitElement {
@property({ type: String }) markdown = "Loading...";
private initialized: boolean = false;
private initialized = false;
static styles = css`
:host {
+3 -3
View File
@@ -11,12 +11,12 @@ import { terrainMapFileLoader } from "./TerrainMapFileLoader";
@customElement("public-lobby")
export class PublicLobby extends LitElement {
@state() private lobbies: GameInfo[] = [];
@state() public isLobbyHighlighted: boolean = false;
@state() private isButtonDebounced: boolean = false;
@state() public isLobbyHighlighted = false;
@state() private isButtonDebounced = false;
@state() private mapImages: Map<GameID, string> = new Map();
private lobbiesInterval: number | null = null;
private currLobby: GameInfo | null = null;
private debounceDelay: number = 750;
private debounceDelay = 750;
private lobbyIDToStart = new Map<GameID, number>();
createRenderRoot() {
+8 -8
View File
@@ -34,14 +34,14 @@ export class SinglePlayerModal extends LitElement {
};
@state() private selectedMap: GameMapType = GameMapType.World;
@state() private selectedDifficulty: Difficulty = Difficulty.Medium;
@state() private disableNPCs: boolean = false;
@state() private bots: number = 400;
@state() private infiniteGold: boolean = false;
@state() private donateGold: boolean = false;
@state() private infiniteTroops: boolean = false;
@state() private donateTroops: boolean = false;
@state() private instantBuild: boolean = false;
@state() private useRandomMap: boolean = false;
@state() private disableNPCs = false;
@state() private bots = 400;
@state() private infiniteGold = false;
@state() private donateGold = false;
@state() private infiniteTroops = false;
@state() private donateTroops = false;
@state() private instantBuild = false;
@state() private useRandomMap = false;
@state() private gameMode: GameMode = GameMode.FFA;
@state() private teamCount: TeamCountConfig = 2;
+2 -2
View File
@@ -19,7 +19,7 @@ export class TerritoryPatternsModal extends LitElement {
};
public previewButton: HTMLElement | null = null;
public buttonWidth: number = 150;
public buttonWidth = 150;
@state() private selectedPattern: string | undefined;
@@ -172,7 +172,7 @@ export class TerritoryPatternsModal extends LitElement {
}}
>
${translateText("territory_patterns.purchase")}
(${pattern.product!.price})
(${pattern.product.price})
</button>
`
: null}
+1 -1
View File
@@ -383,7 +383,7 @@ export class Transport {
} satisfies ClientJoinMessage);
}
leaveGame(saveFullGame: boolean = false) {
leaveGame(saveFullGame = false) {
if (this.isLocal) {
this.localServer.endGame(saveFullGame);
return;
+4 -4
View File
@@ -8,13 +8,13 @@ import {
validateUsername,
} from "../core/validations/username";
const usernameKey: string = "username";
const usernameKey = "username";
@customElement("username-input")
export class UsernameInput extends LitElement {
@state() private username: string = "";
@property({ type: String }) validationError: string = "";
private _isValid: boolean = true;
@state() private username = "";
@property({ type: String }) validationError = "";
private _isValid = true;
private userSettings: UserSettings = new UserSettings();
// Remove static styles since we're using Tailwind
+2 -2
View File
@@ -192,7 +192,7 @@ export function getMessageTypeClasses(type: MessageType): string {
}
export function getModifierKey(): string {
const isMac = /Mac/.test(navigator.userAgent);
const isMac = navigator.userAgent.includes("Mac");
if (isMac) {
return "⌘"; // Command key
} else {
@@ -201,7 +201,7 @@ export function getModifierKey(): string {
}
export function getAltKey(): string {
const isMac = /Mac/.test(navigator.userAgent);
const isMac = navigator.userAgent.includes("Mac");
if (isMac) {
return "⌥"; // Option key
} else {
+1 -1
View File
@@ -41,7 +41,7 @@ export const MapDescription: Record<keyof typeof GameMapType, string> = {
export class MapDisplay extends LitElement {
@property({ type: String }) mapKey = "";
@property({ type: Boolean }) selected = false;
@property({ type: String }) translation: string = "";
@property({ type: String }) translation = "";
@state() private mapWebpPath: string | null = null;
@state() private mapName: string | null = null;
@state() private isLoading = true;
+1 -1
View File
@@ -3,7 +3,7 @@ import { customElement, property } from "lit/decorators";
@customElement("modal-overlay")
export class ModalOverlay extends LitElement {
@property({ reflect: true }) public visible: boolean = false;
@property({ reflect: true }) public visible = false;
static styles = css`
.overlay {
+4 -4
View File
@@ -1,15 +1,15 @@
export class AnimatedSprite {
private frameHeight: number;
private currentFrame: number = 0;
private elapsedTime: number = 0;
private active: boolean = true;
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: boolean = false,
private looping = false,
private originX: number,
private originY: number,
) {
+1 -1
View File
@@ -246,7 +246,7 @@ export function createRenderer(
eventBus,
game,
transformHandler,
emojiTable as EmojiTable,
emojiTable,
buildMenu,
uiState,
playerPanel,
+4 -4
View File
@@ -1,17 +1,17 @@
import { Cell, Game, NameViewData, Player } from "../../core/game/Game";
import { calculateBoundingBox } from "../../core/Util";
export interface Point {
export type Point = {
x: number;
y: number;
}
};
export interface Rectangle {
export type Rectangle = {
x: number;
y: number;
width: number;
height: number;
}
};
export function placeName(game: Game, player: Player): NameViewData {
const boundingBox =
+1 -1
View File
@@ -7,7 +7,7 @@ export class ProgressBar {
private y: number,
private w: number,
private h: number,
private progress: number = 0, // Progress from 0 to 1
private progress = 0, // Progress from 0 to 1
) {
this.setProgress(progress);
}
+5 -5
View File
@@ -13,10 +13,10 @@ export const CAMERA_MAX_SPEED = 15;
export const CAMERA_SMOOTHING = 0.03;
export class TransformHandler {
public scale: number = 1.8;
public scale = 1.8;
private _boundingRect: DOMRect;
private offsetX: number = -350;
private offsetY: number = -200;
private offsetX = -350;
private offsetY = -200;
private lastGoToCallTime: number | null = null;
private target: Cell | null;
@@ -267,7 +267,7 @@ export class TransformHandler {
this.target = null;
}
override(x: number = 0, y: number = 0, s: number = 1) {
override(x = 0, y = 0, s = 1) {
//hardset view position
this.clearTarget();
this.offsetX = x;
@@ -276,7 +276,7 @@ export class TransformHandler {
this.changed = true;
}
centerAll(fit: number = 1) {
centerAll(fit = 1) {
//position entire map centered on the screen
const vpWidth = this.boundingRect().width;
+2 -2
View File
@@ -1,3 +1,3 @@
export interface UIState {
export type UIState = {
attackRatio: number;
}
};
+2 -2
View File
@@ -1,6 +1,6 @@
export interface Fx {
export type Fx = {
renderTick(duration: number, ctx: CanvasRenderingContext2D): boolean;
}
};
export enum FxType {
MiniFire = "MiniFire",
+1 -1
View File
@@ -7,7 +7,7 @@ import { FadeFx, SpriteFx } from "./SpriteFx";
* Shockwave effect: draw a growing 1px white circle
*/
export class ShockwaveFx implements Fx {
private lifeTime: number = 0;
private lifeTime = 0;
constructor(
private x: number,
private y: number,
+1 -5
View File
@@ -4,11 +4,7 @@ import { AnimatedSprite } from "../AnimatedSprite";
import { AnimatedSpriteLoader } from "../AnimatedSpriteLoader";
import { Fx, FxType } from "./Fx";
function fadeInOut(
t: number,
fadeIn: number = 0.3,
fadeOut: number = 0.7,
): number {
function fadeInOut(t: number, fadeIn = 0.3, fadeOut = 0.7): number {
if (t < fadeIn) {
const f = t / fadeIn; // Map to [0, 1]
return f * f;
+3 -3
View File
@@ -1,15 +1,15 @@
import { Fx } from "./Fx";
export class TextFx implements Fx {
private lifeTime: number = 0;
private lifeTime = 0;
constructor(
private text: string,
private x: number,
private y: number,
private duration: number,
private riseDistance: number = 30,
private font: string = "11px sans-serif",
private riseDistance = 30,
private font = "11px sans-serif",
private color: { r: number; g: number; b: number } = {
r: 255,
g: 255,
+1 -1
View File
@@ -80,7 +80,7 @@ export class AlertFrame extends LitElement implements Layer {
this.game
.updatesSinceLastTick()
?.[GameUpdateType.BrokeAlliance]?.forEach((update) => {
this.onBrokeAllianceUpdate(update as BrokeAllianceUpdate);
this.onBrokeAllianceUpdate(update);
});
}
+2 -2
View File
@@ -35,13 +35,13 @@ import { renderNumber } from "../../Utils";
import { TransformHandler } from "../TransformHandler";
import { Layer } from "./Layer";
export interface BuildItemDisplay {
export type BuildItemDisplay = {
unitType: UnitType;
icon: string;
description?: string;
key?: string;
countable?: boolean;
}
};
export const buildTable: BuildItemDisplay[][] = [
[
+5 -5
View File
@@ -12,22 +12,22 @@ import { GameView } from "../../../core/game/GameView";
import { onlyImages } from "../../../core/Util";
import { Layer } from "./Layer";
interface ChatEvent {
type ChatEvent = {
description: string;
unsafeDescription?: boolean;
createdAt: number;
highlight?: boolean;
}
};
@customElement("chat-display")
export class ChatDisplay extends LitElement implements Layer {
public eventBus: EventBus;
public game: GameView;
private active: boolean = false;
private active = false;
@state() private _hidden: boolean = false;
@state() private newEvents: number = 0;
@state() private _hidden = false;
@state() private newEvents = 0;
@state() private chatEvents: ChatEvent[] = [];
private toggleHidden() {
+2 -2
View File
@@ -32,9 +32,9 @@ export class ChatModal extends LitElement {
private players: PlayerView[] = [];
private playerSearchQuery: string = "";
private playerSearchQuery = "";
private previewText: string | null = null;
private requiresPlayerSelection: boolean = false;
private requiresPlayerSelection = false;
private selectedCategory: string | null = null;
private selectedPhraseText: string | null = null;
private selectedPhraseTemplate: string | null = null;
+2 -2
View File
@@ -18,7 +18,7 @@ export class ControlPanel extends LitElement implements Layer {
public uiState: UIState;
@state()
private attackRatio: number = 0.2;
private attackRatio = 0.2;
@state()
private _maxTroops: number;
@@ -35,7 +35,7 @@ export class ControlPanel extends LitElement implements Layer {
@state()
private _gold: Gold;
private _troopRateIsIncreasing: boolean = true;
private _troopRateIsIncreasing = true;
private _lastTroopIncreaseRate: number;
+9 -9
View File
@@ -48,7 +48,7 @@ import {
import { getMessageTypeClasses, translateText } from "../../Utils";
interface GameEvent {
type GameEvent = {
description: string;
unsafeDescription?: boolean;
buttons?: {
@@ -66,14 +66,14 @@ interface GameEvent {
duration?: Tick;
focusID?: number;
unitView?: UnitView;
}
};
@customElement("events-display")
export class EventsDisplay extends LitElement implements Layer {
public eventBus: EventBus;
public game: GameView;
private active: boolean = false;
private active = false;
private events: GameEvent[] = [];
// allianceID -> last checked at tick
@@ -82,11 +82,11 @@ export class EventsDisplay extends LitElement implements Layer {
@state() private outgoingAttacks: AttackUpdate[] = [];
@state() private outgoingLandAttacks: AttackUpdate[] = [];
@state() private outgoingBoats: UnitView[] = [];
@state() private _hidden: boolean = false;
@state() private _isVisible: boolean = false;
@state() private newEvents: number = 0;
@state() private _hidden = false;
@state() private _isVisible = false;
@state() private newEvents = 0;
@state() private latestGoldAmount: bigint | null = null;
@state() private goldAmountAnimating: boolean = false;
@state() private goldAmountAnimating = false;
private goldAmountTimeoutId: ReturnType<typeof setTimeout> | null = null;
@state() private eventsFilters: Map<MessageCategory, boolean> = new Map([
[MessageCategory.ATTACK, false],
@@ -261,7 +261,7 @@ export class EventsDisplay extends LitElement implements Layer {
this.alliancesCheckedAt.set(alliance.id, this.game.ticks());
const other = this.game.player(alliance.other) as PlayerView;
const other = this.game.player(alliance.other);
if (!other.isAlive()) continue;
this.addEvent({
@@ -393,7 +393,7 @@ export class EventsDisplay extends LitElement implements Layer {
}
}
let otherPlayerDiplayName: string = "";
let otherPlayerDiplayName = "";
if (event.recipient !== null) {
//'recipient' parameter contains sender ID or recipient ID
const player = this.game.player(event.recipient);
+9 -9
View File
@@ -14,29 +14,29 @@ export class FPSDisplay extends LitElement implements Layer {
public userSettings!: UserSettings;
@state()
private currentFPS: number = 0;
private currentFPS = 0;
@state()
private averageFPS: number = 0;
private averageFPS = 0;
@state()
private frameTime: number = 0;
private frameTime = 0;
@state()
private isVisible: boolean = false;
private isVisible = false;
@state()
private isDragging: boolean = false;
private isDragging = false;
@state()
private position: { x: number; y: number } = { x: 50, y: 20 }; // Percentage values
private frameCount: number = 0;
private lastTime: number = 0;
private frameCount = 0;
private lastTime = 0;
private frameTimes: number[] = [];
private fpsHistory: number[] = [];
private lastSecondTime: number = 0;
private framesThisSecond: number = 0;
private lastSecondTime = 0;
private framesThisSecond = 0;
private dragStart: { x: number; y: number } = { x: 0, y: 0 };
static styles = css`
+2 -2
View File
@@ -20,8 +20,8 @@ export class FxLayer implements Layer {
private canvas: HTMLCanvasElement;
private context: CanvasRenderingContext2D;
private lastRefresh: number = 0;
private refreshRate: number = 10;
private lastRefresh = 0;
private refreshRate = 10;
private theme: Theme;
private animatedSpriteLoader: AnimatedSpriteLoader =
new AnimatedSpriteLoader();
@@ -22,19 +22,19 @@ export class GameRightSidebar extends LitElement implements Layer {
public eventBus: EventBus;
@state()
private _isSinglePlayer: boolean = false;
private _isSinglePlayer = false;
@state()
private _isReplayVisible: boolean = false;
private _isReplayVisible = false;
@state()
private _isVisible: boolean = true;
private _isVisible = true;
@state()
private isPaused: boolean = false;
private isPaused = false;
@state()
private timer: number = 0;
private timer = 0;
private hasWinner = false;
+7 -7
View File
@@ -13,16 +13,16 @@ export class GutterAdModal extends LitElement implements Layer {
public eventBus: EventBus;
@state()
private isVisible: boolean = false;
private isVisible = false;
@state()
private adLoaded: boolean = false;
private adLoaded = false;
private leftAdType: string = "left_rail";
private rightAdType: string = "right_rail";
private leftContainerId: string = "gutter-ad-container-left";
private rightContainerId: string = "gutter-ad-container-right";
private margin: string = "10px";
private leftAdType = "left_rail";
private rightAdType = "right_rail";
private leftContainerId = "gutter-ad-container-left";
private rightContainerId = "gutter-ad-container-right";
private margin = "10px";
// Override createRenderRoot to disable shadow DOM
createRenderRoot() {
+2 -2
View File
@@ -1,7 +1,7 @@
export interface Layer {
export type Layer = {
init?: () => void;
tick?: () => void;
renderLayer?: (context: CanvasRenderingContext2D) => void;
shouldTransform?: () => boolean;
redraw?: () => void;
}
};
+2 -2
View File
@@ -7,7 +7,7 @@ import { GameView, PlayerView, UnitView } from "../../../core/game/GameView";
import { renderNumber } from "../../Utils";
import { Layer } from "./Layer";
interface Entry {
type Entry = {
name: string;
position: number;
score: string;
@@ -15,7 +15,7 @@ interface Entry {
troops: string;
isMyPlayer: boolean;
player: PlayerView;
}
};
export class GoToPlayerEvent implements GameEvent {
constructor(public player: PlayerView) {}
+1 -1
View File
@@ -110,7 +110,7 @@ export class MainRadialMenu extends LitElement implements Layer {
this.buildMenu.playerActions = actions;
const tileOwner = this.game.owner(tile);
const recipient = tileOwner.isPlayer() ? (tileOwner as PlayerView) : null;
const recipient = tileOwner.isPlayer() ? tileOwner : null;
if (myPlayer && recipient) {
this.chatIntegration.setupChatModal(myPlayer, recipient);
+6 -6
View File
@@ -13,12 +13,12 @@ export class MultiTabModal extends LitElement implements Layer {
private detector: MultiTabDetector;
@property({ type: Number }) duration: number = 5000;
@state() private countdown: number = 5;
@state() private isVisible: boolean = false;
@state() private fakeIp: string = "";
@state() private deviceFingerprint: string = "";
@state() private reported: boolean = true;
@property({ type: Number }) duration = 5000;
@state() private countdown = 5;
@state() private isVisible = false;
@state() private fakeIp = "";
@state() private deviceFingerprint = "";
@state() private reported = true;
private intervalId?: number;
+2 -2
View File
@@ -59,7 +59,7 @@ export class NameLayer implements Layer {
private firstPlace: PlayerView | null = null;
private theme: Theme = this.game.config().theme();
private userSettings: UserSettings = new UserSettings();
private isVisible: boolean = true;
private isVisible = true;
constructor(
private game: GameView,
@@ -617,7 +617,7 @@ export class NameLayer implements Layer {
src: string,
size: number,
id: string,
center: boolean = false,
center = false,
): HTMLImageElement {
const icon = document.createElement("img");
icon.src = src;
+5 -5
View File
@@ -48,23 +48,23 @@ export class OptionsMenu extends LitElement implements Layer {
private userSettings: UserSettings = new UserSettings();
@state()
private showPauseButton: boolean = true;
private showPauseButton = true;
@state()
private isPaused: boolean = false;
private isPaused = false;
@state()
private timer: number = 0;
private timer = 0;
@state()
private showSettings: boolean = false;
private showSettings = false;
private isVisible = false;
private hasWinner = false;
@state()
private alternateView: boolean = false;
private alternateView = false;
private onTerrainButtonClick() {
this.alternateView = !this.alternateView;
@@ -60,7 +60,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
private unit: UnitView | null = null;
@state()
private _isInfoVisible: boolean = false;
private _isInfoVisible = false;
private _isActive = false;
@@ -107,7 +107,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
const owner = this.game.owner(tile);
if (owner && owner.isPlayer()) {
this.player = owner as PlayerView;
this.player = owner;
this.player.profile().then((p) => {
this.playerProfile = p;
});
@@ -231,7 +231,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
}}
>
${player.cosmetics.flag
? player.cosmetics.flag!.startsWith("!")
? player.cosmetics.flag.startsWith("!")
? html`<div
class="h-8 mr-1 aspect-[3/4] player-flag"
${ref((el) => {
@@ -244,7 +244,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer {
></div>`
: html`<img
class="h-8 mr-1 aspect-[3/4]"
src=${"/flags/" + player.cosmetics.flag! + ".svg"}
src=${"/flags/" + player.cosmetics.flag + ".svg"}
/>`
: html``}
${player.name()}
+2 -3
View File
@@ -40,7 +40,7 @@ export class PlayerPanel extends LitElement implements Layer {
private tile: TileRef | null = null;
@state()
public isVisible: boolean = false;
public isVisible = false;
@state()
private allianceExpiryText: string | null = null;
@@ -224,13 +224,12 @@ export class PlayerPanel extends LitElement implements Layer {
const myPlayer = this.g.myPlayer();
if (myPlayer === null) return;
if (this.tile === null) return;
let other = this.g.owner(this.tile);
const other = this.g.owner(this.tile);
if (!other.isPlayer()) {
this.hide();
console.warn("Tile is not owned by a player");
return;
}
other = other as PlayerView;
const canDonateGold = this.actions?.interaction?.canDonateGold;
const canDonateTroops = this.actions?.interaction?.canDonateTroops;
+11 -11
View File
@@ -15,12 +15,12 @@ export class CloseRadialMenuEvent implements GameEvent {
constructor() {}
}
export interface TooltipItem {
export type TooltipItem = {
text: string;
className: string;
}
};
export interface RadialMenuConfig {
export type RadialMenuConfig = {
menuSize?: number;
submenuScale?: number;
centerButtonSize?: number;
@@ -33,7 +33,7 @@ export interface RadialMenuConfig {
maxNestedLevels?: number;
innerRadiusIncrement?: number;
tooltipStyle?: string;
}
};
type CenterButtonState = "default" | "back";
@@ -42,9 +42,9 @@ type RequiredRadialMenuConfig = Required<RadialMenuConfig>;
export class RadialMenu implements Layer {
private menuElement: d3.Selection<HTMLDivElement, unknown, null, undefined>;
private tooltipElement: HTMLDivElement | null = null;
private isVisible: boolean = false;
private isVisible = false;
private currentLevel: number = 0; // Current menu level (0 = main menu, 1 = submenu, etc.)
private currentLevel = 0; // Current menu level (0 = main menu, 1 = submenu, etc.)
private menuStack: MenuElement[][] = []; // Stack to track menu navigation history
private currentMenuItems: MenuElement[] = []; // Current active menu items (changes based on level)
@@ -53,9 +53,9 @@ export class RadialMenu implements Layer {
private centerButtonState: CenterButtonState = "default";
private isTransitioning: boolean = false;
private lastHideTime: number = 0;
private reopenCooldownMs: number = 300;
private isTransitioning = false;
private lastHideTime = 0;
private reopenCooldownMs = 300;
private menuGroups: Map<
number,
@@ -73,8 +73,8 @@ export class RadialMenu implements Layer {
private selectedItemId: string | null = null;
private submenuHoverTimeout: number | null = null;
private backButtonHoverTimeout: number | null = null;
private navigationInProgress: boolean = false;
private originalCenterButtonIcon: string = "";
private navigationInProgress = false;
private originalCenterButtonIcon = "";
private params: MenuElementParams | null = null;
@@ -25,7 +25,7 @@ import traitorIcon from "../../../../resources/images/TraitorIconWhite.svg";
import xIcon from "../../../../resources/images/XIcon.svg";
import { EventBus } from "../../../core/EventBus";
export interface MenuElementParams {
export type MenuElementParams = {
myPlayer: PlayerView;
selected: PlayerView | null;
tile: TileRef;
@@ -38,9 +38,9 @@ export interface MenuElementParams {
chatIntegration: ChatIntegration;
eventBus: EventBus;
closeMenu: () => void;
}
};
export interface MenuElement {
export type MenuElement = {
id: string;
name: string;
displayed?: boolean | ((params: MenuElementParams) => boolean);
@@ -54,18 +54,18 @@ export interface MenuElement {
disabled: (params: MenuElementParams) => boolean;
action?: (params: MenuElementParams) => void; // For leaf items that perform actions
subMenu?: (params: MenuElementParams) => MenuElement[]; // For non-leaf items that open submenus
}
};
export interface TooltipKey {
export type TooltipKey = {
key: string;
className: string;
params?: Record<string, string | number>;
}
};
export interface CenterButtonElement {
export type CenterButtonElement = {
disabled: (params: MenuElementParams) => boolean;
action: (params: MenuElementParams) => void;
}
};
export const COLORS = {
build: "#ebe250",
@@ -566,8 +566,7 @@ export const rootMenuElement: MenuElement = {
const tileOwner = params.game.owner(params.tile);
const isOwnTerritory =
tileOwner.isPlayer() &&
(tileOwner as PlayerView).id() === params.myPlayer.id();
tileOwner.isPlayer() && tileOwner.id() === params.myPlayer.id();
const menuItems: (MenuElement | null)[] = [
infoMenuElement,
+2 -2
View File
@@ -8,7 +8,7 @@ import {
RailTile,
RailType,
} from "../../../core/game/GameUpdates";
import { GameView, PlayerView } from "../../../core/game/GameView";
import { GameView } from "../../../core/game/GameView";
import { Layer } from "./Layer";
import { getRailroadRects } from "./RailroadSprites";
@@ -151,7 +151,7 @@ export class RailroadLayer implements Layer {
const x = this.game.x(railRoad.tile);
const y = this.game.y(railRoad.tile);
const owner = this.game.owner(railRoad.tile);
const recipient = owner.isPlayer() ? (owner as PlayerView) : null;
const recipient = owner.isPlayer() ? owner : null;
const color = recipient
? this.theme.railroadColor(recipient)
: new Colord({ r: 255, g: 255, b: 255, a: 1 });
+3 -3
View File
@@ -12,8 +12,8 @@ import { Layer } from "./Layer";
export class ShowReplayPanelEvent {
constructor(
public visible: boolean = true,
public isSingleplayer: boolean = false,
public visible = true,
public isSingleplayer = false,
) {}
}
@@ -23,7 +23,7 @@ export class ReplayPanel extends LitElement implements Layer {
public eventBus: EventBus | undefined;
@property({ type: Boolean })
visible: boolean = false;
visible = false;
@state()
private _replaySpeedMultiplier: number = defaultReplaySpeedMultiplier;
+5 -5
View File
@@ -18,9 +18,9 @@ import { Layer } from "./Layer";
export class ShowSettingsModalEvent {
constructor(
public readonly isVisible: boolean = true,
public readonly shouldPause: boolean = false,
public readonly isPaused: boolean = false,
public readonly isVisible = true,
public readonly shouldPause = false,
public readonly isPaused = false,
) {}
}
@@ -30,10 +30,10 @@ export class SettingsModal extends LitElement implements Layer {
public userSettings: UserSettings;
@state()
private isVisible: boolean = false;
private isVisible = false;
@state()
private alternateView: boolean = false;
private alternateView = false;
@query(".modal-overlay")
private modalOverlay!: HTMLElement;
+3 -3
View File
@@ -13,12 +13,12 @@ export class SpawnAd extends LitElement implements Layer {
public g: GameView;
@state()
private isVisible: boolean = false;
private isVisible = false;
@state()
private adLoaded: boolean = false;
private adLoaded = false;
private gamesPlayed: number = 0;
private gamesPlayed = 0;
// Override createRenderRoot to disable shadow DOM
createRenderRoot() {
@@ -19,15 +19,15 @@ import { Layer } from "./Layer";
type ShapeType = "triangle" | "square" | "pentagon" | "octagon" | "circle";
class StructureRenderInfo {
public isOnScreen: boolean = false;
public isOnScreen = false;
constructor(
public unit: UnitView,
public owner: PlayerID,
public iconContainer: PIXI.Container,
public levelContainer: PIXI.Container,
public dotContainer: PIXI.Container,
public level: number = 0,
public underConstruction: boolean = true,
public level = 0,
public underConstruction = true,
) {}
}
@@ -58,7 +58,7 @@ export class StructureIconsLayer implements Layer {
private iconsStage: PIXI.Container;
private levelsStage: PIXI.Container;
private dotsStage: PIXI.Container;
private shouldRedraw: boolean = true;
private shouldRedraw = true;
private textureCache: Map<string, PIXI.Texture> = new Map();
private theme: Theme;
private renderer: PIXI.Renderer;
+2 -2
View File
@@ -23,11 +23,11 @@ const BASE_TERRITORY_RADIUS = 13.5;
const RADIUS_SCALE_FACTOR = 0.5;
const ZOOM_THRESHOLD = 4.3; // below this zoom level, structures are not rendered
interface UnitRenderConfig {
type UnitRenderConfig = {
icon: string;
borderRadius: number;
territoryRadius: number;
}
};
export class StructureLayer implements Layer {
private canvas: HTMLCanvasElement;
+2 -2
View File
@@ -6,14 +6,14 @@ import { GameView, PlayerView } from "../../../core/game/GameView";
import { renderNumber, translateText } from "../../Utils";
import { Layer } from "./Layer";
interface TeamEntry {
type TeamEntry = {
teamName: string;
totalScoreStr: string;
totalGold: string;
totalTroops: string;
totalScoreSort: number;
players: PlayerView[];
}
};
@customElement("team-stats")
export class TeamStats extends LitElement implements Layer {
+1 -1
View File
@@ -391,7 +391,7 @@ export class TerritoryLayer implements Layer {
}
}
paintTerritory(tile: TileRef, isBorder: boolean = false) {
paintTerritory(tile: TileRef, isBorder = false) {
if (isBorder && !this.game.hasOwner(tile)) {
return;
}
+1 -1
View File
@@ -77,7 +77,7 @@ export function getAuthHeader(): string {
return `Bearer ${token}`;
}
export async function logOut(allSessions: boolean = false) {
export async function logOut(allSessions = false) {
const token = getToken();
if (token === null) return;
clearToken();
@@ -3,10 +3,10 @@ import { html, TemplateResult } from "lit";
import { UnitType } from "../../core/game/Game";
import { translateText } from "../Utils";
export interface UnitTypeRenderContext {
export type UnitTypeRenderContext = {
disabledUnits: UnitType[];
toggleUnit: (unit: UnitType, checked: boolean) => void;
}
};
const unitOptions: { type: UnitType; translationKey: string }[] = [
{ type: UnitType.City, translationKey: "unit_type.city" },