mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-25 00:22:43 +00:00
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:
+13
-3
@@ -48,10 +48,20 @@ export default [
|
||||
{
|
||||
rules: {
|
||||
// Enable rules
|
||||
"@typescript-eslint/consistent-type-assertions": [
|
||||
"warn", // TODO: Raise this to error, https://github.com/openfrontio/OpenFrontIO/issues/1033
|
||||
{ assertionStyle: "never" },
|
||||
"@typescript-eslint/consistent-type-definitions": [
|
||||
"error",
|
||||
"type",
|
||||
// TODO: { assertionStyle: "never" }, https://github.com/openfrontio/OpenFrontIO/issues/1033
|
||||
],
|
||||
"@typescript-eslint/no-duplicate-enum-values": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-mixed-enums": "error",
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/prefer-as-const": "error",
|
||||
"@typescript-eslint/prefer-function-type": "error",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-literal-enum-member": "error",
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "error",
|
||||
eqeqeq: "error",
|
||||
"sort-keys": "error",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -9,7 +9,7 @@ export class FlagInputModal extends LitElement {
|
||||
close: () => void;
|
||||
};
|
||||
|
||||
@state() private search: string = "";
|
||||
@state() private search = "";
|
||||
|
||||
createRenderRoot() {
|
||||
return this;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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}
|
||||
|
||||
@@ -383,7 +383,7 @@ export class Transport {
|
||||
} satisfies ClientJoinMessage);
|
||||
}
|
||||
|
||||
leaveGame(saveFullGame: boolean = false) {
|
||||
leaveGame(saveFullGame = false) {
|
||||
if (this.isLocal) {
|
||||
this.localServer.endGame(saveFullGame);
|
||||
return;
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -246,7 +246,7 @@ export function createRenderer(
|
||||
eventBus,
|
||||
game,
|
||||
transformHandler,
|
||||
emojiTable as EmojiTable,
|
||||
emojiTable,
|
||||
buildMenu,
|
||||
uiState,
|
||||
playerPanel,
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
export interface UIState {
|
||||
export type UIState = {
|
||||
attackRatio: number;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export interface Fx {
|
||||
export type Fx = {
|
||||
renderTick(duration: number, ctx: CanvasRenderingContext2D): boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export enum FxType {
|
||||
MiniFire = "MiniFire",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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[][] = [
|
||||
[
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export interface Layer {
|
||||
export type Layer = {
|
||||
init?: () => void;
|
||||
tick?: () => void;
|
||||
renderLayer?: (context: CanvasRenderingContext2D) => void;
|
||||
shouldTransform?: () => boolean;
|
||||
redraw?: () => void;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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()}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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" },
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export type GameEvent = object;
|
||||
|
||||
export interface EventConstructor<T extends GameEvent = GameEvent> {
|
||||
new (...args: any[]): T;
|
||||
}
|
||||
export type EventConstructor<T extends GameEvent = GameEvent> = new (
|
||||
...args: any[]
|
||||
) => T;
|
||||
|
||||
export class EventBus {
|
||||
private listeners: Map<EventConstructor, Array<(event: GameEvent) => void>> =
|
||||
|
||||
@@ -198,7 +198,7 @@ export class GameRunner {
|
||||
canTarget: player.canTarget(other),
|
||||
sharedBorder: player.sharesBorderWith(other),
|
||||
};
|
||||
const alliance = player.allianceWith(other as Player);
|
||||
const alliance = player.allianceWith(other);
|
||||
if (alliance) {
|
||||
actions.interaction.allianceExpiresAt = alliance.expiresAt();
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@ export class PseudoRandom {
|
||||
private state1: number;
|
||||
|
||||
// Keep these variables to maintain the exact same interface
|
||||
private m: number = 0x80000000; // 2**31
|
||||
private a: number = 1103515245;
|
||||
private c: number = 12345;
|
||||
private m = 0x80000000; // 2**31
|
||||
private a = 1103515245;
|
||||
private c = 12345;
|
||||
private state: number;
|
||||
|
||||
private static readonly POW36_8 = Math.pow(36, 8); // Pre-compute 36^8
|
||||
|
||||
@@ -26,7 +26,7 @@ export enum GameEnv {
|
||||
Prod,
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
export type ServerConfig = {
|
||||
turnIntervalMs(): number;
|
||||
gameCreationRate(): number;
|
||||
lobbyMaxPlayers(
|
||||
@@ -62,14 +62,14 @@ export interface ServerConfig {
|
||||
cloudflareCredsPath(): string;
|
||||
stripePublishableKey(): string;
|
||||
allowedFlares(): string[] | undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export interface NukeMagnitude {
|
||||
export type NukeMagnitude = {
|
||||
inner: number;
|
||||
outer: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Config {
|
||||
export type Config = {
|
||||
samHittingChance(): number;
|
||||
samWarheadHittingChance(): number;
|
||||
spawnImmunityDuration(): Tick;
|
||||
@@ -170,9 +170,9 @@ export interface Config {
|
||||
structureMinDist(): number;
|
||||
isReplay(): boolean;
|
||||
allianceExtensionPromptOffset(): number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Theme {
|
||||
export type Theme = {
|
||||
teamColor(team: Team): Colord;
|
||||
territoryColor(playerInfo: PlayerView): Colord;
|
||||
specialBuildingColor(playerInfo: PlayerView): Colord;
|
||||
@@ -190,4 +190,4 @@ export interface Theme {
|
||||
allyColor(): Colord;
|
||||
enemyColor(): Colord;
|
||||
spawnHighlightColor(): Colord;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ export let cachedSC: ServerConfig | null = null;
|
||||
export async function getConfig(
|
||||
gameConfig: GameConfig,
|
||||
userSettings: UserSettings | null,
|
||||
isReplay: boolean = false,
|
||||
isReplay = false,
|
||||
): Promise<Config> {
|
||||
const sc = await getServerConfigFromClient();
|
||||
switch (sc.env()) {
|
||||
|
||||
@@ -18,7 +18,7 @@ const malusForRetreat = 25;
|
||||
export class AttackExecution implements Execution {
|
||||
private breakAlliance = false;
|
||||
private wasAlliedAtInit = false; // Store alliance state at initialization
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
private toConquer = new FlatBinaryHeap();
|
||||
|
||||
private random = new PseudoRandom(123);
|
||||
@@ -34,7 +34,7 @@ export class AttackExecution implements Execution {
|
||||
private _owner: Player,
|
||||
private _targetID: PlayerID | null,
|
||||
private sourceTile: TileRef | null = null,
|
||||
private removeTroops: boolean = true,
|
||||
private removeTroops = true,
|
||||
) {}
|
||||
|
||||
public targetID(): PlayerID | null {
|
||||
@@ -69,7 +69,7 @@ export class AttackExecution implements Execution {
|
||||
}
|
||||
|
||||
if (this.target && this.target.isPlayer()) {
|
||||
const targetPlayer = this.target as Player;
|
||||
const targetPlayer = this.target;
|
||||
if (
|
||||
targetPlayer.type() !== PlayerType.Bot &&
|
||||
this._owner.type() !== PlayerType.Bot
|
||||
|
||||
@@ -5,7 +5,7 @@ import { TrainStationExecution } from "./TrainStationExecution";
|
||||
export class CityExecution implements Execution {
|
||||
private mg: Game;
|
||||
private city: Unit | null = null;
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
|
||||
constructor(
|
||||
private player: Player,
|
||||
@@ -48,7 +48,7 @@ export class CityExecution implements Execution {
|
||||
createStation(): void {
|
||||
if (this.city !== null) {
|
||||
const nearbyFactory = this.mg.hasUnitNearby(
|
||||
this.city.tile()!,
|
||||
this.city.tile(),
|
||||
this.mg.config().trainStationMaxRange(),
|
||||
UnitType.Factory,
|
||||
this.player.id(),
|
||||
|
||||
@@ -20,7 +20,7 @@ import { WarshipExecution } from "./WarshipExecution";
|
||||
|
||||
export class ConstructionExecution implements Execution {
|
||||
private construction: Unit | null = null;
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
private mg: Game;
|
||||
|
||||
private ticksUntilComplete: Tick;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ShellExecution } from "./ShellExecution";
|
||||
export class DefensePostExecution implements Execution {
|
||||
private mg: Game;
|
||||
private post: Unit | null = null;
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
|
||||
private target: Unit | null = null;
|
||||
private lastShellAttack = 0;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Execution, Game, MessageType, Player } from "../game/Game";
|
||||
|
||||
export class DeleteUnitExecution implements Execution {
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
private mg: Game;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -4,7 +4,7 @@ import { TrainStationExecution } from "./TrainStationExecution";
|
||||
|
||||
export class FactoryExecution implements Execution {
|
||||
private factory: Unit | null = null;
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
private game: Game;
|
||||
constructor(
|
||||
private player: Player,
|
||||
@@ -47,7 +47,7 @@ export class FactoryExecution implements Execution {
|
||||
createStation(): void {
|
||||
if (this.factory !== null) {
|
||||
const structures = this.game.nearbyUnits(
|
||||
this.factory.tile()!,
|
||||
this.factory.tile(),
|
||||
this.game.config().trainStationMaxRange(),
|
||||
[UnitType.City, UnitType.Port, UnitType.Factory],
|
||||
);
|
||||
|
||||
@@ -31,7 +31,7 @@ export class MirvExecution implements Execution {
|
||||
|
||||
private separateDst: TileRef;
|
||||
|
||||
private speed: number = -1;
|
||||
private speed = -1;
|
||||
|
||||
constructor(
|
||||
private player: Player,
|
||||
|
||||
@@ -28,7 +28,7 @@ export class NukeExecution implements Execution {
|
||||
private player: Player,
|
||||
private dst: TileRef,
|
||||
private src?: TileRef | null,
|
||||
private speed: number = -1,
|
||||
private speed = -1,
|
||||
private waitTicks = 0,
|
||||
) {}
|
||||
|
||||
|
||||
@@ -28,11 +28,11 @@ export class PlayerExecution implements Execution {
|
||||
tick(ticks: number) {
|
||||
this.player.decayRelations();
|
||||
this.player.units().forEach((u) => {
|
||||
const tileOwner = this.mg!.owner(u.tile());
|
||||
const tileOwner = this.mg.owner(u.tile());
|
||||
if (u.info().territoryBound) {
|
||||
if (tileOwner.isPlayer()) {
|
||||
if (tileOwner !== this.player) {
|
||||
this.mg!.player(tileOwner.id()).captureUnit(u);
|
||||
this.mg.player(tileOwner.id()).captureUnit(u);
|
||||
}
|
||||
} else {
|
||||
u.delete();
|
||||
@@ -218,7 +218,7 @@ export class PlayerExecution implements Execution {
|
||||
}
|
||||
|
||||
let largestNeighborAttack: Player | null = null;
|
||||
let largestTroopCount: number = 0;
|
||||
let largestTroopCount = 0;
|
||||
for (const id of neighborsIDs) {
|
||||
const neighbor = this.mg.playerBySmallID(id);
|
||||
if (!neighbor.isPlayer() || this.player.isFriendly(neighbor)) {
|
||||
|
||||
@@ -90,7 +90,7 @@ export class PortExecution implements Execution {
|
||||
createStation(): void {
|
||||
if (this.port !== null) {
|
||||
const nearbyFactory = this.mg.hasUnitNearby(
|
||||
this.port.tile()!,
|
||||
this.port.tile(),
|
||||
this.mg.config().trainStationMaxRange(),
|
||||
UnitType.Factory,
|
||||
this.player.id(),
|
||||
|
||||
@@ -5,10 +5,10 @@ import { Railroad } from "../game/Railroad";
|
||||
|
||||
export class RailroadExecution implements Execution {
|
||||
private mg: Game;
|
||||
private active: boolean = true;
|
||||
private headIndex: number = 0;
|
||||
private tailIndex: number = 0;
|
||||
private increment: number = 3;
|
||||
private active = true;
|
||||
private headIndex = 0;
|
||||
private tailIndex = 0;
|
||||
private increment = 3;
|
||||
private railTiles: RailTile[] = [];
|
||||
constructor(private railRoad: Railroad) {
|
||||
this.tailIndex = railRoad.tiles.length;
|
||||
|
||||
@@ -128,7 +128,7 @@ class SAMTargetingSystem {
|
||||
|
||||
export class SAMLauncherExecution implements Execution {
|
||||
private mg: Game;
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
|
||||
// As MIRV go very fast we have to detect them very early but we only
|
||||
// shoot the one targeting very close (MIRVWarheadProtectionRadius)
|
||||
|
||||
@@ -16,7 +16,7 @@ export class SAMMissileExecution implements Execution {
|
||||
private pathFinder: AirPathFinder;
|
||||
private SAMMissile: Unit | undefined;
|
||||
private mg: Game;
|
||||
private speed: number = 0;
|
||||
private speed = 0;
|
||||
|
||||
constructor(
|
||||
private spawn: TileRef,
|
||||
|
||||
@@ -8,7 +8,7 @@ export class ShellExecution implements Execution {
|
||||
private pathFinder: AirPathFinder;
|
||||
private shell: Unit | undefined;
|
||||
private mg: Game;
|
||||
private destroyAtTick: number = -1;
|
||||
private destroyAtTick = -1;
|
||||
private random: PseudoRandom;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -5,7 +5,7 @@ import { PlayerExecution } from "./PlayerExecution";
|
||||
import { getSpawnTiles } from "./Util";
|
||||
|
||||
export class SpawnExecution implements Execution {
|
||||
active: boolean = true;
|
||||
active = true;
|
||||
private mg: Game;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -16,13 +16,13 @@ export class TrainExecution implements Execution {
|
||||
private mg: Game | null = null;
|
||||
private train: Unit | null = null;
|
||||
private cars: Unit[] = [];
|
||||
private hasCargo: boolean = false;
|
||||
private currentTile: number = 0;
|
||||
private hasCargo = false;
|
||||
private currentTile = 0;
|
||||
private spacing = 2;
|
||||
private usedTiles: TileRef[] = []; // used for cars behind
|
||||
private stations: TrainStation[] = [];
|
||||
private currentRailroad: OrientedRailroad | null = null;
|
||||
private speed: number = 2;
|
||||
private speed = 2;
|
||||
|
||||
constructor(
|
||||
private railNetwork: RailNetwork,
|
||||
|
||||
@@ -5,12 +5,12 @@ import { TrainExecution } from "./TrainExecution";
|
||||
|
||||
export class TrainStationExecution implements Execution {
|
||||
private mg: Game;
|
||||
private active: boolean = true;
|
||||
private active = true;
|
||||
private random: PseudoRandom;
|
||||
private station: TrainStation | null = null;
|
||||
private numCars: number = 5;
|
||||
private lastSpawnTick: number = 0;
|
||||
private ticksCooldown: number = 10; // Minimum cooldown between two trains
|
||||
private numCars = 5;
|
||||
private lastSpawnTick = 0;
|
||||
private ticksCooldown = 10; // Minimum cooldown between two trains
|
||||
constructor(
|
||||
private unit: Unit,
|
||||
private spawnTrains?: boolean, // If set, the station will spawn trains
|
||||
@@ -50,7 +50,7 @@ export class TrainStationExecution implements Execution {
|
||||
|
||||
private shouldSpawnTrain(clusterSize: number): boolean {
|
||||
const spawnRate = this.mg.config().trainSpawnRate(clusterSize);
|
||||
for (let i = 0; i < this.unit!.level(); i++) {
|
||||
for (let i = 0; i < this.unit.level(); i++) {
|
||||
if (this.random.chance(spawnRate)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ export class WarshipExecution implements Execution {
|
||||
const patrolRangeSquared = this.mg.config().warshipPatrolRange() ** 2;
|
||||
|
||||
const ships = this.mg.nearbyUnits(
|
||||
this.warship.tile()!,
|
||||
this.warship.tile(),
|
||||
this.mg.config().warshipTargettingRange(),
|
||||
[UnitType.TransportShip, UnitType.Warship, UnitType.TradeShip],
|
||||
);
|
||||
@@ -238,11 +238,11 @@ export class WarshipExecution implements Execution {
|
||||
return false;
|
||||
}
|
||||
|
||||
randomTile(allowShoreline: boolean = false): TileRef | undefined {
|
||||
randomTile(allowShoreline = false): TileRef | undefined {
|
||||
let warshipPatrolRange = this.mg.config().warshipPatrolRange();
|
||||
const maxAttemptBeforeExpand: number = 500;
|
||||
let attempts: number = 0;
|
||||
let expandCount: number = 0;
|
||||
const maxAttemptBeforeExpand = 500;
|
||||
let attempts = 0;
|
||||
let expandCount = 0;
|
||||
while (expandCount < 3) {
|
||||
const x =
|
||||
this.mg.x(this.warship.patrolTile()!) +
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Game, MutableAlliance, Player, Tick } from "./Game";
|
||||
|
||||
export class AllianceImpl implements MutableAlliance {
|
||||
private extensionRequestedRequestor_: boolean = false;
|
||||
private extensionRequestedRecipient_: boolean = false;
|
||||
private extensionRequestedRequestor_ = false;
|
||||
private extensionRequestedRecipient_ = false;
|
||||
|
||||
private expiresAt_: Tick;
|
||||
|
||||
|
||||
@@ -2,13 +2,13 @@ import { GameMapType } from "./Game";
|
||||
import { GameMapLoader, MapData } from "./GameMapLoader";
|
||||
import { MapManifest } from "./TerrainMapLoader";
|
||||
|
||||
export interface BinModule {
|
||||
export type BinModule = {
|
||||
default: string;
|
||||
}
|
||||
};
|
||||
|
||||
interface NationMapModule {
|
||||
type NationMapModule = {
|
||||
default: MapManifest;
|
||||
}
|
||||
};
|
||||
|
||||
export class BinaryLoaderGameMapLoader implements GameMapLoader {
|
||||
private maps: Map<GameMapType, MapData>;
|
||||
|
||||
+42
-42
@@ -26,10 +26,10 @@ export type GameUpdates = {
|
||||
[K in GameUpdateType]: UpdateTypeMap<K>[];
|
||||
};
|
||||
|
||||
export interface MapPos {
|
||||
export type MapPos = {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
};
|
||||
|
||||
export enum Difficulty {
|
||||
Easy = "Easy",
|
||||
@@ -141,7 +141,7 @@ export enum GameMode {
|
||||
Team = "Team",
|
||||
}
|
||||
|
||||
export interface UnitInfo {
|
||||
export type UnitInfo = {
|
||||
cost: (player: Player) => Gold;
|
||||
// Determines if its owner changes when its tile is conquered.
|
||||
territoryBound: boolean;
|
||||
@@ -151,7 +151,7 @@ export interface UnitInfo {
|
||||
upgradable?: boolean;
|
||||
canBuildTrainStation?: boolean;
|
||||
experimental?: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export enum UnitType {
|
||||
TransportShip = "Transport",
|
||||
@@ -191,15 +191,15 @@ export function isStructureType(type: UnitType): boolean {
|
||||
return _structureTypes.has(type);
|
||||
}
|
||||
|
||||
export interface OwnerComp {
|
||||
export type OwnerComp = {
|
||||
owner: Player;
|
||||
}
|
||||
};
|
||||
|
||||
export type TrajectoryTile = {
|
||||
tile: TileRef;
|
||||
targetable: boolean;
|
||||
};
|
||||
export interface UnitParamsMap {
|
||||
export type UnitParamsMap = {
|
||||
[UnitType.TransportShip]: {
|
||||
troops?: number;
|
||||
destination?: TileRef;
|
||||
@@ -253,7 +253,7 @@ export interface UnitParamsMap {
|
||||
};
|
||||
|
||||
[UnitType.Construction]: Record<string, never>;
|
||||
}
|
||||
};
|
||||
|
||||
// Type helper to get params type for a specific unit type
|
||||
export type UnitParams<T extends UnitType> = UnitParamsMap[T];
|
||||
@@ -320,14 +320,14 @@ export enum PlayerType {
|
||||
FakeHuman = "FAKEHUMAN",
|
||||
}
|
||||
|
||||
export interface Execution {
|
||||
export type Execution = {
|
||||
isActive(): boolean;
|
||||
activeDuringSpawnPhase(): boolean;
|
||||
init(mg: Game, ticks: number): void;
|
||||
tick(ticks: number): void;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Attack {
|
||||
export type Attack = {
|
||||
id(): string;
|
||||
retreating(): boolean;
|
||||
retreated(): boolean;
|
||||
@@ -346,25 +346,25 @@ export interface Attack {
|
||||
clearBorder(): void;
|
||||
borderSize(): number;
|
||||
averagePosition(): Cell | null;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AllianceRequest {
|
||||
export type AllianceRequest = {
|
||||
accept(): void;
|
||||
reject(): void;
|
||||
requestor(): Player;
|
||||
recipient(): Player;
|
||||
createdAt(): Tick;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Alliance {
|
||||
export type Alliance = {
|
||||
requestor(): Player;
|
||||
recipient(): Player;
|
||||
createdAt(): Tick;
|
||||
expiresAt(): Tick;
|
||||
other(player: Player): Player;
|
||||
}
|
||||
};
|
||||
|
||||
export interface MutableAlliance extends Alliance {
|
||||
export type MutableAlliance = {
|
||||
expire(): void;
|
||||
other(player: Player): Player;
|
||||
bothAgreedToExtend(): boolean;
|
||||
@@ -372,7 +372,7 @@ export interface MutableAlliance extends Alliance {
|
||||
id(): number;
|
||||
extend(): void;
|
||||
onlyOneAgreedToExtend(): boolean;
|
||||
}
|
||||
} & Alliance;
|
||||
|
||||
export class PlayerInfo {
|
||||
public readonly clan: string | null;
|
||||
@@ -406,7 +406,7 @@ export function isUnit(unit: unknown): unit is Unit {
|
||||
);
|
||||
}
|
||||
|
||||
export interface Unit {
|
||||
export type Unit = {
|
||||
isUnit(): this is Unit;
|
||||
|
||||
// Common properties.
|
||||
@@ -480,22 +480,22 @@ export interface Unit {
|
||||
// Warships
|
||||
setPatrolTile(tile: TileRef): void;
|
||||
patrolTile(): TileRef | undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export interface TerraNullius {
|
||||
export type TerraNullius = {
|
||||
isPlayer(): false;
|
||||
id(): null;
|
||||
clientID(): ClientID;
|
||||
smallID(): number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Embargo {
|
||||
export type Embargo = {
|
||||
createdAt: Tick;
|
||||
isTemporary: boolean;
|
||||
target: PlayerID;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Player {
|
||||
export type Player = {
|
||||
// Basic Info
|
||||
smallID(): number;
|
||||
info(): PlayerInfo;
|
||||
@@ -629,9 +629,9 @@ export interface Player {
|
||||
tradingPorts(port: Unit): Unit[];
|
||||
// WARNING: this operation is expensive.
|
||||
bestTransportShipSpawn(tile: TileRef): TileRef | false;
|
||||
}
|
||||
};
|
||||
|
||||
export interface Game extends GameMap {
|
||||
export type Game = {
|
||||
// Map & Dimensions
|
||||
isOnMap(cell: Cell): boolean;
|
||||
width(): number;
|
||||
@@ -715,33 +715,33 @@ export interface Game extends GameMap {
|
||||
addUpdate(update: GameUpdate): void;
|
||||
railNetwork(): RailNetwork;
|
||||
conquerPlayer(conqueror: Player, conquered: Player): void;
|
||||
}
|
||||
} & GameMap;
|
||||
|
||||
export interface PlayerActions {
|
||||
export type PlayerActions = {
|
||||
canAttack: boolean;
|
||||
buildableUnits: BuildableUnit[];
|
||||
canSendEmojiAllPlayers: boolean;
|
||||
interaction?: PlayerInteraction;
|
||||
}
|
||||
};
|
||||
|
||||
export interface BuildableUnit {
|
||||
export type BuildableUnit = {
|
||||
canBuild: TileRef | false;
|
||||
// unit id of the existing unit that can be upgraded, or false if it cannot be upgraded.
|
||||
canUpgrade: number | false;
|
||||
type: UnitType;
|
||||
cost: Gold;
|
||||
}
|
||||
};
|
||||
|
||||
export interface PlayerProfile {
|
||||
export type PlayerProfile = {
|
||||
relations: Record<number, Relation>;
|
||||
alliances: number[];
|
||||
}
|
||||
};
|
||||
|
||||
export interface PlayerBorderTiles {
|
||||
export type PlayerBorderTiles = {
|
||||
borderTiles: ReadonlySet<TileRef>;
|
||||
}
|
||||
};
|
||||
|
||||
export interface PlayerInteraction {
|
||||
export type PlayerInteraction = {
|
||||
sharedBorder: boolean;
|
||||
canSendEmoji: boolean;
|
||||
canSendAllianceRequest: boolean;
|
||||
@@ -751,14 +751,14 @@ export interface PlayerInteraction {
|
||||
canDonateTroops: boolean;
|
||||
canEmbargo: boolean;
|
||||
allianceExpiresAt?: Tick;
|
||||
}
|
||||
};
|
||||
|
||||
export interface EmojiMessage {
|
||||
export type EmojiMessage = {
|
||||
message: string;
|
||||
senderID: number;
|
||||
recipientID: number | typeof AllPlayers;
|
||||
createdAt: Tick;
|
||||
}
|
||||
};
|
||||
|
||||
export enum MessageType {
|
||||
ATTACK_FAILED,
|
||||
@@ -832,8 +832,8 @@ export function getMessageCategory(messageType: MessageType): MessageCategory {
|
||||
return MESSAGE_TYPE_CATEGORIES[messageType];
|
||||
}
|
||||
|
||||
export interface NameViewData {
|
||||
export type NameViewData = {
|
||||
x: number;
|
||||
y: number;
|
||||
size: number;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -82,7 +82,7 @@ export class GameImpl implements Game {
|
||||
private _railNetwork: RailNetwork = createRailNetwork(this);
|
||||
|
||||
// Used to assign unique IDs to each new alliance
|
||||
private nextAllianceID: number = 0;
|
||||
private nextAllianceID = 0;
|
||||
|
||||
constructor(
|
||||
private _humans: PlayerInfo[],
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Cell, TerrainType } from "./Game";
|
||||
export type TileRef = number;
|
||||
export type TileUpdate = bigint;
|
||||
|
||||
export interface GameMap {
|
||||
export type GameMap = {
|
||||
ref(x: number, y: number): TileRef;
|
||||
isValidRef(ref: TileRef): boolean;
|
||||
x(ref: TileRef): number;
|
||||
@@ -48,7 +48,7 @@ export interface GameMap {
|
||||
updateTile(tu: TileUpdate): TileRef;
|
||||
|
||||
numTilesWithFallout(): number;
|
||||
}
|
||||
};
|
||||
|
||||
export class GameMapImpl implements GameMap {
|
||||
private _numTilesWithFallout = 0;
|
||||
@@ -341,7 +341,7 @@ export class GameMapImpl implements GameMap {
|
||||
export function euclDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
center: boolean = false,
|
||||
center = false,
|
||||
): (gm: GameMap, tile: TileRef) => boolean {
|
||||
const dist2 = dist * dist;
|
||||
if (!center) {
|
||||
@@ -364,7 +364,7 @@ export function euclDistFN(
|
||||
export function manhattanDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
center: boolean = false,
|
||||
center = false,
|
||||
): (gm: GameMap, tile: TileRef) => boolean {
|
||||
if (!center) {
|
||||
return (gm: GameMap, n: TileRef) => gm.manhattanDist(root, n) <= dist;
|
||||
@@ -382,7 +382,7 @@ export function manhattanDistFN(
|
||||
export function rectDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
center: boolean = false,
|
||||
center = false,
|
||||
): (gm: GameMap, tile: TileRef) => boolean {
|
||||
if (!center) {
|
||||
return (gm: GameMap, n: TileRef) => {
|
||||
@@ -415,7 +415,7 @@ function isInIsometricTile(
|
||||
export function isometricDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
center: boolean = false,
|
||||
center = false,
|
||||
): (gm: GameMap, tile: TileRef) => boolean {
|
||||
if (!center) {
|
||||
return (gm: GameMap, n: TileRef) => gm.manhattanDist(root, n) <= dist;
|
||||
@@ -437,7 +437,7 @@ export function isometricDistFN(
|
||||
export function hexDistFN(
|
||||
root: TileRef,
|
||||
dist: number,
|
||||
center: boolean = false,
|
||||
center = false,
|
||||
): (gm: GameMap, tile: TileRef) => boolean {
|
||||
if (!center) {
|
||||
return (gm: GameMap, n: TileRef) => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { GameMapType } from "./Game";
|
||||
import { MapManifest } from "./TerrainMapLoader";
|
||||
|
||||
export interface GameMapLoader {
|
||||
export type GameMapLoader = {
|
||||
getMapData(map: GameMapType): MapData;
|
||||
}
|
||||
};
|
||||
|
||||
export interface MapData {
|
||||
export type MapData = {
|
||||
mapBin: () => Promise<Uint8Array>;
|
||||
miniMapBin: () => Promise<Uint8Array>;
|
||||
manifest: () => Promise<MapManifest>;
|
||||
webpPath: () => Promise<string>;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -14,17 +14,17 @@ import {
|
||||
} from "./Game";
|
||||
import { TileRef, TileUpdate } from "./GameMap";
|
||||
|
||||
export interface GameUpdateViewData {
|
||||
export type GameUpdateViewData = {
|
||||
tick: number;
|
||||
updates: GameUpdates;
|
||||
packedTileUpdates: BigUint64Array;
|
||||
playerNameViewData: Record<string, NameViewData>;
|
||||
}
|
||||
};
|
||||
|
||||
export interface ErrorUpdate {
|
||||
export type ErrorUpdate = {
|
||||
errMsg: string;
|
||||
stack?: string;
|
||||
}
|
||||
};
|
||||
|
||||
export enum GameUpdateType {
|
||||
Tile,
|
||||
@@ -67,13 +67,13 @@ export type GameUpdate =
|
||||
| RailroadUpdate
|
||||
| ConquestUpdate;
|
||||
|
||||
export interface BonusEventUpdate {
|
||||
export type BonusEventUpdate = {
|
||||
type: GameUpdateType.BonusEvent;
|
||||
player: PlayerID;
|
||||
tile: TileRef;
|
||||
gold: number;
|
||||
troops: number;
|
||||
}
|
||||
};
|
||||
|
||||
export enum RailType {
|
||||
VERTICAL,
|
||||
@@ -84,30 +84,30 @@ export enum RailType {
|
||||
BOTTOM_RIGHT,
|
||||
}
|
||||
|
||||
export interface RailTile {
|
||||
export type RailTile = {
|
||||
tile: TileRef;
|
||||
railType: RailType;
|
||||
}
|
||||
};
|
||||
|
||||
export interface RailroadUpdate {
|
||||
export type RailroadUpdate = {
|
||||
type: GameUpdateType.RailroadEvent;
|
||||
isActive: boolean;
|
||||
railTiles: RailTile[];
|
||||
}
|
||||
};
|
||||
|
||||
export interface ConquestUpdate {
|
||||
export type ConquestUpdate = {
|
||||
type: GameUpdateType.ConquestEvent;
|
||||
conquerorId: PlayerID;
|
||||
conqueredId: PlayerID;
|
||||
gold: Gold;
|
||||
}
|
||||
};
|
||||
|
||||
export interface TileUpdateWrapper {
|
||||
export type TileUpdateWrapper = {
|
||||
type: GameUpdateType.Tile;
|
||||
update: TileUpdate;
|
||||
}
|
||||
};
|
||||
|
||||
export interface UnitUpdate {
|
||||
export type UnitUpdate = {
|
||||
type: GameUpdateType.Unit;
|
||||
unitType: UnitType;
|
||||
troops: number;
|
||||
@@ -130,17 +130,17 @@ export interface UnitUpdate {
|
||||
hasTrainStation: boolean;
|
||||
trainType?: TrainType; // Only for trains
|
||||
loaded?: boolean; // Only for trains
|
||||
}
|
||||
};
|
||||
|
||||
export interface AttackUpdate {
|
||||
export type AttackUpdate = {
|
||||
attackerID: number;
|
||||
targetID: number;
|
||||
troops: number;
|
||||
id: string;
|
||||
retreating: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export interface PlayerUpdate {
|
||||
export type PlayerUpdate = {
|
||||
type: GameUpdateType.Player;
|
||||
nameViewData?: NameViewData;
|
||||
clientID: ClientID | null;
|
||||
@@ -166,65 +166,65 @@ export interface PlayerUpdate {
|
||||
alliances: AllianceView[];
|
||||
hasSpawned: boolean;
|
||||
betrayals?: bigint;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AllianceView {
|
||||
export type AllianceView = {
|
||||
id: number;
|
||||
other: PlayerID;
|
||||
createdAt: Tick;
|
||||
expiresAt: Tick;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AllianceRequestUpdate {
|
||||
export type AllianceRequestUpdate = {
|
||||
type: GameUpdateType.AllianceRequest;
|
||||
requestorID: number;
|
||||
recipientID: number;
|
||||
createdAt: Tick;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AllianceRequestReplyUpdate {
|
||||
export type AllianceRequestReplyUpdate = {
|
||||
type: GameUpdateType.AllianceRequestReply;
|
||||
request: AllianceRequestUpdate;
|
||||
accepted: boolean;
|
||||
}
|
||||
};
|
||||
|
||||
export interface BrokeAllianceUpdate {
|
||||
export type BrokeAllianceUpdate = {
|
||||
type: GameUpdateType.BrokeAlliance;
|
||||
traitorID: number;
|
||||
betrayedID: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AllianceExpiredUpdate {
|
||||
export type AllianceExpiredUpdate = {
|
||||
type: GameUpdateType.AllianceExpired;
|
||||
player1ID: number;
|
||||
player2ID: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface AllianceExtensionUpdate {
|
||||
export type AllianceExtensionUpdate = {
|
||||
type: GameUpdateType.AllianceExtension;
|
||||
playerID: number;
|
||||
allianceID: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface TargetPlayerUpdate {
|
||||
export type TargetPlayerUpdate = {
|
||||
type: GameUpdateType.TargetPlayer;
|
||||
playerID: number;
|
||||
targetID: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface EmojiUpdate {
|
||||
export type EmojiUpdate = {
|
||||
type: GameUpdateType.Emoji;
|
||||
emoji: EmojiMessage;
|
||||
}
|
||||
};
|
||||
|
||||
export interface DisplayMessageUpdate {
|
||||
export type DisplayMessageUpdate = {
|
||||
type: GameUpdateType.DisplayEvent;
|
||||
message: string;
|
||||
messageType: MessageType;
|
||||
goldAmount?: bigint;
|
||||
playerID: number | null;
|
||||
params?: Record<string, string | number>;
|
||||
}
|
||||
};
|
||||
|
||||
export type DisplayChatMessageUpdate = {
|
||||
type: GameUpdateType.DisplayChatEvent;
|
||||
@@ -236,22 +236,22 @@ export type DisplayChatMessageUpdate = {
|
||||
recipient: string;
|
||||
};
|
||||
|
||||
export interface WinUpdate {
|
||||
export type WinUpdate = {
|
||||
type: GameUpdateType.Win;
|
||||
allPlayersStats: AllPlayersStats;
|
||||
winner: Winner;
|
||||
}
|
||||
};
|
||||
|
||||
export interface HashUpdate {
|
||||
export type HashUpdate = {
|
||||
type: GameUpdateType.Hash;
|
||||
tick: Tick;
|
||||
hash: number;
|
||||
}
|
||||
};
|
||||
|
||||
export interface UnitIncomingUpdate {
|
||||
export type UnitIncomingUpdate = {
|
||||
type: GameUpdateType.UnitIncoming;
|
||||
unitID: number;
|
||||
message: string;
|
||||
messageType: MessageType;
|
||||
playerID: number;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -39,10 +39,10 @@ import { UserSettings } from "./UserSettings";
|
||||
|
||||
const userSettings: UserSettings = new UserSettings();
|
||||
|
||||
interface PlayerCosmetics {
|
||||
type PlayerCosmetics = {
|
||||
pattern?: string | undefined;
|
||||
flag?: string | undefined;
|
||||
}
|
||||
};
|
||||
|
||||
export class UnitView {
|
||||
public _wasUpdated = true;
|
||||
@@ -106,7 +106,7 @@ export class UnitView {
|
||||
return this.data.pos;
|
||||
}
|
||||
owner(): PlayerView {
|
||||
return this.gameView.playerBySmallID(this.data.ownerID)! as PlayerView;
|
||||
return this.gameView.playerBySmallID(this.data.ownerID) as PlayerView;
|
||||
}
|
||||
isActive(): boolean {
|
||||
return this.data.isActive;
|
||||
|
||||
@@ -53,10 +53,10 @@ import {
|
||||
} from "./TransportShipUtils";
|
||||
import { UnitImpl } from "./UnitImpl";
|
||||
|
||||
interface Target {
|
||||
type Target = {
|
||||
tick: Tick;
|
||||
target: Player;
|
||||
}
|
||||
};
|
||||
|
||||
class Donation {
|
||||
constructor(
|
||||
@@ -66,7 +66,7 @@ class Donation {
|
||||
}
|
||||
|
||||
export class PlayerImpl implements Player {
|
||||
public _lastTileChange: number = 0;
|
||||
public _lastTileChange = 0;
|
||||
public _pseudo_random: PseudoRandom;
|
||||
|
||||
private _gold: bigint;
|
||||
@@ -278,7 +278,7 @@ export class PlayerImpl implements Player {
|
||||
}
|
||||
|
||||
tiles(): ReadonlySet<TileRef> {
|
||||
return new Set(this._tiles.values()) as Set<TileRef>;
|
||||
return new Set(this._tiles.values());
|
||||
}
|
||||
|
||||
borderTiles(): ReadonlySet<TileRef> {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Unit } from "./Game";
|
||||
import { TrainStation } from "./TrainStation";
|
||||
|
||||
export interface RailNetwork {
|
||||
export type RailNetwork = {
|
||||
connectStation(station: TrainStation): void;
|
||||
removeStation(unit: Unit): void;
|
||||
findStationsPath(from: TrainStation, to: TrainStation): TrainStation[];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -13,12 +13,12 @@ import { Cluster, TrainStation, TrainStationMapAdapter } from "./TrainStation";
|
||||
* but it would be expensive to look through the graph to find a station.
|
||||
* This class stores the existing stations for quick access
|
||||
*/
|
||||
export interface StationManager {
|
||||
export type StationManager = {
|
||||
addStation(station: TrainStation): void;
|
||||
removeStation(station: TrainStation): void;
|
||||
findStation(unit: Unit): TrainStation | null;
|
||||
getAll(): Set<TrainStation>;
|
||||
}
|
||||
};
|
||||
|
||||
export class StationManagerImpl implements StationManager {
|
||||
private stations: Set<TrainStation> = new Set();
|
||||
@@ -43,10 +43,10 @@ export class StationManagerImpl implements StationManager {
|
||||
}
|
||||
}
|
||||
|
||||
export interface RailPathFinderService {
|
||||
export type RailPathFinderService = {
|
||||
findTilePath(from: TileRef, to: TileRef): TileRef[];
|
||||
findStationsPath(from: TrainStation, to: TrainStation): TrainStation[];
|
||||
}
|
||||
};
|
||||
|
||||
class RailPathFinderServiceImpl implements RailPathFinderService {
|
||||
constructor(private game: Game) {}
|
||||
@@ -88,7 +88,7 @@ export function createRailNetwork(game: Game): RailNetwork {
|
||||
}
|
||||
|
||||
export class RailNetworkImpl implements RailNetwork {
|
||||
private maxConnectionDistance: number = 4;
|
||||
private maxConnectionDistance = 4;
|
||||
|
||||
constructor(
|
||||
private game: Game,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { AllPlayersStats } from "../Schemas";
|
||||
import { NukeType, OtherUnitType, PlayerStats } from "../StatsSchemas";
|
||||
import { Player, TerraNullius } from "./Game";
|
||||
|
||||
export interface Stats {
|
||||
export type Stats = {
|
||||
getPlayerStats(player: Player): PlayerStats | null;
|
||||
stats(): AllPlayersStats;
|
||||
|
||||
@@ -93,4 +93,4 @@ export interface Stats {
|
||||
|
||||
// Player loses a unit of type
|
||||
unitLose(player: Player, type: OtherUnitType): void;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -9,16 +9,16 @@ import { Railroad } from "./Railroad";
|
||||
/**
|
||||
* Handle train stops at various station types
|
||||
*/
|
||||
interface TrainStopHandler {
|
||||
type TrainStopHandler = {
|
||||
onStop(mg: Game, station: TrainStation, trainExecution: TrainExecution): void;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* All stop handlers share the same logic for the time being
|
||||
* Behavior to be defined
|
||||
*/
|
||||
class CityStopHandler implements TrainStopHandler {
|
||||
private factor: bigint = BigInt(2);
|
||||
private factor = BigInt(2);
|
||||
onStop(
|
||||
mg: Game,
|
||||
station: TrainStation,
|
||||
@@ -38,7 +38,7 @@ class CityStopHandler implements TrainStopHandler {
|
||||
}
|
||||
|
||||
class PortStopHandler implements TrainStopHandler {
|
||||
private factor: bigint = BigInt(2);
|
||||
private factor = BigInt(2);
|
||||
constructor(private random: PseudoRandom) {}
|
||||
onStop(
|
||||
mg: Game,
|
||||
@@ -59,7 +59,7 @@ class PortStopHandler implements TrainStopHandler {
|
||||
}
|
||||
|
||||
class FactoryStopHandler implements TrainStopHandler {
|
||||
private factor: bigint = BigInt(2);
|
||||
private factor = BigInt(2);
|
||||
onStop(
|
||||
mg: Game,
|
||||
station: TrainStation,
|
||||
|
||||
@@ -102,7 +102,7 @@ export function sourceDstOceanShore(
|
||||
const srcTile = closestShoreFromPlayer(gm, src, tile);
|
||||
let dstTile: TileRef | null = null;
|
||||
if (dst.isPlayer()) {
|
||||
dstTile = closestShoreFromPlayer(gm, dst as Player, tile);
|
||||
dstTile = closestShoreFromPlayer(gm, dst, tile);
|
||||
} else {
|
||||
dstTile = closestShoreTN(gm, tile, 50);
|
||||
}
|
||||
@@ -113,7 +113,7 @@ export function targetTransportTile(gm: Game, tile: TileRef): TileRef | null {
|
||||
const dst = gm.playerBySmallID(gm.ownerID(tile));
|
||||
let dstTile: TileRef | null = null;
|
||||
if (dst.isPlayer()) {
|
||||
dstTile = closestShoreFromPlayer(gm, dst as Player, tile);
|
||||
dstTile = closestShoreFromPlayer(gm, dst, tile);
|
||||
} else {
|
||||
dstTile = closestShoreTN(gm, tile, 50);
|
||||
}
|
||||
@@ -235,7 +235,7 @@ export function candidateShoreTiles(
|
||||
extremumTiles.maxX,
|
||||
extremumTiles.maxY,
|
||||
...sampledTiles,
|
||||
].filter(Boolean) as number[];
|
||||
].filter(Boolean);
|
||||
|
||||
return candidates;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ export class UnitImpl implements Unit {
|
||||
private _targetUnit: Unit | undefined;
|
||||
private _health: bigint;
|
||||
private _lastTile: TileRef;
|
||||
private _retreating: boolean = false;
|
||||
private _retreating = false;
|
||||
private _targetedBySAM = false;
|
||||
private _reachedTarget = false;
|
||||
private _lastSetSafeFromPirates: number; // Only for trade ships
|
||||
@@ -30,14 +30,14 @@ export class UnitImpl implements Unit {
|
||||
private _troops: number;
|
||||
// Number of missiles in cooldown, if empty all missiles are ready.
|
||||
private _missileTimerQueue: number[] = [];
|
||||
private _hasTrainStation: boolean = false;
|
||||
private _hasTrainStation = false;
|
||||
private _patrolTile: TileRef | undefined;
|
||||
private _level: number = 1;
|
||||
private _targetable: boolean = true;
|
||||
private _level = 1;
|
||||
private _targetable = true;
|
||||
private _loaded: boolean | undefined;
|
||||
private _trainType: TrainType | undefined;
|
||||
// Nuke only
|
||||
private _trajectoryIndex: number = 0;
|
||||
private _trajectoryIndex = 0;
|
||||
private _trajectory: TrajectoryTile[];
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export interface AStar<NodeType> {
|
||||
export type AStar<NodeType> = {
|
||||
compute(): PathFindResultType;
|
||||
reconstructPath(): NodeType[];
|
||||
}
|
||||
};
|
||||
|
||||
export enum PathFindResultType {
|
||||
NextTile,
|
||||
@@ -25,7 +25,7 @@ export type AStarResult<NodeType> =
|
||||
type: PathFindResultType.PathNotFound;
|
||||
};
|
||||
|
||||
export interface Point {
|
||||
export type Point = {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,8 +36,8 @@ export class MiniAStar implements AStar<TileRef> {
|
||||
private dst: TileRef,
|
||||
iterations: number,
|
||||
maxTries: number,
|
||||
waterPath: boolean = true,
|
||||
directionChangePenalty: number = 0,
|
||||
waterPath = true,
|
||||
directionChangePenalty = 0,
|
||||
) {
|
||||
const srcArray: TileRef[] = Array.isArray(src) ? src : [src];
|
||||
const miniSrc = srcArray.map((srcPoint) =>
|
||||
@@ -113,7 +113,7 @@ function fixExtremes(upscaled: Cell[], cellDst: Cell, cellSrc?: Cell): Cell[] {
|
||||
return upscaled;
|
||||
}
|
||||
|
||||
function upscalePath(path: Cell[], scaleFactor: number = 2): Cell[] {
|
||||
function upscalePath(path: Cell[], scaleFactor = 2): Cell[] {
|
||||
// Scale up each point
|
||||
const scaledPath = path.map(
|
||||
(point) => new Cell(point.x * scaleFactor, point.y * scaleFactor),
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user