diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index 26de903ae..9b225c143 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -64,13 +64,13 @@ export interface LobbyConfig { export function joinLobby( lobbyConfig: LobbyConfig, - onjoin: () => void + onjoin: () => void, ): () => void { const eventBus = new EventBus(); initRemoteSender(eventBus); consolex.log( - `joinging lobby: gameID: ${lobbyConfig.gameID}, clientID: ${lobbyConfig.clientID}, persistentID: ${lobbyConfig.persistentID}` + `joinging lobby: gameID: ${lobbyConfig.gameID}, clientID: ${lobbyConfig.clientID}, persistentID: ${lobbyConfig.persistentID}`, ); const serverConfig = getServerConfig(); @@ -91,7 +91,7 @@ export function joinLobby( lobbyConfig, gameConfig, eventBus, - serverConfig + serverConfig, ); const onconnect = () => { @@ -103,7 +103,7 @@ export function joinLobby( consolex.log("lobby: game started"); onjoin(); createClientGame(lobbyConfig, message.config, eventBus, transport).then( - (r) => r.start() + (r) => r.start(), ); } }; @@ -118,7 +118,7 @@ export async function createClientGame( lobbyConfig: LobbyConfig, gameConfig: GameConfig, eventBus: EventBus, - transport: Transport + transport: Transport, ): Promise { const config = getConfig(gameConfig); @@ -126,14 +126,14 @@ export async function createClientGame( const worker = new WorkerClient( lobbyConfig.gameID, gameConfig, - lobbyConfig.clientID + lobbyConfig.clientID, ); await worker.initialize(); const gameView = new GameView( worker, config, gameMap.gameMap, - lobbyConfig.clientID + lobbyConfig.clientID, ); consolex.log("going to init path finder"); @@ -143,11 +143,11 @@ export async function createClientGame( canvas, gameView, eventBus, - lobbyConfig.clientID + lobbyConfig.clientID, ); consolex.log( - `creating private game got difficulty: ${gameConfig.difficulty}` + `creating private game got difficulty: ${gameConfig.difficulty}`, ); return new ClientGameRunner( @@ -157,7 +157,7 @@ export async function createClientGame( new InputHandler(canvas, eventBus), transport, worker, - gameView + gameView, ); } @@ -175,7 +175,7 @@ export class ClientGameRunner { private input: InputHandler, private transport: Transport, private worker: WorkerClient, - private gameView: GameView + private gameView: GameView, ) {} public start() { @@ -223,7 +223,7 @@ export class ClientGameRunner { } if (this.turnsSeen != message.turn.turnNumber) { consolex.error( - `got wrong turn have turns ${this.turnsSeen}, received turn ${message.turn.turnNumber}` + `got wrong turn have turns ${this.turnsSeen}, received turn ${message.turn.turnNumber}`, ); } else { this.worker.sendTurn(message.turn); @@ -246,7 +246,7 @@ export class ClientGameRunner { } const cell = this.renderer.transformHandler.screenToWorldCoordinates( event.x, - event.y + event.y, ); if (!this.gameView.isValidCoord(cell.x, cell.y)) { return; @@ -276,8 +276,8 @@ export class ClientGameRunner { this.eventBus.emit( new SendAttackIntentEvent( this.gameView.owner(tile).id(), - this.myPlayer.troops() * this.renderer.uiState.attackRatio - ) + this.myPlayer.troops() * this.renderer.uiState.attackRatio, + ), ); } }); diff --git a/src/client/HostLobbyModal.ts b/src/client/HostLobbyModal.ts index 6ed8f9ae5..5951a5aba 100644 --- a/src/client/HostLobbyModal.ts +++ b/src/client/HostLobbyModal.ts @@ -355,7 +355,7 @@ export class HostLobbyModal extends LitElement { .selected=${this.selectedMap === value} > - ` + `, )} @@ -381,7 +381,7 @@ export class HostLobbyModal extends LitElement { ${DifficultyDescription[key]}

- ` + `, )} @@ -443,7 +443,7 @@ export class HostLobbyModal extends LitElement {
${this.players.map( - (player) => html`${player}` + (player) => html`${player}`, )}
@@ -484,7 +484,7 @@ export class HostLobbyModal extends LitElement { }, bubbles: true, composed: true, - }) + }), ); }); this.isModalOpen = true; @@ -545,7 +545,7 @@ export class HostLobbyModal extends LitElement { private async startGame() { consolex.log( - `Starting private game with map: ${GameMapType[this.selectedMap]}` + `Starting private game with map: ${GameMapType[this.selectedMap]}`, ); this.close(); const response = await fetch(`/start_private_lobby/${this.lobbyId}`, { diff --git a/src/client/InputHandler.ts b/src/client/InputHandler.ts index 9748d5fef..2162ccdc5 100644 --- a/src/client/InputHandler.ts +++ b/src/client/InputHandler.ts @@ -2,31 +2,46 @@ import { EventBus, GameEvent } from "../core/EventBus"; import { Game } from "../core/game/Game"; export class MouseUpEvent implements GameEvent { - constructor(public readonly x: number, public readonly y: number) {} + constructor( + public readonly x: number, + public readonly y: number, + ) {} } export class MouseDownEvent implements GameEvent { - constructor(public readonly x: number, public readonly y: number) {} + constructor( + public readonly x: number, + public readonly y: number, + ) {} } export class MouseMoveEvent implements GameEvent { - constructor(public readonly x: number, public readonly y: number) {} + constructor( + public readonly x: number, + public readonly y: number, + ) {} } export class ContextMenuEvent implements GameEvent { - constructor(public readonly x: number, public readonly y: number) {} + constructor( + public readonly x: number, + public readonly y: number, + ) {} } export class ZoomEvent implements GameEvent { constructor( public readonly x: number, public readonly y: number, - public readonly delta: number + public readonly delta: number, ) {} } export class DragEvent implements GameEvent { - constructor(public readonly deltaX: number, public readonly deltaY: number) {} + constructor( + public readonly deltaX: number, + public readonly deltaY: number, + ) {} } export class AlternateViewEvent implements GameEvent { @@ -36,7 +51,10 @@ export class AlternateViewEvent implements GameEvent { export class RefreshGraphicsEvent implements GameEvent {} export class ShowBuildMenuEvent implements GameEvent { - constructor(public readonly x: number, public readonly y: number) {} + constructor( + public readonly x: number, + public readonly y: number, + ) {} } export class InputHandler { @@ -60,7 +78,10 @@ export class InputHandler { private readonly PAN_SPEED = 5; private readonly ZOOM_SPEED = 10; - constructor(private canvas: HTMLCanvasElement, private eventBus: EventBus) {} + constructor( + private canvas: HTMLCanvasElement, + private eventBus: EventBus, + ) {} initialize() { this.canvas.addEventListener("pointerdown", (e) => this.onPointerDown(e)); @@ -105,12 +126,12 @@ export class InputHandler { if (this.activeKeys.has("Minus")) { this.eventBus.emit( - new ZoomEvent(screenCenterX, screenCenterY, this.ZOOM_SPEED) + new ZoomEvent(screenCenterX, screenCenterY, this.ZOOM_SPEED), ); } if (this.activeKeys.has("Equal")) { this.eventBus.emit( - new ZoomEvent(screenCenterX, screenCenterY, -this.ZOOM_SPEED) + new ZoomEvent(screenCenterX, screenCenterY, -this.ZOOM_SPEED), ); } }, 1); @@ -251,7 +272,7 @@ export class InputHandler { if (Math.abs(pinchDelta) > 1) { const zoomCenter = this.getPinchCenter(); this.eventBus.emit( - new ZoomEvent(zoomCenter.x, zoomCenter.y, -pinchDelta * 2) + new ZoomEvent(zoomCenter.x, zoomCenter.y, -pinchDelta * 2), ); this.lastPinchDistance = currentPinchDistance; } diff --git a/src/client/JoinPrivateLobbyModal.ts b/src/client/JoinPrivateLobbyModal.ts index f6b26bf1b..551754072 100644 --- a/src/client/JoinPrivateLobbyModal.ts +++ b/src/client/JoinPrivateLobbyModal.ts @@ -264,7 +264,7 @@ export class JoinPrivateLobbyModal extends LitElement {
${this.players.map( (player) => - html`${player}` + html`${player}`, )}
` @@ -302,7 +302,7 @@ export class JoinPrivateLobbyModal extends LitElement { detail: { lobby: this.lobbyIdInput.value }, bubbles: true, composed: true, - }) + }), ); } @@ -340,7 +340,7 @@ export class JoinPrivateLobbyModal extends LitElement { }, bubbles: true, composed: true, - }) + }), ); this.playersInterval = setInterval(() => this.pollPlayers(), 1000); } else { diff --git a/src/client/Main.ts b/src/client/Main.ts index 3b36a7fe4..490a41c24 100644 --- a/src/client/Main.ts +++ b/src/client/Main.ts @@ -1,179 +1,168 @@ -import { ClientGameRunner, joinLobby } from './ClientGameRunner'; -import backgroundImage from '../../resources/images/EuropeBackground.svg'; -import favicon from '../../resources/images/Favicon.svg'; +import { ClientGameRunner, joinLobby } from "./ClientGameRunner"; +import backgroundImage from "../../resources/images/EuropeBackground.svg"; +import favicon from "../../resources/images/Favicon.svg"; -import './PublicLobby'; -import './UsernameInput'; -import './styles.css'; -import { UsernameInput } from './UsernameInput'; -import { SinglePlayerModal } from './SinglePlayerModal'; -import { HostLobbyModal as HostPrivateLobbyModal } from './HostLobbyModal'; -import { JoinPrivateLobbyModal } from './JoinPrivateLobbyModal'; -import { generateID } from '../core/Util'; -import { generateCryptoRandomUUID } from './Utils'; -import { consolex } from '../core/Consolex'; -import './components/FlagInput'; -import { FlagInput } from './components/FlagInput'; +import "./PublicLobby"; +import "./UsernameInput"; +import "./styles.css"; +import { UsernameInput } from "./UsernameInput"; +import { SinglePlayerModal } from "./SinglePlayerModal"; +import { HostLobbyModal as HostPrivateLobbyModal } from "./HostLobbyModal"; +import { JoinPrivateLobbyModal } from "./JoinPrivateLobbyModal"; +import { generateID } from "../core/Util"; +import { generateCryptoRandomUUID } from "./Utils"; +import { consolex } from "../core/Consolex"; +import "./components/FlagInput"; +import { FlagInput } from "./components/FlagInput"; class Client { - private gameStop: () => void; + private gameStop: () => void; - private usernameInput: UsernameInput | null = null; - private flagInput: FlagInput | null = null; + private usernameInput: UsernameInput | null = null; + private flagInput: FlagInput | null = null; - private joinModal: JoinPrivateLobbyModal; - constructor() {} + private joinModal: JoinPrivateLobbyModal; + constructor() {} - initialize(): void { - this.flagInput = document.querySelector('flag-input') as FlagInput; - if (!this.flagInput) { - consolex.warn('Flag input element not found'); - } + initialize(): void { + this.flagInput = document.querySelector("flag-input") as FlagInput; + if (!this.flagInput) { + consolex.warn("Flag input element not found"); + } - this.usernameInput = document.querySelector( - 'username-input' - ) as UsernameInput; - if (!this.usernameInput) { - consolex.warn('Username input element not found'); - } - window.addEventListener('beforeunload', (event) => { - consolex.log('Browser is closing'); - if (this.gameStop != null) { - this.gameStop(); - } - }); + this.usernameInput = document.querySelector( + "username-input", + ) as UsernameInput; + if (!this.usernameInput) { + consolex.warn("Username input element not found"); + } + window.addEventListener("beforeunload", (event) => { + consolex.log("Browser is closing"); + if (this.gameStop != null) { + this.gameStop(); + } + }); - setFavicon(); - document.addEventListener( - 'join-lobby', - this.handleJoinLobby.bind(this) - ); - document.addEventListener( - 'leave-lobby', - this.handleLeaveLobby.bind(this) - ); - document.addEventListener( - 'single-player', - this.handleSinglePlayer.bind(this) - ); + setFavicon(); + document.addEventListener("join-lobby", this.handleJoinLobby.bind(this)); + document.addEventListener("leave-lobby", this.handleLeaveLobby.bind(this)); + document.addEventListener( + "single-player", + this.handleSinglePlayer.bind(this), + ); - const spModal = document.querySelector( - 'single-player-modal' - ) as SinglePlayerModal; - spModal instanceof SinglePlayerModal; - document - .getElementById('single-player') - .addEventListener('click', () => { - if (this.usernameInput.isValid()) { - spModal.open(); - } - }); + const spModal = document.querySelector( + "single-player-modal", + ) as SinglePlayerModal; + spModal instanceof SinglePlayerModal; + document.getElementById("single-player").addEventListener("click", () => { + if (this.usernameInput.isValid()) { + spModal.open(); + } + }); - const hostModal = document.querySelector( - 'host-lobby-modal' - ) as HostPrivateLobbyModal; - hostModal instanceof HostPrivateLobbyModal; - document - .getElementById('host-lobby-button') - .addEventListener('click', () => { - if (this.usernameInput.isValid()) { - hostModal.open(); - } - }); + const hostModal = document.querySelector( + "host-lobby-modal", + ) as HostPrivateLobbyModal; + hostModal instanceof HostPrivateLobbyModal; + document + .getElementById("host-lobby-button") + .addEventListener("click", () => { + if (this.usernameInput.isValid()) { + hostModal.open(); + } + }); - this.joinModal = document.querySelector( - 'join-private-lobby-modal' - ) as JoinPrivateLobbyModal; - this.joinModal instanceof JoinPrivateLobbyModal; - document - .getElementById('join-private-lobby-button') - .addEventListener('click', () => { - if (this.usernameInput.isValid()) { - this.joinModal.open(); - } - }); - } + this.joinModal = document.querySelector( + "join-private-lobby-modal", + ) as JoinPrivateLobbyModal; + this.joinModal instanceof JoinPrivateLobbyModal; + document + .getElementById("join-private-lobby-button") + .addEventListener("click", () => { + if (this.usernameInput.isValid()) { + this.joinModal.open(); + } + }); + } - private async handleJoinLobby(event: CustomEvent) { - const lobby = event.detail.lobby; - consolex.log(`joining lobby ${lobby.id}`); - if (this.gameStop != null) { - consolex.log('joining lobby, stopping existing game'); - this.gameStop(); - } - this.gameStop = joinLobby( - { - gameType: event.detail.gameType, - flag: (): string => this.flagInput.getCurrentFlag(), - playerName: (): string => - this.usernameInput.getCurrentUsername(), - gameID: lobby.id, - persistentID: getPersistentIDFromCookie(), - playerID: generateID(), - clientID: generateID(), - map: event.detail.map, - difficulty: event.detail.difficulty, - disableBots: event.detail.disableBots, - disableNPCs: event.detail.disableNPCs, - creativeMode: event.detail.creativeMode, - }, - () => this.joinModal.close() - ); - } + private async handleJoinLobby(event: CustomEvent) { + const lobby = event.detail.lobby; + consolex.log(`joining lobby ${lobby.id}`); + if (this.gameStop != null) { + consolex.log("joining lobby, stopping existing game"); + this.gameStop(); + } + this.gameStop = joinLobby( + { + gameType: event.detail.gameType, + flag: (): string => this.flagInput.getCurrentFlag(), + playerName: (): string => this.usernameInput.getCurrentUsername(), + gameID: lobby.id, + persistentID: getPersistentIDFromCookie(), + playerID: generateID(), + clientID: generateID(), + map: event.detail.map, + difficulty: event.detail.difficulty, + disableBots: event.detail.disableBots, + disableNPCs: event.detail.disableNPCs, + creativeMode: event.detail.creativeMode, + }, + () => this.joinModal.close(), + ); + } - private async handleLeaveLobby(event: CustomEvent) { - if (this.gameStop == null) { - return; - } - consolex.log('leaving lobby, cancelling game'); - this.gameStop(); - this.gameStop = null; - } + private async handleLeaveLobby(event: CustomEvent) { + if (this.gameStop == null) { + return; + } + consolex.log("leaving lobby, cancelling game"); + this.gameStop(); + this.gameStop = null; + } - private async handleSinglePlayer(event: CustomEvent) { - alert('coming soon'); - } + private async handleSinglePlayer(event: CustomEvent) { + alert("coming soon"); + } } // Initialize the client when the DOM is loaded -document.addEventListener('DOMContentLoaded', () => { - new Client().initialize(); +document.addEventListener("DOMContentLoaded", () => { + new Client().initialize(); }); document.body.style.backgroundImage = `url(${backgroundImage})`; function setFavicon(): void { - const link = document.createElement('link'); - link.type = 'image/x-icon'; - link.rel = 'shortcut icon'; - link.href = favicon; - document.head.appendChild(link); + const link = document.createElement("link"); + link.type = "image/x-icon"; + link.rel = "shortcut icon"; + link.href = favicon; + document.head.appendChild(link); } // WARNING: DO NOT EXPOSE THIS ID export function getPersistentIDFromCookie(): string { - const COOKIE_NAME = 'player_persistent_id'; + const COOKIE_NAME = "player_persistent_id"; - // Try to get existing cookie - const cookies = document.cookie.split(';'); - for (let cookie of cookies) { - const [cookieName, cookieValue] = cookie - .split('=') - .map((c) => c.trim()); - if (cookieName === COOKIE_NAME) { - return cookieValue; - } - } + // Try to get existing cookie + const cookies = document.cookie.split(";"); + for (let cookie of cookies) { + const [cookieName, cookieValue] = cookie.split("=").map((c) => c.trim()); + if (cookieName === COOKIE_NAME) { + return cookieValue; + } + } - // If no cookie exists, create new ID and set cookie - const newID = generateCryptoRandomUUID(); - document.cookie = [ - `${COOKIE_NAME}=${newID}`, - `max-age=${5 * 365 * 24 * 60 * 60}`, // 5 years - 'path=/', - 'SameSite=Strict', - 'Secure', - ].join(';'); + // If no cookie exists, create new ID and set cookie + const newID = generateCryptoRandomUUID(); + document.cookie = [ + `${COOKIE_NAME}=${newID}`, + `max-age=${5 * 365 * 24 * 60 * 60}`, // 5 years + "path=/", + "SameSite=Strict", + "Secure", + ].join(";"); - return newID; + return newID; } diff --git a/src/client/PublicLobby.ts b/src/client/PublicLobby.ts index 57fe25289..f1258e2d5 100644 --- a/src/client/PublicLobby.ts +++ b/src/client/PublicLobby.ts @@ -20,7 +20,7 @@ export class PublicLobby extends LitElement { this.fetchAndUpdateLobbies(); this.lobbiesInterval = window.setInterval( () => this.fetchAndUpdateLobbies(), - 1000 + 1000, ); } @@ -111,7 +111,7 @@ export class PublicLobby extends LitElement { }, bubbles: true, composed: true, - }) + }), ); } else { this.dispatchEvent( @@ -119,7 +119,7 @@ export class PublicLobby extends LitElement { detail: { lobby: this.currLobby }, bubbles: true, composed: true, - }) + }), ); this.currLobby = null; } diff --git a/src/client/SinglePlayerModal.ts b/src/client/SinglePlayerModal.ts index 966902cfe..16547ac14 100644 --- a/src/client/SinglePlayerModal.ts +++ b/src/client/SinglePlayerModal.ts @@ -251,7 +251,7 @@ export class SinglePlayerModal extends LitElement { .selected=${this.selectedMap === value} > - ` + `, )} @@ -277,7 +277,7 @@ export class SinglePlayerModal extends LitElement { ${DifficultyDescription[key]}

- ` + `, )} @@ -363,7 +363,7 @@ export class SinglePlayerModal extends LitElement { } private startGame() { consolex.log( - `Starting single player game with map: ${GameMapType[this.selectedMap]}` + `Starting single player game with map: ${GameMapType[this.selectedMap]}`, ); this.dispatchEvent( new CustomEvent("join-lobby", { @@ -380,7 +380,7 @@ export class SinglePlayerModal extends LitElement { }, bubbles: true, composed: true, - }) + }), ); this.close(); } diff --git a/src/client/Utils.ts b/src/client/Utils.ts index 744921aa8..6f8ffd47b 100644 --- a/src/client/Utils.ts +++ b/src/client/Utils.ts @@ -52,7 +52,7 @@ export function generateCryptoRandomUUID(): string { ( c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4))) - ).toString(16) + ).toString(16), ); } @@ -64,6 +64,6 @@ export function generateCryptoRandomUUID(): string { const r: number = (Math.random() * 16) | 0; const v: number = c === "x" ? r : (r & 0x3) | 0x8; return v.toString(16); - } + }, ); } diff --git a/src/client/components/FlagInput.ts b/src/client/components/FlagInput.ts index 27e31bab7..a17380df1 100644 --- a/src/client/components/FlagInput.ts +++ b/src/client/components/FlagInput.ts @@ -1,231 +1,217 @@ -import { LitElement, html, css } from 'lit'; -import { customElement, property, state } from 'lit/decorators.js'; -import Countries from '../data/countries.json'; +import { LitElement, html, css } from "lit"; +import { customElement, property, state } from "lit/decorators.js"; +import Countries from "../data/countries.json"; -const flagKey: string = 'flag'; +const flagKey: string = "flag"; -@customElement('flag-input') +@customElement("flag-input") export class FlagInput extends LitElement { - @state() private flag: string = ''; - @state() private search: string = ''; - @state() private showModal: boolean = false; + @state() private flag: string = ""; + @state() private search: string = ""; + @state() private showModal: boolean = false; - static styles = css` - .hidden { - display: none; - } + static styles = css` + .hidden { + display: none; + } - .flag-container { - display: flex; - } + .flag-container { + display: flex; + } - .no-selected-flag { - position: absolute; - left: 8px; - top: 8px; - height: 50px; - border-radius: 0.75rem; - border: none; - background: none; - font-size: 1rem; - cursor: pointer; - } + .no-selected-flag { + position: absolute; + left: 8px; + top: 8px; + height: 50px; + border-radius: 0.75rem; + border: none; + background: none; + font-size: 1rem; + cursor: pointer; + } - .selected-flag { - width: 48px; - cursor: pointer; - position: absolute; - left: 24px; - top: 14px; - border: 1px solid black; - } + .selected-flag { + width: 48px; + cursor: pointer; + position: absolute; + left: 24px; + top: 14px; + border: 1px solid black; + } - .flag-modal { - display: flex; - flex-direction: column; - gap: 0.5rem; - position: absolute; - top: 60px; - left: 0; - width: 560px; - height: 500px; - max-height: 50vh; - background-color: rgb(35 35 35 / 0.8); - -webkit-backdrop-filter: blur(12px); - backdrop-filter: blur(12px); - padding: 10px; - border-radius: 8px; - } + .flag-modal { + display: flex; + flex-direction: column; + gap: 0.5rem; + position: absolute; + top: 60px; + left: 0; + width: 560px; + height: 500px; + max-height: 50vh; + background-color: rgb(35 35 35 / 0.8); + -webkit-backdrop-filter: blur(12px); + backdrop-filter: blur(12px); + padding: 10px; + border-radius: 8px; + } - .flag-search { - height: 2rem; - border-radius: 8px; - border: none; - text-align: center; - font-size: 1.3rem; - } + .flag-search { + height: 2rem; + border-radius: 8px; + border: none; + text-align: center; + font-size: 1.3rem; + } - .flag-dropdown { - overflow-y: auto; - display: flex; - flex-direction: row; - flex-wrap: wrap; - gap: 1rem; - } + .flag-dropdown { + overflow-y: auto; + display: flex; + flex-direction: row; + flex-wrap: wrap; + gap: 1rem; + } - .dropdown-item { - opacity: 0.7; - width: calc(100% / 4 - 15px); - text-align: center; - color: white; - cursor: pointer; - border: none; - background: none; - } + .dropdown-item { + opacity: 0.7; + width: calc(100% / 4 - 15px); + text-align: center; + color: white; + cursor: pointer; + border: none; + background: none; + } - .dropdown-item:hover { - opacity: 1; - } + .dropdown-item:hover { + opacity: 1; + } - .country-flag { - width: 100%; - height: auto; - } + .country-flag { + width: 100%; + height: auto; + } - @media (max-width: 768px) { - .flag-modal { - left: 0px; - width: calc(100% - 16px); - height: 50vh; - } + @media (max-width: 768px) { + .flag-modal { + left: 0px; + width: calc(100% - 16px); + height: 50vh; + } - .dropdown-item { - width: calc(100% / 3 - 15px); - } - } - `; + .dropdown-item { + width: calc(100% / 3 - 15px); + } + } + `; - private handleSearch(e: Event) { - this.search = String((e.target as HTMLInputElement).value); - } + private handleSearch(e: Event) { + this.search = String((e.target as HTMLInputElement).value); + } - private setFlag(flag: string) { - this.flag = flag; - this.showModal = false; - this.storeFlag(flag); - } + private setFlag(flag: string) { + this.flag = flag; + this.showModal = false; + this.storeFlag(flag); + } - public getCurrentFlag(): string { - return this.flag; - } + public getCurrentFlag(): string { + return this.flag; + } - private getStoredFlag(): string { - const storedFlag = localStorage.getItem(flagKey); - if (storedFlag) { - return storedFlag; - } - return ''; - } + private getStoredFlag(): string { + const storedFlag = localStorage.getItem(flagKey); + if (storedFlag) { + return storedFlag; + } + return ""; + } - private storeFlag(flag: string) { - if (flag) { - localStorage.setItem(flagKey, flag); - } else if (flag === '') { - localStorage.removeItem(flagKey); - } - } + private storeFlag(flag: string) { + if (flag) { + localStorage.setItem(flagKey, flag); + } else if (flag === "") { + localStorage.removeItem(flagKey); + } + } - private dispatchFlagEvent() { - this.dispatchEvent( - new CustomEvent('flag-change', { - detail: { flag: this.flag }, - bubbles: true, - composed: true, - }) - ); - } + private dispatchFlagEvent() { + this.dispatchEvent( + new CustomEvent("flag-change", { + detail: { flag: this.flag }, + bubbles: true, + composed: true, + }), + ); + } - connectedCallback() { - super.connectedCallback(); - this.flag = this.getStoredFlag(); - this.dispatchFlagEvent(); - } + connectedCallback() { + super.connectedCallback(); + this.flag = this.getStoredFlag(); + this.dispatchFlagEvent(); + } - render() { - return html` -
- ${this.flag === '' - ? html` ` - : html` (this.showModal = true)} - />`} - ${this.showModal - ? html` -
- -
- - - ${Countries.filter( - (country) => - country.name - .toLowerCase() - .includes( - this.search.toLowerCase() - ) || - country.code - .toLowerCase() - .includes( - this.search.toLowerCase() - ) - ).map( - (country) => html` - - ` - )} -
-
- ` - : ''} -
- `; - } + render() { + return html` +
+ ${this.flag === "" + ? html` ` + : html` (this.showModal = true)} + />`} + ${this.showModal + ? html` +
+ +
+ + + ${Countries.filter( + (country) => + country.name + .toLowerCase() + .includes(this.search.toLowerCase()) || + country.code + .toLowerCase() + .includes(this.search.toLowerCase()), + ).map( + (country) => html` + + `, + )} +
+
+ ` + : ""} +
+ `; + } } diff --git a/src/client/data/countries.json b/src/client/data/countries.json index a3f9e6234..f67812d9e 100644 --- a/src/client/data/countries.json +++ b/src/client/data/countries.json @@ -1,1336 +1,1336 @@ [ - { - "code": "af", - "continent": "Asia", - "name": "Afghanistan" - }, - { - "code": "ax", - "continent": "Europe", - "name": "Aland Islands" - }, - { - "code": "al", - "continent": "Europe", - "name": "Albania" - }, - { - "code": "dz", - "continent": "Africa", - "name": "Algeria" - }, - { - "code": "as", - "continent": "Oceania", - "name": "American Samoa" - }, - { - "code": "ad", - "continent": "Europe", - "name": "Andorra" - }, - { - "code": "ao", - "continent": "Africa", - "name": "Angola" - }, - { - "code": "ai", - "continent": "North America", - "name": "Anguilla" - }, - { - "code": "aq", - "name": "Antarctica" - }, - { - "code": "ag", - "continent": "North America", - "name": "Antigua and Barbuda" - }, - { - "code": "ar", - "continent": "South America", - "name": "Argentina" - }, - { - "code": "am", - "continent": "Asia", - "name": "Armenia" - }, - { - "code": "aw", - "continent": "South America", - "name": "Aruba" - }, - { - "code": "sh-ac", - "continent": "Africa", - "name": "Ascension Island" - }, - { - "code": "asean", - "name": "Association of Southeast Asian Nations" - }, - { - "code": "au", - "continent": "Oceania", - "name": "Australia" - }, - { - "code": "at", - "continent": "Europe", - "name": "Austria" - }, - { - "code": "az", - "continent": "Asia", - "name": "Azerbaijan" - }, - { - "code": "bs", - "continent": "North America", - "name": "Bahamas" - }, - { - "code": "bh", - "continent": "Asia", - "name": "Bahrain" - }, - { - "code": "bd", - "continent": "Asia", - "name": "Bangladesh" - }, - { - "code": "bb", - "continent": "North America", - "name": "Barbados" - }, - { - "code": "es-pv", - "name": "Basque Country" - }, - { - "code": "by", - "continent": "Europe", - "name": "Belarus" - }, - { - "code": "be", - "continent": "Europe", - "name": "Belgium" - }, - { - "code": "bz", - "continent": "North America", - "name": "Belize" - }, - { - "code": "bj", - "continent": "Africa", - "name": "Benin" - }, - { - "code": "bm", - "continent": "North America", - "name": "Bermuda" - }, - { - "code": "bt", - "continent": "Asia", - "name": "Bhutan" - }, - { - "code": "bo", - "continent": "South America", - "name": "Bolivia" - }, - { - "code": "bq", - "continent": "South America", - "name": "Bonaire, Sint Eustatius and Saba" - }, - { - "code": "ba", - "continent": "Europe", - "name": "Bosnia and Herzegovina" - }, - { - "code": "bw", - "continent": "Africa", - "name": "Botswana" - }, - { - "code": "bv", - "name": "Bouvet Island" - }, - { - "code": "br", - "continent": "South America", - "name": "Brazil" - }, - { - "code": "io", - "continent": "Asia", - "name": "British Indian Ocean Territory" - }, - { - "code": "bn", - "continent": "Asia", - "name": "Brunei Darussalam" - }, - { - "code": "bg", - "continent": "Europe", - "name": "Bulgaria" - }, - { - "code": "bf", - "continent": "Africa", - "name": "Burkina Faso" - }, - { - "code": "bi", - "continent": "Africa", - "name": "Burundi" - }, - { - "code": "cv", - "continent": "Africa", - "name": "Cabo Verde" - }, - { - "code": "kh", - "continent": "Asia", - "name": "Cambodia" - }, - { - "code": "cm", - "continent": "Africa", - "name": "Cameroon" - }, - { - "code": "ca", - "continent": "North America", - "name": "Canada" - }, - { - "code": "ic", - "name": "Canary Islands" - }, - { - "code": "es-ct", - "name": "Catalonia" - }, - { - "code": "ky", - "continent": "North America", - "name": "Cayman Islands" - }, - { - "code": "cf", - "continent": "Africa", - "name": "Central African Republic" - }, - { - "code": "cefta", - "name": "Central European Free Trade Agreement" - }, - { - "code": "td", - "continent": "Africa", - "name": "Chad" - }, - { - "code": "cl", - "continent": "South America", - "name": "Chile" - }, - { - "code": "cn", - "continent": "Asia", - "name": "China" - }, - { - "code": "cx", - "continent": "Asia", - "name": "Christmas Island" - }, - { - "code": "cp", - "name": "Clipperton Island" - }, - { - "code": "cc", - "continent": "Asia", - "name": "Cocos (Keeling) Islands" - }, - { - "code": "co", - "continent": "South America", - "name": "Colombia" - }, - { - "code": "km", - "continent": "Africa", - "name": "Comoros" - }, - { - "code": "ck", - "continent": "Oceania", - "name": "Cook Islands" - }, - { - "code": "cr", - "continent": "North America", - "name": "Costa Rica" - }, - { - "code": "hr", - "continent": "Europe", - "name": "Croatia" - }, - { - "code": "cu", - "continent": "North America", - "name": "Cuba" - }, - { - "code": "cw", - "continent": "South America", - "name": "Curaçao" - }, - { - "code": "cy", - "continent": "Europe", - "name": "Cyprus" - }, - { - "code": "cz", - "continent": "Europe", - "name": "Czech Republic" - }, - { - "code": "ci", - "continent": "Africa", - "name": "Côte d'Ivoire" - }, - { - "code": "cd", - "continent": "Africa", - "name": "Democratic Republic of the Congo" - }, - { - "code": "dk", - "continent": "Europe", - "name": "Denmark" - }, - { - "code": "dg", - "name": "Diego Garcia" - }, - { - "code": "dj", - "continent": "Africa", - "name": "Djibouti" - }, - { - "code": "dm", - "continent": "North America", - "name": "Dominica" - }, - { - "code": "do", - "continent": "North America", - "name": "Dominican Republic" - }, - { - "code": "eac", - "name": "East African Community" - }, - { - "code": "ec", - "continent": "South America", - "name": "Ecuador" - }, - { - "code": "eg", - "continent": "Africa", - "name": "Egypt" - }, - { - "code": "sv", - "continent": "North America", - "name": "El Salvador" - }, - { - "code": "gb-eng", - "continent": "Europe", - "name": "England" - }, - { - "code": "gq", - "continent": "Africa", - "name": "Equatorial Guinea" - }, - { - "code": "er", - "continent": "Africa", - "name": "Eritrea" - }, - { - "code": "ee", - "continent": "Europe", - "name": "Estonia" - }, - { - "code": "sz", - "continent": "Africa", - "name": "Eswatini" - }, - { - "code": "et", - "continent": "Africa", - "name": "Ethiopia" - }, - { - "code": "eu", - "name": "Europe" - }, - { - "code": "fk", - "continent": "South America", - "name": "Falkland Islands" - }, - { - "code": "fo", - "continent": "Europe", - "name": "Faroe Islands" - }, - { - "code": "fm", - "continent": "Oceania", - "name": "Federated States of Micronesia" - }, - { - "code": "fj", - "continent": "Oceania", - "name": "Fiji" - }, - { - "code": "fi", - "continent": "Europe", - "name": "Finland" - }, - { - "code": "fr", - "continent": "Europe", - "name": "France" - }, - { - "code": "gf", - "continent": "South America", - "name": "French Guiana" - }, - { - "code": "pf", - "continent": "Oceania", - "name": "French Polynesia" - }, - { - "code": "tf", - "continent": "Africa", - "name": "French Southern Territories" - }, - { - "code": "ga", - "continent": "Africa", - "name": "Gabon" - }, - { - "code": "es-ga", - "name": "Galicia" - }, - { - "code": "gm", - "continent": "Africa", - "name": "Gambia" - }, - { - "code": "ge", - "continent": "Asia", - "name": "Georgia" - }, - { - "code": "de", - "continent": "Europe", - "name": "Germany" - }, - { - "code": "gh", - "continent": "Africa", - "name": "Ghana" - }, - { - "code": "gi", - "continent": "Europe", - "name": "Gibraltar" - }, - { - "code": "gr", - "continent": "Europe", - "name": "Greece" - }, - { - "code": "gl", - "continent": "North America", - "name": "Greenland" - }, - { - "code": "gd", - "continent": "North America", - "name": "Grenada" - }, - { - "code": "gp", - "continent": "North America", - "name": "Guadeloupe" - }, - { - "code": "gu", - "continent": "Oceania", - "name": "Guam" - }, - { - "code": "gt", - "continent": "North America", - "name": "Guatemala" - }, - { - "code": "gg", - "continent": "Europe", - "name": "Guernsey" - }, - { - "code": "gn", - "continent": "Africa", - "name": "Guinea" - }, - { - "code": "gw", - "continent": "Africa", - "name": "Guinea-Bissau" - }, - { - "code": "gy", - "continent": "South America", - "name": "Guyana" - }, - { - "code": "ht", - "continent": "North America", - "name": "Haiti" - }, - { - "code": "hm", - "name": "Heard Island and McDonald Islands" - }, - { - "code": "va", - "continent": "Europe", - "name": "Holy See" - }, - { - "code": "hn", - "continent": "North America", - "name": "Honduras" - }, - { - "code": "hk", - "continent": "Asia", - "name": "Hong Kong" - }, - { - "code": "hu", - "continent": "Europe", - "name": "Hungary" - }, - { - "code": "is", - "continent": "Europe", - "name": "Iceland" - }, - { - "code": "in", - "continent": "Asia", - "name": "India" - }, - { - "code": "id", - "continent": "Asia", - "name": "Indonesia" - }, - { - "code": "ir", - "continent": "Asia", - "name": "Iran" - }, - { - "code": "iq", - "continent": "Asia", - "name": "Iraq" - }, - { - "code": "ie", - "continent": "Europe", - "name": "Ireland" - }, - { - "code": "im", - "continent": "Europe", - "name": "Isle of Man" - }, - { - "code": "il", - "continent": "Asia", - "name": "Israel" - }, - { - "code": "it", - "continent": "Europe", - "name": "Italy" - }, - { - "code": "jm", - "continent": "North America", - "name": "Jamaica" - }, - { - "code": "jp", - "continent": "Asia", - "name": "Japan" - }, - { - "code": "je", - "continent": "Europe", - "name": "Jersey" - }, - { - "code": "jo", - "continent": "Asia", - "name": "Jordan" - }, - { - "code": "kz", - "continent": "Asia", - "name": "Kazakhstan" - }, - { - "code": "ke", - "continent": "Africa", - "name": "Kenya" - }, - { - "code": "ki", - "continent": "Oceania", - "name": "Kiribati" - }, - { - "code": "xk", - "continent": "Europe", - "name": "Kosovo" - }, - { - "code": "kw", - "continent": "Asia", - "name": "Kuwait" - }, - { - "code": "kg", - "continent": "Asia", - "name": "Kyrgyzstan" - }, - { - "code": "la", - "continent": "Asia", - "name": "Laos" - }, - { - "code": "lv", - "continent": "Europe", - "name": "Latvia" - }, - { - "code": "arab", - "name": "League of Arab States" - }, - { - "code": "lb", - "continent": "Asia", - "name": "Lebanon" - }, - { - "code": "ls", - "continent": "Africa", - "name": "Lesotho" - }, - { - "code": "lr", - "continent": "Africa", - "name": "Liberia" - }, - { - "code": "ly", - "continent": "Africa", - "name": "Libya" - }, - { - "code": "li", - "continent": "Europe", - "name": "Liechtenstein" - }, - { - "code": "lt", - "continent": "Europe", - "name": "Lithuania" - }, - { - "code": "lu", - "continent": "Europe", - "name": "Luxembourg" - }, - { - "code": "mo", - "continent": "Asia", - "name": "Macau" - }, - { - "code": "mg", - "continent": "Africa", - "name": "Madagascar" - }, - { - "code": "mw", - "continent": "Africa", - "name": "Malawi" - }, - { - "code": "my", - "continent": "Asia", - "name": "Malaysia" - }, - { - "code": "mv", - "continent": "Asia", - "name": "Maldives" - }, - { - "code": "ml", - "continent": "Africa", - "name": "Mali" - }, - { - "code": "mt", - "continent": "Europe", - "name": "Malta" - }, - { - "code": "mh", - "continent": "Oceania", - "name": "Marshall Islands" - }, - { - "code": "mq", - "continent": "North America", - "name": "Martinique" - }, - { - "code": "mr", - "continent": "Africa", - "name": "Mauritania" - }, - { - "code": "mu", - "continent": "Africa", - "name": "Mauritius" - }, - { - "code": "yt", - "continent": "Africa", - "name": "Mayotte" - }, - { - "code": "mx", - "continent": "North America", - "name": "Mexico" - }, - { - "code": "md", - "continent": "Europe", - "name": "Moldova" - }, - { - "code": "mc", - "continent": "Europe", - "name": "Monaco" - }, - { - "code": "mn", - "continent": "Asia", - "name": "Mongolia" - }, - { - "code": "me", - "continent": "Europe", - "name": "Montenegro" - }, - { - "code": "ms", - "continent": "North America", - "name": "Montserrat" - }, - { - "code": "ma", - "continent": "Africa", - "name": "Morocco" - }, - { - "code": "mz", - "continent": "Africa", - "name": "Mozambique" - }, - { - "code": "mm", - "continent": "Asia", - "name": "Myanmar" - }, - { - "code": "na", - "continent": "Africa", - "name": "Namibia" - }, - { - "code": "nr", - "continent": "Oceania", - "name": "Nauru" - }, - { - "code": "np", - "continent": "Asia", - "name": "Nepal" - }, - { - "code": "nl", - "continent": "Europe", - "name": "Netherlands" - }, - { - "code": "nc", - "continent": "Oceania", - "name": "New Caledonia" - }, - { - "code": "nz", - "continent": "Oceania", - "name": "New Zealand" - }, - { - "code": "ni", - "continent": "North America", - "name": "Nicaragua" - }, - { - "code": "ne", - "continent": "Africa", - "name": "Niger" - }, - { - "code": "ng", - "continent": "Africa", - "name": "Nigeria" - }, - { - "code": "nu", - "continent": "Oceania", - "name": "Niue" - }, - { - "code": "nf", - "continent": "Oceania", - "name": "Norfolk Island" - }, - { - "code": "kp", - "continent": "Asia", - "name": "North Korea" - }, - { - "code": "mk", - "continent": "Europe", - "name": "North Macedonia" - }, - { - "code": "gb-nir", - "continent": "Europe", - "name": "Northern Ireland" - }, - { - "code": "mp", - "continent": "Oceania", - "name": "Northern Mariana Islands" - }, - { - "code": "no", - "continent": "Europe", - "name": "Norway" - }, - { - "code": "om", - "continent": "Asia", - "name": "Oman" - }, - { - "code": "pc", - "name": "Pacific Community" - }, - { - "code": "pk", - "continent": "Asia", - "name": "Pakistan" - }, - { - "code": "pw", - "continent": "Oceania", - "name": "Palau" - }, - { - "code": "pa", - "continent": "North America", - "name": "Panama" - }, - { - "code": "pg", - "continent": "Oceania", - "name": "Papua New Guinea" - }, - { - "code": "py", - "continent": "South America", - "name": "Paraguay" - }, - { - "code": "pe", - "continent": "South America", - "name": "Peru" - }, - { - "code": "ph", - "continent": "Asia", - "name": "Philippines" - }, - { - "code": "pn", - "continent": "Oceania", - "name": "Pitcairn" - }, - { - "code": "pl", - "continent": "Europe", - "name": "Poland" - }, - { - "code": "pt", - "continent": "Europe", - "name": "Portugal" - }, - { - "code": "pr", - "continent": "North America", - "name": "Puerto Rico" - }, - { - "code": "qa", - "continent": "Asia", - "name": "Qatar" - }, - { - "code": "cg", - "continent": "Africa", - "name": "Republic of the Congo" - }, - { - "code": "ro", - "continent": "Europe", - "name": "Romania" - }, - { - "code": "ru", - "continent": "Europe", - "name": "Russia" - }, - { - "code": "rw", - "continent": "Africa", - "name": "Rwanda" - }, - { - "code": "re", - "continent": "Africa", - "name": "Réunion" - }, - { - "code": "bl", - "continent": "North America", - "name": "Saint Barthélemy" - }, - { - "code": "sh-hl", - "continent": "Africa", - "name": "Saint Helena" - }, - { - "code": "sh", - "continent": "Africa", - "name": "Saint Helena, Ascension and Tristan da Cunha" - }, - { - "code": "kn", - "continent": "North America", - "name": "Saint Kitts and Nevis" - }, - { - "code": "lc", - "continent": "North America", - "name": "Saint Lucia" - }, - { - "code": "mf", - "continent": "North America", - "name": "Saint Martin" - }, - { - "code": "pm", - "continent": "North America", - "name": "Saint Pierre and Miquelon" - }, - { - "code": "vc", - "continent": "North America", - "name": "Saint Vincent and the Grenadines" - }, - { - "code": "ws", - "continent": "Oceania", - "name": "Samoa" - }, - { - "code": "sm", - "continent": "Europe", - "name": "San Marino" - }, - { - "code": "st", - "continent": "Africa", - "name": "Sao Tome and Principe" - }, - { - "code": "sa", - "continent": "Asia", - "name": "Saudi Arabia" - }, - { - "code": "gb-sct", - "continent": "Europe", - "name": "Scotland" - }, - { - "code": "sn", - "continent": "Africa", - "name": "Senegal" - }, - { - "code": "rs", - "continent": "Europe", - "name": "Serbia" - }, - { - "code": "sc", - "continent": "Africa", - "name": "Seychelles" - }, - { - "code": "sl", - "continent": "Africa", - "name": "Sierra Leone" - }, - { - "code": "sg", - "continent": "Asia", - "name": "Singapore" - }, - { - "code": "sx", - "continent": "North America", - "name": "Sint Maarten" - }, - { - "code": "sk", - "continent": "Europe", - "name": "Slovakia" - }, - { - "code": "si", - "continent": "Europe", - "name": "Slovenia" - }, - { - "code": "sb", - "continent": "Oceania", - "name": "Solomon Islands" - }, - { - "code": "so", - "continent": "Africa", - "name": "Somalia" - }, - { - "code": "za", - "continent": "Africa", - "name": "South Africa" - }, - { - "code": "gs", - "continent": "Antarctica", - "name": "South Georgia and the South Sandwich Islands" - }, - { - "code": "kr", - "continent": "Asia", - "name": "South Korea" - }, - { - "code": "ss", - "continent": "Africa", - "name": "South Sudan" - }, - { - "code": "es", - "continent": "Europe", - "name": "Spain" - }, - { - "code": "lk", - "continent": "Asia", - "name": "Sri Lanka" - }, - { - "code": "ps", - "continent": "Asia", - "name": "State of Palestine" - }, - { - "code": "sd", - "continent": "Africa", - "name": "Sudan" - }, - { - "code": "sr", - "continent": "South America", - "name": "Suriname" - }, - { - "code": "sj", - "continent": "Europe", - "name": "Svalbard and Jan Mayen" - }, - { - "code": "se", - "continent": "Europe", - "name": "Sweden" - }, - { - "code": "ch", - "continent": "Europe", - "name": "Switzerland" - }, - { - "code": "sy", - "continent": "Asia", - "name": "Syria" - }, - { - "code": "tw", - "continent": "Asia", - "name": "Taiwan" - }, - { - "code": "tj", - "continent": "Asia", - "name": "Tajikistan" - }, - { - "code": "tz", - "continent": "Africa", - "name": "Tanzania" - }, - { - "code": "th", - "continent": "Asia", - "name": "Thailand" - }, - { - "code": "tl", - "continent": "Asia", - "name": "Timor-Leste" - }, - { - "code": "tg", - "continent": "Africa", - "name": "Togo" - }, - { - "code": "tk", - "continent": "Oceania", - "name": "Tokelau" - }, - { - "code": "to", - "continent": "Oceania", - "name": "Tonga" - }, - { - "code": "tt", - "continent": "South America", - "name": "Trinidad and Tobago" - }, - { - "code": "sh-ta", - "continent": "Africa", - "name": "Tristan da Cunha" - }, - { - "code": "tn", - "continent": "Africa", - "name": "Tunisia" - }, - { - "code": "tm", - "continent": "Asia", - "name": "Turkmenistan" - }, - { - "code": "tc", - "continent": "North America", - "name": "Turks and Caicos Islands" - }, - { - "code": "tv", - "continent": "Oceania", - "name": "Tuvalu" - }, - { - "code": "tr", - "continent": "Asia", - "name": "Türkiye" - }, - { - "code": "ug", - "continent": "Africa", - "name": "Uganda" - }, - { - "code": "ua", - "continent": "Europe", - "name": "Ukraine" - }, - { - "code": "ae", - "continent": "Asia", - "name": "United Arab Emirates" - }, - { - "code": "gb", - "continent": "Europe", - "name": "United Kingdom" - }, - { - "code": "un", - "name": "United Nations" - }, - { - "code": "um", - "continent": "North America", - "name": "United States Minor Outlying Islands" - }, - { - "code": "us", - "continent": "North America", - "name": "United States of America" - }, - { - "code": "uy", - "continent": "South America", - "name": "Uruguay" - }, - { - "code": "uz", - "continent": "Asia", - "name": "Uzbekistan" - }, - { - "code": "vu", - "continent": "Oceania", - "name": "Vanuatu" - }, - { - "code": "ve", - "continent": "South America", - "name": "Venezuela" - }, - { - "code": "vn", - "continent": "Asia", - "name": "Vietnam" - }, - { - "code": "vg", - "continent": "North America", - "name": "Virgin Islands (British)" - }, - { - "code": "vi", - "continent": "North America", - "name": "Virgin Islands (U.S.)" - }, - { - "code": "gb-wls", - "continent": "Europe", - "name": "Wales" - }, - { - "code": "wf", - "continent": "Oceania", - "name": "Wallis and Futuna" - }, - { - "code": "eh", - "continent": "Africa", - "name": "Western Sahara" - }, - { - "code": "ye", - "continent": "Asia", - "name": "Yemen" - }, - { - "code": "zm", - "continent": "Africa", - "name": "Zambia" - }, - { - "code": "zw", - "continent": "Africa", - "name": "Zimbabwe" - } + { + "code": "af", + "continent": "Asia", + "name": "Afghanistan" + }, + { + "code": "ax", + "continent": "Europe", + "name": "Aland Islands" + }, + { + "code": "al", + "continent": "Europe", + "name": "Albania" + }, + { + "code": "dz", + "continent": "Africa", + "name": "Algeria" + }, + { + "code": "as", + "continent": "Oceania", + "name": "American Samoa" + }, + { + "code": "ad", + "continent": "Europe", + "name": "Andorra" + }, + { + "code": "ao", + "continent": "Africa", + "name": "Angola" + }, + { + "code": "ai", + "continent": "North America", + "name": "Anguilla" + }, + { + "code": "aq", + "name": "Antarctica" + }, + { + "code": "ag", + "continent": "North America", + "name": "Antigua and Barbuda" + }, + { + "code": "ar", + "continent": "South America", + "name": "Argentina" + }, + { + "code": "am", + "continent": "Asia", + "name": "Armenia" + }, + { + "code": "aw", + "continent": "South America", + "name": "Aruba" + }, + { + "code": "sh-ac", + "continent": "Africa", + "name": "Ascension Island" + }, + { + "code": "asean", + "name": "Association of Southeast Asian Nations" + }, + { + "code": "au", + "continent": "Oceania", + "name": "Australia" + }, + { + "code": "at", + "continent": "Europe", + "name": "Austria" + }, + { + "code": "az", + "continent": "Asia", + "name": "Azerbaijan" + }, + { + "code": "bs", + "continent": "North America", + "name": "Bahamas" + }, + { + "code": "bh", + "continent": "Asia", + "name": "Bahrain" + }, + { + "code": "bd", + "continent": "Asia", + "name": "Bangladesh" + }, + { + "code": "bb", + "continent": "North America", + "name": "Barbados" + }, + { + "code": "es-pv", + "name": "Basque Country" + }, + { + "code": "by", + "continent": "Europe", + "name": "Belarus" + }, + { + "code": "be", + "continent": "Europe", + "name": "Belgium" + }, + { + "code": "bz", + "continent": "North America", + "name": "Belize" + }, + { + "code": "bj", + "continent": "Africa", + "name": "Benin" + }, + { + "code": "bm", + "continent": "North America", + "name": "Bermuda" + }, + { + "code": "bt", + "continent": "Asia", + "name": "Bhutan" + }, + { + "code": "bo", + "continent": "South America", + "name": "Bolivia" + }, + { + "code": "bq", + "continent": "South America", + "name": "Bonaire, Sint Eustatius and Saba" + }, + { + "code": "ba", + "continent": "Europe", + "name": "Bosnia and Herzegovina" + }, + { + "code": "bw", + "continent": "Africa", + "name": "Botswana" + }, + { + "code": "bv", + "name": "Bouvet Island" + }, + { + "code": "br", + "continent": "South America", + "name": "Brazil" + }, + { + "code": "io", + "continent": "Asia", + "name": "British Indian Ocean Territory" + }, + { + "code": "bn", + "continent": "Asia", + "name": "Brunei Darussalam" + }, + { + "code": "bg", + "continent": "Europe", + "name": "Bulgaria" + }, + { + "code": "bf", + "continent": "Africa", + "name": "Burkina Faso" + }, + { + "code": "bi", + "continent": "Africa", + "name": "Burundi" + }, + { + "code": "cv", + "continent": "Africa", + "name": "Cabo Verde" + }, + { + "code": "kh", + "continent": "Asia", + "name": "Cambodia" + }, + { + "code": "cm", + "continent": "Africa", + "name": "Cameroon" + }, + { + "code": "ca", + "continent": "North America", + "name": "Canada" + }, + { + "code": "ic", + "name": "Canary Islands" + }, + { + "code": "es-ct", + "name": "Catalonia" + }, + { + "code": "ky", + "continent": "North America", + "name": "Cayman Islands" + }, + { + "code": "cf", + "continent": "Africa", + "name": "Central African Republic" + }, + { + "code": "cefta", + "name": "Central European Free Trade Agreement" + }, + { + "code": "td", + "continent": "Africa", + "name": "Chad" + }, + { + "code": "cl", + "continent": "South America", + "name": "Chile" + }, + { + "code": "cn", + "continent": "Asia", + "name": "China" + }, + { + "code": "cx", + "continent": "Asia", + "name": "Christmas Island" + }, + { + "code": "cp", + "name": "Clipperton Island" + }, + { + "code": "cc", + "continent": "Asia", + "name": "Cocos (Keeling) Islands" + }, + { + "code": "co", + "continent": "South America", + "name": "Colombia" + }, + { + "code": "km", + "continent": "Africa", + "name": "Comoros" + }, + { + "code": "ck", + "continent": "Oceania", + "name": "Cook Islands" + }, + { + "code": "cr", + "continent": "North America", + "name": "Costa Rica" + }, + { + "code": "hr", + "continent": "Europe", + "name": "Croatia" + }, + { + "code": "cu", + "continent": "North America", + "name": "Cuba" + }, + { + "code": "cw", + "continent": "South America", + "name": "Curaçao" + }, + { + "code": "cy", + "continent": "Europe", + "name": "Cyprus" + }, + { + "code": "cz", + "continent": "Europe", + "name": "Czech Republic" + }, + { + "code": "ci", + "continent": "Africa", + "name": "Côte d'Ivoire" + }, + { + "code": "cd", + "continent": "Africa", + "name": "Democratic Republic of the Congo" + }, + { + "code": "dk", + "continent": "Europe", + "name": "Denmark" + }, + { + "code": "dg", + "name": "Diego Garcia" + }, + { + "code": "dj", + "continent": "Africa", + "name": "Djibouti" + }, + { + "code": "dm", + "continent": "North America", + "name": "Dominica" + }, + { + "code": "do", + "continent": "North America", + "name": "Dominican Republic" + }, + { + "code": "eac", + "name": "East African Community" + }, + { + "code": "ec", + "continent": "South America", + "name": "Ecuador" + }, + { + "code": "eg", + "continent": "Africa", + "name": "Egypt" + }, + { + "code": "sv", + "continent": "North America", + "name": "El Salvador" + }, + { + "code": "gb-eng", + "continent": "Europe", + "name": "England" + }, + { + "code": "gq", + "continent": "Africa", + "name": "Equatorial Guinea" + }, + { + "code": "er", + "continent": "Africa", + "name": "Eritrea" + }, + { + "code": "ee", + "continent": "Europe", + "name": "Estonia" + }, + { + "code": "sz", + "continent": "Africa", + "name": "Eswatini" + }, + { + "code": "et", + "continent": "Africa", + "name": "Ethiopia" + }, + { + "code": "eu", + "name": "Europe" + }, + { + "code": "fk", + "continent": "South America", + "name": "Falkland Islands" + }, + { + "code": "fo", + "continent": "Europe", + "name": "Faroe Islands" + }, + { + "code": "fm", + "continent": "Oceania", + "name": "Federated States of Micronesia" + }, + { + "code": "fj", + "continent": "Oceania", + "name": "Fiji" + }, + { + "code": "fi", + "continent": "Europe", + "name": "Finland" + }, + { + "code": "fr", + "continent": "Europe", + "name": "France" + }, + { + "code": "gf", + "continent": "South America", + "name": "French Guiana" + }, + { + "code": "pf", + "continent": "Oceania", + "name": "French Polynesia" + }, + { + "code": "tf", + "continent": "Africa", + "name": "French Southern Territories" + }, + { + "code": "ga", + "continent": "Africa", + "name": "Gabon" + }, + { + "code": "es-ga", + "name": "Galicia" + }, + { + "code": "gm", + "continent": "Africa", + "name": "Gambia" + }, + { + "code": "ge", + "continent": "Asia", + "name": "Georgia" + }, + { + "code": "de", + "continent": "Europe", + "name": "Germany" + }, + { + "code": "gh", + "continent": "Africa", + "name": "Ghana" + }, + { + "code": "gi", + "continent": "Europe", + "name": "Gibraltar" + }, + { + "code": "gr", + "continent": "Europe", + "name": "Greece" + }, + { + "code": "gl", + "continent": "North America", + "name": "Greenland" + }, + { + "code": "gd", + "continent": "North America", + "name": "Grenada" + }, + { + "code": "gp", + "continent": "North America", + "name": "Guadeloupe" + }, + { + "code": "gu", + "continent": "Oceania", + "name": "Guam" + }, + { + "code": "gt", + "continent": "North America", + "name": "Guatemala" + }, + { + "code": "gg", + "continent": "Europe", + "name": "Guernsey" + }, + { + "code": "gn", + "continent": "Africa", + "name": "Guinea" + }, + { + "code": "gw", + "continent": "Africa", + "name": "Guinea-Bissau" + }, + { + "code": "gy", + "continent": "South America", + "name": "Guyana" + }, + { + "code": "ht", + "continent": "North America", + "name": "Haiti" + }, + { + "code": "hm", + "name": "Heard Island and McDonald Islands" + }, + { + "code": "va", + "continent": "Europe", + "name": "Holy See" + }, + { + "code": "hn", + "continent": "North America", + "name": "Honduras" + }, + { + "code": "hk", + "continent": "Asia", + "name": "Hong Kong" + }, + { + "code": "hu", + "continent": "Europe", + "name": "Hungary" + }, + { + "code": "is", + "continent": "Europe", + "name": "Iceland" + }, + { + "code": "in", + "continent": "Asia", + "name": "India" + }, + { + "code": "id", + "continent": "Asia", + "name": "Indonesia" + }, + { + "code": "ir", + "continent": "Asia", + "name": "Iran" + }, + { + "code": "iq", + "continent": "Asia", + "name": "Iraq" + }, + { + "code": "ie", + "continent": "Europe", + "name": "Ireland" + }, + { + "code": "im", + "continent": "Europe", + "name": "Isle of Man" + }, + { + "code": "il", + "continent": "Asia", + "name": "Israel" + }, + { + "code": "it", + "continent": "Europe", + "name": "Italy" + }, + { + "code": "jm", + "continent": "North America", + "name": "Jamaica" + }, + { + "code": "jp", + "continent": "Asia", + "name": "Japan" + }, + { + "code": "je", + "continent": "Europe", + "name": "Jersey" + }, + { + "code": "jo", + "continent": "Asia", + "name": "Jordan" + }, + { + "code": "kz", + "continent": "Asia", + "name": "Kazakhstan" + }, + { + "code": "ke", + "continent": "Africa", + "name": "Kenya" + }, + { + "code": "ki", + "continent": "Oceania", + "name": "Kiribati" + }, + { + "code": "xk", + "continent": "Europe", + "name": "Kosovo" + }, + { + "code": "kw", + "continent": "Asia", + "name": "Kuwait" + }, + { + "code": "kg", + "continent": "Asia", + "name": "Kyrgyzstan" + }, + { + "code": "la", + "continent": "Asia", + "name": "Laos" + }, + { + "code": "lv", + "continent": "Europe", + "name": "Latvia" + }, + { + "code": "arab", + "name": "League of Arab States" + }, + { + "code": "lb", + "continent": "Asia", + "name": "Lebanon" + }, + { + "code": "ls", + "continent": "Africa", + "name": "Lesotho" + }, + { + "code": "lr", + "continent": "Africa", + "name": "Liberia" + }, + { + "code": "ly", + "continent": "Africa", + "name": "Libya" + }, + { + "code": "li", + "continent": "Europe", + "name": "Liechtenstein" + }, + { + "code": "lt", + "continent": "Europe", + "name": "Lithuania" + }, + { + "code": "lu", + "continent": "Europe", + "name": "Luxembourg" + }, + { + "code": "mo", + "continent": "Asia", + "name": "Macau" + }, + { + "code": "mg", + "continent": "Africa", + "name": "Madagascar" + }, + { + "code": "mw", + "continent": "Africa", + "name": "Malawi" + }, + { + "code": "my", + "continent": "Asia", + "name": "Malaysia" + }, + { + "code": "mv", + "continent": "Asia", + "name": "Maldives" + }, + { + "code": "ml", + "continent": "Africa", + "name": "Mali" + }, + { + "code": "mt", + "continent": "Europe", + "name": "Malta" + }, + { + "code": "mh", + "continent": "Oceania", + "name": "Marshall Islands" + }, + { + "code": "mq", + "continent": "North America", + "name": "Martinique" + }, + { + "code": "mr", + "continent": "Africa", + "name": "Mauritania" + }, + { + "code": "mu", + "continent": "Africa", + "name": "Mauritius" + }, + { + "code": "yt", + "continent": "Africa", + "name": "Mayotte" + }, + { + "code": "mx", + "continent": "North America", + "name": "Mexico" + }, + { + "code": "md", + "continent": "Europe", + "name": "Moldova" + }, + { + "code": "mc", + "continent": "Europe", + "name": "Monaco" + }, + { + "code": "mn", + "continent": "Asia", + "name": "Mongolia" + }, + { + "code": "me", + "continent": "Europe", + "name": "Montenegro" + }, + { + "code": "ms", + "continent": "North America", + "name": "Montserrat" + }, + { + "code": "ma", + "continent": "Africa", + "name": "Morocco" + }, + { + "code": "mz", + "continent": "Africa", + "name": "Mozambique" + }, + { + "code": "mm", + "continent": "Asia", + "name": "Myanmar" + }, + { + "code": "na", + "continent": "Africa", + "name": "Namibia" + }, + { + "code": "nr", + "continent": "Oceania", + "name": "Nauru" + }, + { + "code": "np", + "continent": "Asia", + "name": "Nepal" + }, + { + "code": "nl", + "continent": "Europe", + "name": "Netherlands" + }, + { + "code": "nc", + "continent": "Oceania", + "name": "New Caledonia" + }, + { + "code": "nz", + "continent": "Oceania", + "name": "New Zealand" + }, + { + "code": "ni", + "continent": "North America", + "name": "Nicaragua" + }, + { + "code": "ne", + "continent": "Africa", + "name": "Niger" + }, + { + "code": "ng", + "continent": "Africa", + "name": "Nigeria" + }, + { + "code": "nu", + "continent": "Oceania", + "name": "Niue" + }, + { + "code": "nf", + "continent": "Oceania", + "name": "Norfolk Island" + }, + { + "code": "kp", + "continent": "Asia", + "name": "North Korea" + }, + { + "code": "mk", + "continent": "Europe", + "name": "North Macedonia" + }, + { + "code": "gb-nir", + "continent": "Europe", + "name": "Northern Ireland" + }, + { + "code": "mp", + "continent": "Oceania", + "name": "Northern Mariana Islands" + }, + { + "code": "no", + "continent": "Europe", + "name": "Norway" + }, + { + "code": "om", + "continent": "Asia", + "name": "Oman" + }, + { + "code": "pc", + "name": "Pacific Community" + }, + { + "code": "pk", + "continent": "Asia", + "name": "Pakistan" + }, + { + "code": "pw", + "continent": "Oceania", + "name": "Palau" + }, + { + "code": "pa", + "continent": "North America", + "name": "Panama" + }, + { + "code": "pg", + "continent": "Oceania", + "name": "Papua New Guinea" + }, + { + "code": "py", + "continent": "South America", + "name": "Paraguay" + }, + { + "code": "pe", + "continent": "South America", + "name": "Peru" + }, + { + "code": "ph", + "continent": "Asia", + "name": "Philippines" + }, + { + "code": "pn", + "continent": "Oceania", + "name": "Pitcairn" + }, + { + "code": "pl", + "continent": "Europe", + "name": "Poland" + }, + { + "code": "pt", + "continent": "Europe", + "name": "Portugal" + }, + { + "code": "pr", + "continent": "North America", + "name": "Puerto Rico" + }, + { + "code": "qa", + "continent": "Asia", + "name": "Qatar" + }, + { + "code": "cg", + "continent": "Africa", + "name": "Republic of the Congo" + }, + { + "code": "ro", + "continent": "Europe", + "name": "Romania" + }, + { + "code": "ru", + "continent": "Europe", + "name": "Russia" + }, + { + "code": "rw", + "continent": "Africa", + "name": "Rwanda" + }, + { + "code": "re", + "continent": "Africa", + "name": "Réunion" + }, + { + "code": "bl", + "continent": "North America", + "name": "Saint Barthélemy" + }, + { + "code": "sh-hl", + "continent": "Africa", + "name": "Saint Helena" + }, + { + "code": "sh", + "continent": "Africa", + "name": "Saint Helena, Ascension and Tristan da Cunha" + }, + { + "code": "kn", + "continent": "North America", + "name": "Saint Kitts and Nevis" + }, + { + "code": "lc", + "continent": "North America", + "name": "Saint Lucia" + }, + { + "code": "mf", + "continent": "North America", + "name": "Saint Martin" + }, + { + "code": "pm", + "continent": "North America", + "name": "Saint Pierre and Miquelon" + }, + { + "code": "vc", + "continent": "North America", + "name": "Saint Vincent and the Grenadines" + }, + { + "code": "ws", + "continent": "Oceania", + "name": "Samoa" + }, + { + "code": "sm", + "continent": "Europe", + "name": "San Marino" + }, + { + "code": "st", + "continent": "Africa", + "name": "Sao Tome and Principe" + }, + { + "code": "sa", + "continent": "Asia", + "name": "Saudi Arabia" + }, + { + "code": "gb-sct", + "continent": "Europe", + "name": "Scotland" + }, + { + "code": "sn", + "continent": "Africa", + "name": "Senegal" + }, + { + "code": "rs", + "continent": "Europe", + "name": "Serbia" + }, + { + "code": "sc", + "continent": "Africa", + "name": "Seychelles" + }, + { + "code": "sl", + "continent": "Africa", + "name": "Sierra Leone" + }, + { + "code": "sg", + "continent": "Asia", + "name": "Singapore" + }, + { + "code": "sx", + "continent": "North America", + "name": "Sint Maarten" + }, + { + "code": "sk", + "continent": "Europe", + "name": "Slovakia" + }, + { + "code": "si", + "continent": "Europe", + "name": "Slovenia" + }, + { + "code": "sb", + "continent": "Oceania", + "name": "Solomon Islands" + }, + { + "code": "so", + "continent": "Africa", + "name": "Somalia" + }, + { + "code": "za", + "continent": "Africa", + "name": "South Africa" + }, + { + "code": "gs", + "continent": "Antarctica", + "name": "South Georgia and the South Sandwich Islands" + }, + { + "code": "kr", + "continent": "Asia", + "name": "South Korea" + }, + { + "code": "ss", + "continent": "Africa", + "name": "South Sudan" + }, + { + "code": "es", + "continent": "Europe", + "name": "Spain" + }, + { + "code": "lk", + "continent": "Asia", + "name": "Sri Lanka" + }, + { + "code": "ps", + "continent": "Asia", + "name": "State of Palestine" + }, + { + "code": "sd", + "continent": "Africa", + "name": "Sudan" + }, + { + "code": "sr", + "continent": "South America", + "name": "Suriname" + }, + { + "code": "sj", + "continent": "Europe", + "name": "Svalbard and Jan Mayen" + }, + { + "code": "se", + "continent": "Europe", + "name": "Sweden" + }, + { + "code": "ch", + "continent": "Europe", + "name": "Switzerland" + }, + { + "code": "sy", + "continent": "Asia", + "name": "Syria" + }, + { + "code": "tw", + "continent": "Asia", + "name": "Taiwan" + }, + { + "code": "tj", + "continent": "Asia", + "name": "Tajikistan" + }, + { + "code": "tz", + "continent": "Africa", + "name": "Tanzania" + }, + { + "code": "th", + "continent": "Asia", + "name": "Thailand" + }, + { + "code": "tl", + "continent": "Asia", + "name": "Timor-Leste" + }, + { + "code": "tg", + "continent": "Africa", + "name": "Togo" + }, + { + "code": "tk", + "continent": "Oceania", + "name": "Tokelau" + }, + { + "code": "to", + "continent": "Oceania", + "name": "Tonga" + }, + { + "code": "tt", + "continent": "South America", + "name": "Trinidad and Tobago" + }, + { + "code": "sh-ta", + "continent": "Africa", + "name": "Tristan da Cunha" + }, + { + "code": "tn", + "continent": "Africa", + "name": "Tunisia" + }, + { + "code": "tm", + "continent": "Asia", + "name": "Turkmenistan" + }, + { + "code": "tc", + "continent": "North America", + "name": "Turks and Caicos Islands" + }, + { + "code": "tv", + "continent": "Oceania", + "name": "Tuvalu" + }, + { + "code": "tr", + "continent": "Asia", + "name": "Türkiye" + }, + { + "code": "ug", + "continent": "Africa", + "name": "Uganda" + }, + { + "code": "ua", + "continent": "Europe", + "name": "Ukraine" + }, + { + "code": "ae", + "continent": "Asia", + "name": "United Arab Emirates" + }, + { + "code": "gb", + "continent": "Europe", + "name": "United Kingdom" + }, + { + "code": "un", + "name": "United Nations" + }, + { + "code": "um", + "continent": "North America", + "name": "United States Minor Outlying Islands" + }, + { + "code": "us", + "continent": "North America", + "name": "United States of America" + }, + { + "code": "uy", + "continent": "South America", + "name": "Uruguay" + }, + { + "code": "uz", + "continent": "Asia", + "name": "Uzbekistan" + }, + { + "code": "vu", + "continent": "Oceania", + "name": "Vanuatu" + }, + { + "code": "ve", + "continent": "South America", + "name": "Venezuela" + }, + { + "code": "vn", + "continent": "Asia", + "name": "Vietnam" + }, + { + "code": "vg", + "continent": "North America", + "name": "Virgin Islands (British)" + }, + { + "code": "vi", + "continent": "North America", + "name": "Virgin Islands (U.S.)" + }, + { + "code": "gb-wls", + "continent": "Europe", + "name": "Wales" + }, + { + "code": "wf", + "continent": "Oceania", + "name": "Wallis and Futuna" + }, + { + "code": "eh", + "continent": "Africa", + "name": "Western Sahara" + }, + { + "code": "ye", + "continent": "Asia", + "name": "Yemen" + }, + { + "code": "zm", + "continent": "Africa", + "name": "Zambia" + }, + { + "code": "zw", + "continent": "Africa", + "name": "Zimbabwe" + } ] diff --git a/src/client/graphics/GameRenderer.ts b/src/client/graphics/GameRenderer.ts index 57b5dd0ac..b8e489598 100644 --- a/src/client/graphics/GameRenderer.ts +++ b/src/client/graphics/GameRenderer.ts @@ -29,7 +29,7 @@ export function createRenderer( canvas: HTMLCanvasElement, game: GameView, eventBus: EventBus, - clientID: ClientID + clientID: ClientID, ): GameRenderer { const transformHandler = new TransformHandler(game, eventBus, canvas); @@ -65,7 +65,7 @@ export function createRenderer( controlPanel.game = game; const eventsDisplay = document.querySelector( - "events-display" + "events-display", ) as EventsDisplay; if (!(eventsDisplay instanceof EventsDisplay)) { consolex.error("events display not found"); @@ -75,7 +75,7 @@ export function createRenderer( eventsDisplay.clientID = clientID; const playerInfo = document.querySelector( - "player-info-overlay" + "player-info-overlay", ) as PlayerInfoOverlay; if (!(playerInfo instanceof PlayerInfoOverlay)) { consolex.error("player info overlay not found"); @@ -129,7 +129,7 @@ export function createRenderer( buildMenu, uiState, playerInfo, - playerPanel + playerPanel, ), new SpawnTimer(game, transformHandler), leaderboard, @@ -147,7 +147,7 @@ export function createRenderer( canvas, transformHandler, uiState, - layers + layers, ); } @@ -160,7 +160,7 @@ export class GameRenderer { private canvas: HTMLCanvasElement, public transformHandler: TransformHandler, public uiState: UIState, - private layers: Layer[] + private layers: Layer[], ) { this.context = canvas.getContext("2d"); } @@ -183,7 +183,7 @@ export class GameRenderer { this.transformHandler = new TransformHandler( this.game, this.eventBus, - this.canvas + this.canvas, ); requestAnimationFrame(() => this.renderGame()); @@ -229,7 +229,7 @@ export class GameRenderer { const duration = performance.now() - start; if (duration > 50) { console.warn( - `tick ${this.game.ticks()} took ${duration}ms to render frame` + `tick ${this.game.ticks()} took ${duration}ms to render frame`, ); } } diff --git a/src/client/graphics/layers/BuildMenu.ts b/src/client/graphics/layers/BuildMenu.ts index 8a6e69c2a..765d2def4 100644 --- a/src/client/graphics/layers/BuildMenu.ts +++ b/src/client/graphics/layers/BuildMenu.ts @@ -200,7 +200,7 @@ export class BuildMenu extends LitElement { public onBuildSelected = (item: BuildItemDisplay) => { this.eventBus.emit( - new BuildUnitIntentEvent(item.unitType, this.clickedCell) + new BuildUnitIntentEvent(item.unitType, this.clickedCell), ); this.hideMenu(); }; @@ -235,7 +235,7 @@ export class BuildMenu extends LitElement { ? this.game .unitInfo(item.unitType) .cost(this.myPlayer) - : 0 + : 0, )} - ` + `, )} - ` + `, )} `; diff --git a/src/client/graphics/layers/EmojiTable.ts b/src/client/graphics/layers/EmojiTable.ts index 89ecd4863..1a7d5978e 100644 --- a/src/client/graphics/layers/EmojiTable.ts +++ b/src/client/graphics/layers/EmojiTable.ts @@ -10,7 +10,7 @@ const emojiTable: string[][] = [ ["😎", "❤️", "💰", "🤝", "🖕"], ["💥", "🆘", "🕊️", "➡️", "⬅️"], ["↙️", "↖️", "↗️", "⬆️", "↘️"], - ["⬇️", "❓", "⏳", "☢️", "⚠️"] + ["⬇️", "❓", "⏳", "☢️", "⚠️"], ]; @customElement("emoji-table") @@ -110,10 +110,10 @@ export class EmojiTable extends LitElement { > ${emoji} - ` + `, )} - ` + `, )} `; diff --git a/src/client/graphics/layers/EventsDisplay.ts b/src/client/graphics/layers/EventsDisplay.ts index b49b22783..c6646edea 100644 --- a/src/client/graphics/layers/EventsDisplay.ts +++ b/src/client/graphics/layers/EventsDisplay.ts @@ -150,10 +150,10 @@ export class EventsDisplay extends LitElement implements Layer { } const requestor = this.game.playerBySmallID( - update.requestorID + update.requestorID, ) as PlayerView; const recipient = this.game.playerBySmallID( - update.recipientID + update.recipientID, ) as PlayerView; this.addEvent({ @@ -164,7 +164,7 @@ export class EventsDisplay extends LitElement implements Layer { className: "btn", action: () => this.eventBus.emit( - new SendAllianceReplyIntentEvent(requestor, recipient, true) + new SendAllianceReplyIntentEvent(requestor, recipient, true), ), }, { @@ -172,7 +172,7 @@ export class EventsDisplay extends LitElement implements Layer { className: "btn-info", action: () => this.eventBus.emit( - new SendAllianceReplyIntentEvent(requestor, recipient, false) + new SendAllianceReplyIntentEvent(requestor, recipient, false), ), }, ], @@ -181,7 +181,7 @@ export class EventsDisplay extends LitElement implements Layer { createdAt: this.game.ticks(), onDelete: () => this.eventBus.emit( - new SendAllianceReplyIntentEvent(requestor, recipient, false) + new SendAllianceReplyIntentEvent(requestor, recipient, false), ), }); } @@ -193,7 +193,7 @@ export class EventsDisplay extends LitElement implements Layer { } const recipient = this.game.playerBySmallID( - update.request.recipientID + update.request.recipientID, ) as PlayerView; this.addEvent({ @@ -238,8 +238,8 @@ export class EventsDisplay extends LitElement implements Layer { update.player1ID === myPlayer.smallID() ? update.player2ID : update.player2ID === myPlayer.smallID() - ? update.player1ID - : null; + ? update.player1ID + : null; const other = this.game.playerBySmallID(otherID) as PlayerView; if (!other || !myPlayer.isAlive() || !other.isAlive()) return; @@ -275,7 +275,7 @@ export class EventsDisplay extends LitElement implements Layer { ? AllPlayers : this.game.playerBySmallID(update.emoji.recipientID); const sender = this.game.playerBySmallID( - update.emoji.senderID + update.emoji.senderID, ) as PlayerView; if (recipient == myPlayer) { @@ -333,11 +333,11 @@ export class EventsDisplay extends LitElement implements Layer { ${renderTroops(attack.troops)} ${( this.game.playerBySmallID( - attack.attackerID + attack.attackerID, ) as PlayerView )?.name()} - ` + `, )} @@ -355,7 +355,7 @@ export class EventsDisplay extends LitElement implements Layer { this.game.playerBySmallID(attack.targetID) as PlayerView )?.name()} - ` + `, )} @@ -385,7 +385,7 @@ export class EventsDisplay extends LitElement implements Layer { (event, index) => html` @@ -410,14 +410,14 @@ export class EventsDisplay extends LitElement implements Layer { > ${btn.text} - ` + `, )} ` : ""} - ` + `, )} ${this.renderAttacks()} diff --git a/src/client/graphics/layers/Leaderboard.ts b/src/client/graphics/layers/Leaderboard.ts index 6a500afcf..4fe61133e 100644 --- a/src/client/graphics/layers/Leaderboard.ts +++ b/src/client/graphics/layers/Leaderboard.ts @@ -80,7 +80,7 @@ export class Leaderboard extends LitElement implements Layer { name: myPlayer.displayName(), position: place, score: formatPercentage( - myPlayer.numTilesOwned() / this.game.numLandTiles() + myPlayer.numTilesOwned() / this.game.numLandTiles(), ), gold: renderNumber(myPlayer.gold()), isMyPlayer: true, @@ -205,7 +205,7 @@ export class Leaderboard extends LitElement implements Layer { ${player.score} ${player.gold} - ` + `, )} diff --git a/src/client/graphics/layers/NameLayer.ts b/src/client/graphics/layers/NameLayer.ts index 542a01390..3a4f78d88 100644 --- a/src/client/graphics/layers/NameLayer.ts +++ b/src/client/graphics/layers/NameLayer.ts @@ -26,7 +26,7 @@ class RenderInfo { public lastRenderCalc: number, public location: Cell, public fontSize: number, - public element: HTMLElement + public element: HTMLElement, ) {} } @@ -50,7 +50,7 @@ export class NameLayer implements Layer { private game: GameView, private theme: Theme, private transformHandler: TransformHandler, - private clientID: ClientID + private clientID: ClientID, ) { this.traitorIconImage = new Image(); this.traitorIconImage.src = traitorIcon; @@ -101,7 +101,13 @@ export class NameLayer implements Layer { if (!this.seenPlayers.has(player)) { this.seenPlayers.add(player); this.renders.push( - new RenderInfo(player, 0, null, 0, this.createPlayerElement(player)) + new RenderInfo( + player, + 0, + null, + 0, + this.createPlayerElement(player), + ), ); } } @@ -110,11 +116,11 @@ export class NameLayer implements Layer { public renderLayer(mainContex: CanvasRenderingContext2D) { const screenPosOld = this.transformHandler.worldToScreenCoordinates( - new Cell(0, 0) + new Cell(0, 0), ); const screenPos = new Cell( screenPosOld.x - window.innerWidth / 2, - screenPosOld.y - window.innerHeight / 2 + screenPosOld.y - window.innerHeight / 2, ); this.container.style.transform = `translate(${screenPos.x}px, ${screenPos.y}px) scale(${this.transformHandler.scale})`; @@ -131,7 +137,7 @@ export class NameLayer implements Layer { 0, 0, mainContex.canvas.width, - mainContex.canvas.height + mainContex.canvas.height, ); } @@ -205,7 +211,7 @@ export class NameLayer implements Layer { const oldLocation = render.location; render.location = new Cell( render.player.nameLocation().x, - render.player.nameLocation().y + render.player.nameLocation().y, ); // Calculate base size and scale @@ -229,10 +235,10 @@ export class NameLayer implements Layer { // Update text sizes const nameDiv = render.element.querySelector( - ".player-name" + ".player-name", ) as HTMLDivElement; const troopsDiv = render.element.querySelector( - ".player-troops" + ".player-troops", ) as HTMLDivElement; nameDiv.style.fontSize = `${render.fontSize}px`; troopsDiv.style.fontSize = `${render.fontSize}px`; @@ -240,7 +246,7 @@ export class NameLayer implements Layer { // Handle icons const iconsDiv = render.element.querySelector( - ".player-icons" + ".player-icons", ) as HTMLDivElement; const iconSize = Math.min(render.fontSize * 1.5, 48); const myPlayer = this.getPlayer(); @@ -250,7 +256,7 @@ export class NameLayer implements Layer { if (render.player === this.firstPlace) { if (!existingCrown) { iconsDiv.appendChild( - this.createIconElement(this.crownIconImage.src, iconSize, "crown") + this.createIconElement(this.crownIconImage.src, iconSize, "crown"), ); } } else if (existingCrown) { @@ -262,7 +268,11 @@ export class NameLayer implements Layer { if (render.player.isTraitor()) { if (!existingTraitor) { iconsDiv.appendChild( - this.createIconElement(this.traitorIconImage.src, iconSize, "traitor") + this.createIconElement( + this.traitorIconImage.src, + iconSize, + "traitor", + ), ); } } else if (existingTraitor) { @@ -277,8 +287,8 @@ export class NameLayer implements Layer { this.createIconElement( this.allianceIconImage.src, iconSize, - "alliance" - ) + "alliance", + ), ); } } else if (existingAlliance) { @@ -293,7 +303,7 @@ export class NameLayer implements Layer { ) { if (!existingTarget) { iconsDiv.appendChild( - this.createIconElement(this.targetIconImage.src, iconSize, "target") + this.createIconElement(this.targetIconImage.src, iconSize, "target"), ); } } else if (existingTarget) { @@ -307,7 +317,7 @@ export class NameLayer implements Layer { .filter( (emoji) => emoji.recipientID == AllPlayers || - emoji.recipientID == myPlayer?.smallID() + emoji.recipientID == myPlayer?.smallID(), ); if (emojis.length > 0) { @@ -340,7 +350,7 @@ export class NameLayer implements Layer { private createIconElement( src: string, size: number, - id: string + id: string, ): HTMLImageElement { const icon = document.createElement("img"); icon.src = src; diff --git a/src/client/graphics/layers/PlayerInfoOverlay.ts b/src/client/graphics/layers/PlayerInfoOverlay.ts index 164a9370b..8ba68024f 100644 --- a/src/client/graphics/layers/PlayerInfoOverlay.ts +++ b/src/client/graphics/layers/PlayerInfoOverlay.ts @@ -22,7 +22,7 @@ import { renderNumber, renderTroops } from "../../Utils"; function euclideanDistWorld( coord: { x: number; y: number }, tileRef: TileRef, - game: GameView + game: GameView, ): number { const x = game.x(tileRef); const y = game.y(tileRef); @@ -71,7 +71,7 @@ export class PlayerInfoOverlay extends LitElement implements Layer { init() { this.eventBus.on(MouseMoveEvent, (e: MouseMoveEvent) => - this.onMouseEvent(e) + this.onMouseEvent(e), ); this._isActive = true; } diff --git a/src/client/graphics/layers/PlayerPanel.ts b/src/client/graphics/layers/PlayerPanel.ts index 4b6433ec0..c34ee53f4 100644 --- a/src/client/graphics/layers/PlayerPanel.ts +++ b/src/client/graphics/layers/PlayerPanel.ts @@ -53,7 +53,7 @@ export class PlayerPanel extends LitElement implements Layer { private handleAllianceClick( e: Event, myPlayer: PlayerView, - other: PlayerView + other: PlayerView, ) { e.stopPropagation(); this.eventBus.emit(new SendAllianceRequestIntentEvent(myPlayer, other)); @@ -63,7 +63,7 @@ export class PlayerPanel extends LitElement implements Layer { private handleBreakAllianceClick( e: Event, myPlayer: PlayerView, - other: PlayerView + other: PlayerView, ) { e.stopPropagation(); this.eventBus.emit(new SendBreakAllianceIntentEvent(myPlayer, other)); diff --git a/src/client/graphics/layers/RadialMenu.ts b/src/client/graphics/layers/RadialMenu.ts index 59a4e9507..fc768c354 100644 --- a/src/client/graphics/layers/RadialMenu.ts +++ b/src/client/graphics/layers/RadialMenu.ts @@ -99,7 +99,7 @@ export class RadialMenu implements Layer { private buildMenu: BuildMenu, private uiState: UIState, private playerInfoOverlay: PlayerInfoOverlay, - private playerPanel: PlayerPanel + private playerPanel: PlayerPanel, ) {} init() { @@ -108,7 +108,7 @@ export class RadialMenu implements Layer { this.eventBus.on(ShowBuildMenuEvent, (e) => { const clickedCell = this.transformHandler.screenToWorldCoordinates( e.x, - e.y + e.y, ); if (clickedCell == null) { return; @@ -144,7 +144,7 @@ export class RadialMenu implements Layer { .append("g") .attr( "transform", - `translate(${this.menuSize / 2},${this.menuSize / 2})` + `translate(${this.menuSize / 2},${this.menuSize / 2})`, ); const pie = d3 @@ -169,7 +169,7 @@ export class RadialMenu implements Layer { .append("path") .attr("d", arc) .attr("fill", (d) => - d.data.disabled ? this.disabledColor : d.data.color + d.data.disabled ? this.disabledColor : d.data.color, ) .attr("stroke", "#ffffff") .attr("stroke-width", "2") @@ -294,7 +294,7 @@ export class RadialMenu implements Layer { this.clickedCell = this.transformHandler.screenToWorldCoordinates( event.x, - event.y + event.y, ); if (!this.g.isValidCoord(this.clickedCell.x, this.clickedCell.y)) { return; @@ -323,7 +323,7 @@ export class RadialMenu implements Layer { private handlePlayerActions( myPlayer: PlayerView, actions: PlayerActions, - tile: TileRef + tile: TileRef, ) { this.activateMenuElement(Slot.Build, "#ebe250", buildIcon, () => { this.buildMenu.showMenu(myPlayer, this.clickedCell); @@ -341,8 +341,8 @@ export class RadialMenu implements Layer { new SendBoatAttackIntentEvent( this.g.owner(tile).id(), this.clickedCell, - this.uiState.attackRatio * myPlayer.troops() - ) + this.uiState.attackRatio * myPlayer.troops(), + ), ); }); } @@ -394,8 +394,8 @@ export class RadialMenu implements Layer { this.eventBus.emit( new SendAttackIntentEvent( this.g.owner(clicked).id(), - this.uiState.attackRatio * myPlayer.troops() - ) + this.uiState.attackRatio * myPlayer.troops(), + ), ); } } @@ -406,7 +406,7 @@ export class RadialMenu implements Layer { slot: Slot, color: string, icon: string, - action: () => void + action: () => void, ) { const menuItem = this.menuItems.get(slot); menuItem.action = action; diff --git a/src/client/graphics/layers/StructureLayer.ts b/src/client/graphics/layers/StructureLayer.ts index ff7b1be73..1d6ee47df 100644 --- a/src/client/graphics/layers/StructureLayer.ts +++ b/src/client/graphics/layers/StructureLayer.ts @@ -50,7 +50,10 @@ export class StructureLayer implements Layer { }, }; - constructor(private game: GameView, private eventBus: EventBus) { + constructor( + private game: GameView, + private eventBus: EventBus, + ) { this.theme = game.config().theme(); this.loadIconData(); } @@ -72,11 +75,11 @@ export class StructureLayer implements Layer { 0, 0, tempCanvas.width, - tempCanvas.height + tempCanvas.height, ); this.unitIcons.set(unitType, iconData); console.log( - `icond data width height: ${iconData.width}, ${iconData.height}` + `icond data width height: ${iconData.width}, ${iconData.height}`, ); }; }); @@ -89,9 +92,9 @@ export class StructureLayer implements Layer { tick() { this.game .updatesSinceLastTick() - [GameUpdateType.Unit].forEach((u) => - this.handleUnitRendering(this.game.unit(u.id)) - ); + [ + GameUpdateType.Unit + ].forEach((u) => this.handleUnitRendering(this.game.unit(u.id))); } init() { @@ -113,7 +116,7 @@ export class StructureLayer implements Layer { -this.game.width() / 2, -this.game.height() / 2, this.game.width(), - this.game.height() + this.game.height(), ); } @@ -133,7 +136,7 @@ export class StructureLayer implements Layer { // Clear previous rendering for (const tile of this.game.bfs( unit.tile(), - euclDistFN(unit.tile(), config.borderRadius) + euclDistFN(unit.tile(), config.borderRadius), )) { this.clearCell(new Cell(this.game.x(tile), this.game.y(tile))); } @@ -145,27 +148,27 @@ export class StructureLayer implements Layer { // Draw border and territory for (const tile of this.game.bfs( unit.tile(), - euclDistFN(unit.tile(), config.borderRadius) + euclDistFN(unit.tile(), config.borderRadius), )) { this.paintCell( new Cell(this.game.x(tile), this.game.y(tile)), unit.type() == UnitType.Construction ? underConstructionColor : this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } for (const tile of this.game.bfs( unit.tile(), - euclDistFN(unit.tile(), config.territoryRadius) + euclDistFN(unit.tile(), config.territoryRadius), )) { this.paintCell( new Cell(this.game.x(tile), this.game.y(tile)), unit.type() == UnitType.Construction ? underConstructionColor : this.theme.territoryColor(unit.owner().info()), - 130 + 130, ); } @@ -181,7 +184,7 @@ export class StructureLayer implements Layer { startY: number, width: number, height: number, - unit: UnitView + unit: UnitView, ) { let color = this.theme.borderColor(unit.owner().info()); if (unit.type() == UnitType.Construction) { diff --git a/src/client/graphics/layers/TerritoryLayer.ts b/src/client/graphics/layers/TerritoryLayer.ts index d22698b64..68eea6138 100644 --- a/src/client/graphics/layers/TerritoryLayer.ts +++ b/src/client/graphics/layers/TerritoryLayer.ts @@ -50,7 +50,10 @@ export class TerritoryLayer implements Layer { private refreshRate = 50; private lastRefresh = 0; - constructor(private game: GameView, private eventBus: EventBus) { + constructor( + private game: GameView, + private eventBus: EventBus, + ) { this.theme = game.config().theme(); } @@ -67,7 +70,7 @@ export class TerritoryLayer implements Layer { this.game .bfs( tile, - manhattanDistFN(tile, this.game.config().defensePostRange()) + manhattanDistFN(tile, this.game.config().defensePostRange()), ) .forEach((t) => { if ( @@ -91,7 +94,7 @@ export class TerritoryLayer implements Layer { 0, 0, this.game.width(), - this.game.height() + this.game.height(), ); const humans = this.game .playerViews() @@ -111,7 +114,7 @@ export class TerritoryLayer implements Layer { this.paintHighlightCell( new Cell(this.game.x(tile), this.game.y(tile)), this.theme.spawnHighlightColor(), - 255 + 255, ); } } @@ -138,7 +141,7 @@ export class TerritoryLayer implements Layer { 0, 0, this.game.width(), - this.game.height() + this.game.height(), ); this.initImageData(); this.canvas.width = this.game.width(); @@ -185,7 +188,7 @@ export class TerritoryLayer implements Layer { -this.game.width() / 2, -this.game.height() / 2, this.game.width(), - this.game.height() + this.game.height(), ); if (this.game.inSpawnPhase()) { context.drawImage( @@ -193,7 +196,7 @@ export class TerritoryLayer implements Layer { -this.game.width() / 2, -this.game.height() / 2, this.game.width(), - this.game.height() + this.game.height(), ); } } @@ -224,7 +227,7 @@ export class TerritoryLayer implements Layer { this.game.x(tile), this.game.y(tile), this.theme.falloutColor(), - 150 + 150, ); return; } @@ -241,14 +244,14 @@ export class TerritoryLayer implements Layer { this.game.x(tile), this.game.y(tile), this.theme.defendedBorderColor(owner.info()), - 255 + 255, ); } else { this.paintCell( this.game.x(tile), this.game.y(tile), this.theme.borderColor(owner.info()), - 255 + 255, ); } } else { @@ -256,7 +259,7 @@ export class TerritoryLayer implements Layer { this.game.x(tile), this.game.y(tile), this.theme.territoryColor(owner.info()), - 150 + 150, ); } } diff --git a/src/client/graphics/layers/UnitLayer.ts b/src/client/graphics/layers/UnitLayer.ts index b6eef957d..3373edb61 100644 --- a/src/client/graphics/layers/UnitLayer.ts +++ b/src/client/graphics/layers/UnitLayer.ts @@ -36,7 +36,7 @@ export class UnitLayer implements Layer { constructor( private game: GameView, private eventBus: EventBus, - private clientID: ClientID + private clientID: ClientID, ) { this.theme = game.config().theme(); } @@ -65,7 +65,7 @@ export class UnitLayer implements Layer { -this.game.width() / 2, -this.game.height() / 2, this.game.width(), - this.game.height() + this.game.height(), ); } @@ -131,7 +131,7 @@ export class UnitLayer implements Layer { // Clear previous area for (const t of this.game.bfs( unit.lastTile(), - euclDistFN(unit.lastTile(), 6) + euclDistFN(unit.lastTile(), 6), )) { this.clearCell(this.game.x(t), this.game.y(t)); } @@ -147,21 +147,21 @@ export class UnitLayer implements Layer { this.game.y(t), rel, this.theme.territoryColor(unit.owner().info()), - 255 + 255, ); } // Paint border for (const t of this.game.bfs( unit.tile(), - manhattanDistFN(unit.tile(), 4) + manhattanDistFN(unit.tile(), 4), )) { this.paintCell( this.game.x(t), this.game.y(t), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } @@ -172,7 +172,7 @@ export class UnitLayer implements Layer { this.game.y(t), rel, this.theme.territoryColor(unit.owner().info()), - 255 + 255, ); } } @@ -198,14 +198,14 @@ export class UnitLayer implements Layer { this.game.y(unit.tile()), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); this.paintCell( this.game.x(unit.lastTile()), this.game.y(unit.lastTile()), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } @@ -215,7 +215,7 @@ export class UnitLayer implements Layer { // Clear previous area for (const t of this.game.bfs( unit.lastTile(), - euclDistFN(unit.lastTile(), 2) + euclDistFN(unit.lastTile(), 2), )) { this.clearCell(this.game.x(t), this.game.y(t)); } @@ -228,7 +228,7 @@ export class UnitLayer implements Layer { this.game.y(t), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } } @@ -246,7 +246,7 @@ export class UnitLayer implements Layer { this.game.y(unit.tile()), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } } @@ -257,7 +257,7 @@ export class UnitLayer implements Layer { // Clear previous area for (const t of this.game.bfs( unit.lastTile(), - euclDistFN(unit.lastTile(), 3) + euclDistFN(unit.lastTile(), 3), )) { this.clearCell(this.game.x(t), this.game.y(t)); } @@ -266,28 +266,28 @@ export class UnitLayer implements Layer { // Paint territory for (const t of this.game.bfs( unit.tile(), - manhattanDistFN(unit.tile(), 2) + manhattanDistFN(unit.tile(), 2), )) { this.paintCell( this.game.x(t), this.game.y(t), rel, this.theme.territoryColor(unit.owner().info()), - 255 + 255, ); } // Paint border for (const t of this.game.bfs( unit.tile(), - manhattanDistFN(unit.tile(), 1) + manhattanDistFN(unit.tile(), 1), )) { this.paintCell( this.game.x(t), this.game.y(t), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } } @@ -305,7 +305,7 @@ export class UnitLayer implements Layer { // Clear previous area for (const t of this.game.bfs( unit.lastTile(), - manhattanDistFN(unit.lastTile(), 3) + manhattanDistFN(unit.lastTile(), 3), )) { this.clearCell(this.game.x(t), this.game.y(t)); } @@ -318,35 +318,35 @@ export class UnitLayer implements Layer { this.game.y(t), rel, this.theme.territoryColor(unit.owner().info()), - 150 + 150, ); } // Paint border for (const t of this.game.bfs( unit.tile(), - manhattanDistFN(unit.tile(), 2) + manhattanDistFN(unit.tile(), 2), )) { this.paintCell( this.game.x(t), this.game.y(t), rel, this.theme.borderColor(unit.owner().info()), - 255 + 255, ); } // Paint territory for (const t of this.game.bfs( unit.tile(), - manhattanDistFN(unit.tile(), 1) + manhattanDistFN(unit.tile(), 1), )) { this.paintCell( this.game.x(t), this.game.y(t), rel, this.theme.territoryColor(unit.owner().info()), - 255 + 255, ); } } else { @@ -362,7 +362,7 @@ export class UnitLayer implements Layer { y: number, relationship: Relationship, color: Colord, - alpha: number + alpha: number, ) { this.clearCell(x, y); if (this.alternateView) { diff --git a/src/core/GameRunner.ts b/src/core/GameRunner.ts index 38bbaa244..8a95ee462 100644 --- a/src/core/GameRunner.ts +++ b/src/core/GameRunner.ts @@ -29,7 +29,7 @@ export async function createGameRunner( gameID: string, gameConfig: GameConfig, clientID: ClientID, - callBack: (gu: GameUpdateViewData) => void + callBack: (gu: GameUpdateViewData) => void, ): Promise { const config = getConfig(gameConfig); const gameMap = await loadGameMap(gameConfig.gameMap); @@ -37,9 +37,13 @@ export async function createGameRunner( gameMap.gameMap, gameMap.miniGameMap, gameMap.nationMap, - config + config, + ); + const gr = new GameRunner( + game as Game, + new Executor(game, gameID, clientID), + callBack, ); - const gr = new GameRunner(game as Game, new Executor(game, gameID, clientID), callBack); gr.init(); return gr; } @@ -54,13 +58,13 @@ export class GameRunner { constructor( public game: Game, private execManager: Executor, - private callBack: (gu: GameUpdateViewData | ErrorUpdate) => void + private callBack: (gu: GameUpdateViewData | ErrorUpdate) => void, ) {} init() { if (this.game.config().spawnBots()) { this.game.addExecution( - ...this.execManager.spawnBots(this.game.config().numBots()) + ...this.execManager.spawnBots(this.game.config().numBots()), ); } if (this.game.config().spawnNPCs()) { @@ -83,7 +87,7 @@ export class GameRunner { this.isExecuting = true; this.game.addExecution( - ...this.execManager.createExecs(this.turns[this.currTurn]) + ...this.execManager.createExecs(this.turns[this.currTurn]), ); this.currTurn++; @@ -107,10 +111,10 @@ export class GameRunner { .players() .filter( (p) => - p.type() == PlayerType.Human || p.type() == PlayerType.FakeHuman + p.type() == PlayerType.Human || p.type() == PlayerType.FakeHuman, ) .forEach( - (p) => (this.playerViewData[p.id()] = placeName(this.game, p)) + (p) => (this.playerViewData[p.id()] = placeName(this.game, p)), ); } @@ -136,7 +140,7 @@ export class GameRunner { public playerActions( playerID: PlayerID, x: number, - y: number + y: number, ): PlayerActions { const player = this.game.player(playerID); const tile = this.game.ref(x, y); @@ -144,7 +148,7 @@ export class GameRunner { canBoat: player.canBoat(tile), canAttack: player.canAttack(tile), buildableUnits: Object.values(UnitType).filter( - (ut) => player.canBuild(ut, tile) != false + (ut) => player.canBuild(ut, tile) != false, ), canSendEmojiAllPlayers: player.canSendEmoji(AllPlayers), } as PlayerActions; diff --git a/src/core/Schemas.ts b/src/core/Schemas.ts index 9bfae45f5..6ebcc2d7d 100644 --- a/src/core/Schemas.ts +++ b/src/core/Schemas.ts @@ -101,7 +101,9 @@ const SafeString = z .string() // Remove common dangerous characters and patterns // The weird \u stuff is to allow emojis - .regex(/^[a-zA-Z0-9\s.,!?@#$%&*()-_+=\[\]{}|;:"'\/\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]]+$/) + .regex( + /^[a-zA-Z0-9\s.,!?@#$%&*()-_+=\[\]{}|;:"'\/\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff]]+$/, + ) // Reasonable max length to prevent DOS .max(1000); @@ -111,7 +113,7 @@ const EmojiSchema = z.string().refine( }, { message: "Must contain at least one emoji character", - } + }, ); const ID = z .string() @@ -324,5 +326,3 @@ export const GameRecordSchema = z.object({ turns: z.array(TurnSchema), winner: ID.nullable(), }); - - diff --git a/src/core/Util.ts b/src/core/Util.ts index a31bdb7f5..5fbd32554 100644 --- a/src/core/Util.ts +++ b/src/core/Util.ts @@ -16,7 +16,7 @@ import { andFN, GameMap, manhattanDistFN, TileRef } from "./game/GameMap"; export function manhattanDistWrapped( c1: Cell, c2: Cell, - width: number + width: number, ): number { // Calculate x distance let dx = Math.abs(c1.x - c2.x); @@ -36,7 +36,7 @@ export function within(value: number, min: number, max: number): number { export function distSort( gm: GameMap, - target: TileRef + target: TileRef, ): (a: TileRef, b: TileRef) => number { return (a: TileRef, b: TileRef) => { return gm.manhattanDist(a, target) - gm.manhattanDist(b, target); @@ -45,7 +45,7 @@ export function distSort( export function distSortUnit( gm: GameMap, - target: Unit | TileRef + target: Unit | TileRef, ): (a: Unit, b: Unit) => number { const targetRef = typeof target === "number" ? target : target.tile(); @@ -61,7 +61,7 @@ export function distSortUnit( export function sourceDstOceanShore( gm: Game, src: Player, - tile: TileRef + tile: TileRef, ): [TileRef | null, TileRef | null] { const dst = gm.owner(tile); let srcTile = closestOceanShoreFromPlayer(gm, src, tile); @@ -88,10 +88,10 @@ export function targetTransportTile(gm: Game, tile: TileRef): TileRef | null { export function closestOceanShoreFromPlayer( gm: GameMap, player: Player, - target: TileRef + target: TileRef, ): TileRef | null { const shoreTiles = Array.from(player.borderTiles()).filter((t) => - gm.isOceanShore(t) + gm.isOceanShore(t), ); if (shoreTiles.length == 0) { return null; @@ -101,12 +101,12 @@ export function closestOceanShoreFromPlayer( const closestDistance = manhattanDistWrapped( gm.cell(target), gm.cell(closest), - gm.width() + gm.width(), ); const currentDistance = manhattanDistWrapped( gm.cell(target), gm.cell(current), - gm.width() + gm.width(), ); return currentDistance < closestDistance ? current : closest; }); @@ -115,13 +115,13 @@ export function closestOceanShoreFromPlayer( function closestOceanShoreTN( gm: GameMap, tile: TileRef, - searchDist: number + searchDist: number, ): TileRef { const tn = Array.from( gm.bfs( tile, - andFN((_, t) => !gm.hasOwner(t), manhattanDistFN(tile, searchDist)) - ) + andFN((_, t) => !gm.hasOwner(t), manhattanDistFN(tile, searchDist)), + ), ) .filter((t) => gm.isOceanShore(t)) .sort((a, b) => gm.manhattanDist(tile, a) - gm.manhattanDist(tile, b)); @@ -143,7 +143,7 @@ export function simpleHash(str: string): number { export function calculateBoundingBox( gm: GameMap, - borderTiles: ReadonlySet + borderTiles: ReadonlySet, ): { min: Cell; max: Cell } { let minX = Infinity, minY = Infinity, @@ -163,18 +163,18 @@ export function calculateBoundingBox( export function calculateBoundingBoxCenter( gm: GameMap, - borderTiles: ReadonlySet + borderTiles: ReadonlySet, ): Cell { const { min, max } = calculateBoundingBox(gm, borderTiles); return new Cell( min.x + Math.floor((max.x - min.x) / 2), - min.y + Math.floor((max.y - min.y) / 2) + min.y + Math.floor((max.y - min.y) / 2), ); } export function inscribed( outer: { min: Cell; max: Cell }, - inner: { min: Cell; max: Cell } + inner: { min: Cell; max: Cell }, ): boolean { return ( outer.min.x <= inner.min.x && @@ -238,7 +238,7 @@ export function processName(name: string): string { // Add CSS for the emoji images const withEmojiStyles = styledHTML.replace( / 0, - territoryBound: false, - }; - case UnitType.Warship: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : (p.units(UnitType.Warship).length + 1) * 250_000, - territoryBound: false, - maxHealth: 1000, - }; - case UnitType.Shell: - return { - cost: () => 0, - territoryBound: false, - damage: 250, - }; - case UnitType.Port: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : Math.min( - 1_000_000, - Math.pow(2, p.units(UnitType.Port).length) * - 250_000 - ), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 2 * 10, - }; - case UnitType.AtomBomb: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : 750_000, - territoryBound: false, - }; - case UnitType.HydrogenBomb: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : 5_000_000, - territoryBound: false, - }; - case UnitType.MIRV: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : 10_000_000, - territoryBound: false, - }; - case UnitType.MIRVWarhead: - return { - cost: () => 0, - territoryBound: false, - }; - case UnitType.TradeShip: - return { - cost: () => 0, - territoryBound: false, - }; - case UnitType.MissileSilo: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : 1_000_000, - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 10 * 10, - }; - case UnitType.DefensePost: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : Math.min( - 250_000, - (p.units(UnitType.DefensePost).length + 1) * - 50_000 - ), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 5 * 10, - }; - case UnitType.City: - return { - cost: (p: Player) => - p.type() == PlayerType.Human && this.creativeMode() - ? 0 - : Math.min( - 1_000_000, - Math.pow(2, p.units(UnitType.City).length) * - 125_000 - ), - territoryBound: true, - constructionDuration: this.creativeMode() ? 0 : 2 * 10, - }; - case UnitType.Construction: - return { - cost: () => 0, - territoryBound: true, - }; - default: - assertNever(type); - } - } - defaultDonationAmount(sender: Player): number { - return Math.floor(sender.troops() / 3); - } - donateCooldown(): Tick { - return 10 * 10; - } - emojiMessageDuration(): Tick { - return 5 * 10; - } - emojiMessageCooldown(): Tick { - return 15 * 10; - } - targetDuration(): Tick { - return 10 * 10; - } - targetCooldown(): Tick { - return 15 * 10; - } - allianceRequestCooldown(): Tick { - return 30 * 10; - } - allianceDuration(): Tick { - return 600 * 10; - } - percentageTilesOwnedToWin(): number { - return 80; - } - boatMaxNumber(): number { - return 3; - } - boatMaxDistance(): number { - return 500; - } - numSpawnPhaseTurns(): number { - return this._gameConfig.gameType == GameType.Singleplayer ? 100 : 300; - } - numBots(): number { - return 400; - } - theme(): Theme { - return pastelTheme; - } + unitInfo(type: UnitType): UnitInfo { + switch (type) { + case UnitType.TransportShip: + return { + cost: () => 0, + territoryBound: false, + }; + case UnitType.Warship: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : (p.units(UnitType.Warship).length + 1) * 250_000, + territoryBound: false, + maxHealth: 1000, + }; + case UnitType.Shell: + return { + cost: () => 0, + territoryBound: false, + damage: 250, + }; + case UnitType.Port: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : Math.min( + 1_000_000, + Math.pow(2, p.units(UnitType.Port).length) * 250_000, + ), + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 2 * 10, + }; + case UnitType.AtomBomb: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() ? 0 : 750_000, + territoryBound: false, + }; + case UnitType.HydrogenBomb: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() ? 0 : 5_000_000, + territoryBound: false, + }; + case UnitType.MIRV: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : 10_000_000, + territoryBound: false, + }; + case UnitType.MIRVWarhead: + return { + cost: () => 0, + territoryBound: false, + }; + case UnitType.TradeShip: + return { + cost: () => 0, + territoryBound: false, + }; + case UnitType.MissileSilo: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() ? 0 : 1_000_000, + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 10 * 10, + }; + case UnitType.DefensePost: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : Math.min( + 250_000, + (p.units(UnitType.DefensePost).length + 1) * 50_000, + ), + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 5 * 10, + }; + case UnitType.City: + return { + cost: (p: Player) => + p.type() == PlayerType.Human && this.creativeMode() + ? 0 + : Math.min( + 1_000_000, + Math.pow(2, p.units(UnitType.City).length) * 125_000, + ), + territoryBound: true, + constructionDuration: this.creativeMode() ? 0 : 2 * 10, + }; + case UnitType.Construction: + return { + cost: () => 0, + territoryBound: true, + }; + default: + assertNever(type); + } + } + defaultDonationAmount(sender: Player): number { + return Math.floor(sender.troops() / 3); + } + donateCooldown(): Tick { + return 10 * 10; + } + emojiMessageDuration(): Tick { + return 5 * 10; + } + emojiMessageCooldown(): Tick { + return 15 * 10; + } + targetDuration(): Tick { + return 10 * 10; + } + targetCooldown(): Tick { + return 15 * 10; + } + allianceRequestCooldown(): Tick { + return 30 * 10; + } + allianceDuration(): Tick { + return 600 * 10; + } + percentageTilesOwnedToWin(): number { + return 80; + } + boatMaxNumber(): number { + return 3; + } + boatMaxDistance(): number { + return 500; + } + numSpawnPhaseTurns(): number { + return this._gameConfig.gameType == GameType.Singleplayer ? 100 : 300; + } + numBots(): number { + return 400; + } + theme(): Theme { + return pastelTheme; + } - attackLogic( - gm: Game, - attackTroops: number, - attacker: Player, - defender: Player | TerraNullius, - tileToConquer: TileRef - ): { - attackerTroopLoss: number; - defenderTroopLoss: number; - tilesPerTickUsed: number; - } { - let mag = 0; - let speed = 0; - const type = gm.terrainType(tileToConquer); - switch (type) { - case TerrainType.Plains: - mag = 80; - speed = 15; - break; - case TerrainType.Highland: - mag = 100; - speed = 20; - break; - case TerrainType.Mountain: - mag = 120; - speed = 25; - break; - default: - throw new Error(`terrain type ${type} not supported`); - } - if (defender.isPlayer()) { - for (const dp of gm.nearbyDefensePosts(tileToConquer)) { - if (dp.owner() == defender) { - mag *= this.defensePostDefenseBonus(); - speed *= this.defensePostDefenseBonus(); - break; - } - } - } + attackLogic( + gm: Game, + attackTroops: number, + attacker: Player, + defender: Player | TerraNullius, + tileToConquer: TileRef, + ): { + attackerTroopLoss: number; + defenderTroopLoss: number; + tilesPerTickUsed: number; + } { + let mag = 0; + let speed = 0; + const type = gm.terrainType(tileToConquer); + switch (type) { + case TerrainType.Plains: + mag = 80; + speed = 15; + break; + case TerrainType.Highland: + mag = 100; + speed = 20; + break; + case TerrainType.Mountain: + mag = 120; + speed = 25; + break; + default: + throw new Error(`terrain type ${type} not supported`); + } + if (defender.isPlayer()) { + for (const dp of gm.nearbyDefensePosts(tileToConquer)) { + if (dp.owner() == defender) { + mag *= this.defensePostDefenseBonus(); + speed *= this.defensePostDefenseBonus(); + break; + } + } + } - if (gm.hasFallout(tileToConquer)) { - mag *= this.falloutDefenseModifier(); - speed *= this.falloutDefenseModifier(); - } + if (gm.hasFallout(tileToConquer)) { + mag *= this.falloutDefenseModifier(); + speed *= this.falloutDefenseModifier(); + } - if (attacker.isPlayer() && defender.isPlayer()) { - if ( - attacker.type() == PlayerType.Human && - defender.type() == PlayerType.Bot - ) { - mag *= 0.8; - } - if ( - attacker.type() == PlayerType.FakeHuman && - defender.type() == PlayerType.Bot - ) { - mag *= 0.8; - } - } + if (attacker.isPlayer() && defender.isPlayer()) { + if ( + attacker.type() == PlayerType.Human && + defender.type() == PlayerType.Bot + ) { + mag *= 0.8; + } + if ( + attacker.type() == PlayerType.FakeHuman && + defender.type() == PlayerType.Bot + ) { + mag *= 0.8; + } + } - if (defender.isPlayer()) { - return { - attackerTroopLoss: - within(defender.troops() / (2.5 * attackTroops), 0.1, 10) * - mag, - defenderTroopLoss: defender.troops() / defender.numTilesOwned(), - tilesPerTickUsed: - within(defender.troops() / (5 * attackTroops), 0.2, 1.5) * - speed, - }; - } else { - return { - attackerTroopLoss: - attacker.type() == PlayerType.Bot ? mag / 10 : mag / 5, - defenderTroopLoss: 0, - tilesPerTickUsed: within( - (2000 * Math.max(10, speed)) / attackTroops, - 5, - 100 - ), - }; - } - } + if (defender.isPlayer()) { + return { + attackerTroopLoss: + within(defender.troops() / (2.5 * attackTroops), 0.1, 10) * mag, + defenderTroopLoss: defender.troops() / defender.numTilesOwned(), + tilesPerTickUsed: + within(defender.troops() / (5 * attackTroops), 0.2, 1.5) * speed, + }; + } else { + return { + attackerTroopLoss: + attacker.type() == PlayerType.Bot ? mag / 10 : mag / 5, + defenderTroopLoss: 0, + tilesPerTickUsed: within( + (2000 * Math.max(10, speed)) / attackTroops, + 5, + 100, + ), + }; + } + } - attackTilesPerTick( - attackTroops: number, - attacker: Player, - defender: Player | TerraNullius, - numAdjacentTilesWithEnemy: number - ): number { - if (defender.isPlayer()) { - return ( - within( - ((5 * attackTroops) / defender.troops()) * 2, - 0.01, - 0.5 - ) * - numAdjacentTilesWithEnemy * - 3 - ); - } else { - return numAdjacentTilesWithEnemy * 2; - } - } + attackTilesPerTick( + attackTroops: number, + attacker: Player, + defender: Player | TerraNullius, + numAdjacentTilesWithEnemy: number, + ): number { + if (defender.isPlayer()) { + return ( + within(((5 * attackTroops) / defender.troops()) * 2, 0.01, 0.5) * + numAdjacentTilesWithEnemy * + 3 + ); + } else { + return numAdjacentTilesWithEnemy * 2; + } + } - boatAttackAmount( - attacker: Player, - defender: Player | TerraNullius - ): number { - return Math.floor(attacker.troops() / 5); - } + boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number { + return Math.floor(attacker.troops() / 5); + } - attackAmount(attacker: Player, defender: Player | TerraNullius) { - if (attacker.type() == PlayerType.Bot) { - return attacker.troops() / 20; - } else { - return attacker.troops() / 5; - } - } + attackAmount(attacker: Player, defender: Player | TerraNullius) { + if (attacker.type() == PlayerType.Bot) { + return attacker.troops() / 20; + } else { + return attacker.troops() / 5; + } + } - startManpower(playerInfo: PlayerInfo): number { - if (playerInfo.playerType == PlayerType.Bot) { - return 10_000; - } - if (playerInfo.playerType == PlayerType.FakeHuman) { - switch (this._gameConfig.difficulty) { - case Difficulty.Easy: - return 2_500 * (playerInfo?.nation?.strength ?? 1); - case Difficulty.Medium: - return 5_000 * (playerInfo?.nation?.strength ?? 1); - case Difficulty.Hard: - return 15_000 * (playerInfo?.nation?.strength ?? 1); - case Difficulty.Impossible: - return 20_000 * (playerInfo?.nation?.strength ?? 1); - } - } - return this.creativeMode() ? 1_000_000 : 25_000; - } + startManpower(playerInfo: PlayerInfo): number { + if (playerInfo.playerType == PlayerType.Bot) { + return 10_000; + } + if (playerInfo.playerType == PlayerType.FakeHuman) { + switch (this._gameConfig.difficulty) { + case Difficulty.Easy: + return 2_500 * (playerInfo?.nation?.strength ?? 1); + case Difficulty.Medium: + return 5_000 * (playerInfo?.nation?.strength ?? 1); + case Difficulty.Hard: + return 15_000 * (playerInfo?.nation?.strength ?? 1); + case Difficulty.Impossible: + return 20_000 * (playerInfo?.nation?.strength ?? 1); + } + } + return this.creativeMode() ? 1_000_000 : 25_000; + } - maxPopulation(player: Player | PlayerView): number { - let maxPop = - player.type() == PlayerType.Human && this.creativeMode() - ? 999_999_999_999 - : 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) + - player.units(UnitType.City).length * - this.cityPopulationIncrease(); + maxPopulation(player: Player | PlayerView): number { + let maxPop = + player.type() == PlayerType.Human && this.creativeMode() + ? 999_999_999_999 + : 2 * (Math.pow(player.numTilesOwned(), 0.6) * 1000 + 50000) + + player.units(UnitType.City).length * this.cityPopulationIncrease(); - if (player.type() == PlayerType.Bot) { - return maxPop / 2; - } + if (player.type() == PlayerType.Bot) { + return maxPop / 2; + } - if (player.type() == PlayerType.Human) { - return maxPop; - } + if (player.type() == PlayerType.Human) { + return maxPop; + } - switch (this._gameConfig.difficulty) { - case Difficulty.Easy: - return maxPop * 0.5; - case Difficulty.Medium: - return maxPop * 0.7; - case Difficulty.Hard: - return maxPop * 1; - case Difficulty.Impossible: - return maxPop * 1.5; - } - } + switch (this._gameConfig.difficulty) { + case Difficulty.Easy: + return maxPop * 0.5; + case Difficulty.Medium: + return maxPop * 0.7; + case Difficulty.Hard: + return maxPop * 1; + case Difficulty.Impossible: + return maxPop * 1.5; + } + } - populationIncreaseRate(player: Player): number { - let max = this.maxPopulation(player); + populationIncreaseRate(player: Player): number { + let max = this.maxPopulation(player); - let toAdd = 10 + Math.pow(player.population(), 0.73) / 4; + let toAdd = 10 + Math.pow(player.population(), 0.73) / 4; - const ratio = 1 - player.population() / max; - toAdd *= ratio; + const ratio = 1 - player.population() / max; + toAdd *= ratio; - if (player.type() == PlayerType.Bot) { - toAdd *= 0.7; - } + if (player.type() == PlayerType.Bot) { + toAdd *= 0.7; + } - return Math.min(player.population() + toAdd, max) - player.population(); - } + return Math.min(player.population() + toAdd, max) - player.population(); + } - goldAdditionRate(player: Player): number { - return Math.sqrt(player.workers() * player.numTilesOwned()) / 200; - } + goldAdditionRate(player: Player): number { + return Math.sqrt(player.workers() * player.numTilesOwned()) / 200; + } - troopAdjustmentRate(player: Player): number { - const maxDiff = this.maxPopulation(player) / 1000; - const target = player.population() * player.targetTroopRatio(); - const diff = target - player.troops(); - if (Math.abs(diff) < maxDiff) { - return diff; - } - const adjustment = maxDiff * Math.sign(diff); - // Can ramp down troops much faster - if (adjustment < 0) { - return adjustment * 5; - } - return adjustment; - } + troopAdjustmentRate(player: Player): number { + const maxDiff = this.maxPopulation(player) / 1000; + const target = player.population() * player.targetTroopRatio(); + const diff = target - player.troops(); + if (Math.abs(diff) < maxDiff) { + return diff; + } + const adjustment = maxDiff * Math.sign(diff); + // Can ramp down troops much faster + if (adjustment < 0) { + return adjustment * 5; + } + return adjustment; + } } diff --git a/src/core/execution/AttackExecution.ts b/src/core/execution/AttackExecution.ts index 9fc77e3d6..b016539e6 100644 --- a/src/core/execution/AttackExecution.ts +++ b/src/core/execution/AttackExecution.ts @@ -45,7 +45,7 @@ export class AttackExecution implements Execution { private _ownerID: PlayerID, private _targetID: PlayerID | null, private sourceTile: TileRef | null, - private removeTroops: boolean = true + private removeTroops: boolean = true, ) {} public targetID(): PlayerID { @@ -95,7 +95,7 @@ export class AttackExecution implements Execution { this.attack = this._owner.createAttack( this.target, this.startTroops, - this.sourceTile + this.sourceTile, ); for (const incoming of this._owner.incomingAttacks()) { @@ -174,7 +174,7 @@ export class AttackExecution implements Execution { this.attack.troops(), this._owner, this.target, - this.border.size + this.random.nextInt(0, 5) + this.border.size + this.random.nextInt(0, 5), ); // consolex.log(`num tiles per tick: ${numTilesPerTick}`) // consolex.log(`num execs: ${this.mg.executions().length}`) @@ -212,7 +212,7 @@ export class AttackExecution implements Execution { this.attack.troops(), this._owner, this.target, - tileToConquer + tileToConquer, ); numTilesPerTick -= tilesPerTickUsed; this.attack.setTroops(this.attack.troops() - attackerTroopLoss); @@ -253,8 +253,8 @@ export class AttackExecution implements Execution { new TileContainer( neighbor, dist / 100 + this.random.nextInt(0, 2) - numOwnedByMe + mag, - this.mg.ticks() - ) + this.mg.ticks(), + ), ); } } @@ -264,10 +264,10 @@ export class AttackExecution implements Execution { const gold = this.target.gold(); this.mg.displayMessage( `Conquered ${this.target.displayName()} received ${renderNumber( - gold + gold, )} gold`, MessageType.SUCCESS, - this._owner.id() + this._owner.id(), ); this.target.removeGold(gold); this._owner.addGold(gold); @@ -306,6 +306,6 @@ class TileContainer { constructor( public readonly tile: TileRef, public readonly priority: number, - public readonly tick: number + public readonly tick: number, ) {} } diff --git a/src/core/execution/BotExecution.ts b/src/core/execution/BotExecution.ts index 8c76c716a..7fde24e19 100644 --- a/src/core/execution/BotExecution.ts +++ b/src/core/execution/BotExecution.ts @@ -104,8 +104,8 @@ export class BotExecution implements Execution { this.bot.id(), toAttack.isPlayer() ? toAttack.id() : null, null, - null - ) + null, + ), ); } diff --git a/src/core/execution/ConstructionExecution.ts b/src/core/execution/ConstructionExecution.ts index 1b44b35d2..be86ad275 100644 --- a/src/core/execution/ConstructionExecution.ts +++ b/src/core/execution/ConstructionExecution.ts @@ -31,7 +31,7 @@ export class ConstructionExecution implements Execution { constructor( private ownerId: PlayerID, private tile: TileRef, - private constructionType: UnitType + private constructionType: UnitType, ) {} init(mg: Game, ticks: number): void { @@ -56,7 +56,7 @@ export class ConstructionExecution implements Execution { this.construction = this.player.buildUnit( UnitType.Construction, 0, - spawnTile + spawnTile, ); this.cost = this.mg.unitInfo(this.constructionType).cost(this.player); this.player.removeGold(this.cost); @@ -88,7 +88,7 @@ export class ConstructionExecution implements Execution { case UnitType.AtomBomb: case UnitType.HydrogenBomb: this.mg.addExecution( - new NukeExecution(this.constructionType, player.id(), this.tile) + new NukeExecution(this.constructionType, player.id(), this.tile), ); break; case UnitType.MIRV: diff --git a/src/core/execution/DefensePostExecution.ts b/src/core/execution/DefensePostExecution.ts index 52a690a40..d298ebc1e 100644 --- a/src/core/execution/DefensePostExecution.ts +++ b/src/core/execution/DefensePostExecution.ts @@ -16,7 +16,10 @@ export class DefensePostExecution implements Execution { private post: Unit; private active: boolean = true; - constructor(private ownerId: PlayerID, private tile: TileRef) {} + constructor( + private ownerId: PlayerID, + private tile: TileRef, + ) {} init(mg: Game, ticks: number): void { this.mg = mg; diff --git a/src/core/execution/ExecutionManager.ts b/src/core/execution/ExecutionManager.ts index bd9d4c974..b7e3f2c92 100644 --- a/src/core/execution/ExecutionManager.ts +++ b/src/core/execution/ExecutionManager.ts @@ -41,7 +41,7 @@ export class Executor { constructor( private mg: Game, private gameID: GameID, - private clientID: ClientID + private clientID: ClientID, ) { // Add one to avoid id collisions with bots. this.random = new PseudoRandom(simpleHash(gameID) + 1); @@ -58,7 +58,7 @@ export class Executor { intent.troops, intent.attackerID, intent.targetID, - null + null, ); } case "spawn": @@ -71,16 +71,16 @@ export class Executor { : fixProfaneUsername(sanitize(intent.name)), intent.playerType, intent.clientID, - intent.playerID + intent.playerID, ), - this.mg.ref(intent.x, intent.y) + this.mg.ref(intent.x, intent.y), ); case "boat": return new TransportShipExecution( intent.attackerID, intent.targetID, this.mg.ref(intent.x, intent.y), - intent.troops + intent.troops, ); case "allianceRequest": return new AllianceRequestExecution(intent.requestor, intent.recipient); @@ -88,7 +88,7 @@ export class Executor { return new AllianceRequestReplyExecution( intent.requestor, intent.recipient, - intent.accept + intent.accept, ); case "breakAlliance": return new BreakAllianceExecution(intent.requestor, intent.recipient); @@ -98,13 +98,13 @@ export class Executor { return new EmojiExecution( intent.sender, intent.recipient, - intent.emoji + intent.emoji, ); case "donate": return new DonateExecution( intent.sender, intent.recipient, - intent.troops + intent.troops, ); case "troop_ratio": return new SetTargetTroopRatioExecution(intent.player, intent.ratio); @@ -112,7 +112,7 @@ export class Executor { return new ConstructionExecution( intent.player, this.mg.ref(intent.x, intent.y), - intent.unit + intent.unit, ); default: throw new Error(`intent type ${intent} not found`); @@ -137,9 +137,9 @@ export class Executor { PlayerType.FakeHuman, null, this.random.nextID(), - nation - ) - ) + nation, + ), + ), ); } return execs; diff --git a/src/core/execution/FakeHumanExecution.ts b/src/core/execution/FakeHumanExecution.ts index eb7c7e93f..d3921adca 100644 --- a/src/core/execution/FakeHumanExecution.ts +++ b/src/core/execution/FakeHumanExecution.ts @@ -40,9 +40,12 @@ export class FakeHumanExecution implements Execution { private lastEnemyUpdateTick: number = 0; private lastEmojiSent = new Map(); - constructor(gameID: GameID, private playerInfo: PlayerInfo) { + constructor( + gameID: GameID, + private playerInfo: PlayerInfo, + ) { this.random = new PseudoRandom( - simpleHash(playerInfo.id) + simpleHash(gameID) + simpleHash(playerInfo.id) + simpleHash(gameID), ); } @@ -99,7 +102,7 @@ export class FakeHumanExecution implements Execution { const enemyborder = Array.from(this.player.borderTiles()) .flatMap((t) => this.mg.neighbors(t)) .filter( - (t) => this.mg.isLand(t) && this.mg.ownerID(t) != this.player.smallID() + (t) => this.mg.isLand(t) && this.mg.ownerID(t) != this.player.smallID(), ); if (enemyborder.length == 0) { @@ -114,7 +117,7 @@ export class FakeHumanExecution implements Execution { } const enemiesWithTN = enemyborder.map((t) => - this.mg.playerBySmallID(this.mg.ownerID(t)) + this.mg.playerBySmallID(this.mg.ownerID(t)), ); if (enemiesWithTN.filter((o) => !o.isPlayer()).length > 0) { this.sendAttack(this.mg.terraNullius()); @@ -194,7 +197,7 @@ export class FakeHumanExecution implements Execution { this.lastEnemyUpdateTick = this.mg.ticks(); if (target.ally.type() == PlayerType.Human) { this.mg.addExecution( - new EmojiExecution(this.player.id(), target.ally.id(), "👍") + new EmojiExecution(this.player.id(), target.ally.id(), "👍"), ); } } @@ -215,8 +218,8 @@ export class FakeHumanExecution implements Execution { new EmojiExecution( this.player.id(), this.enemy.id(), - this.random.randElement(["🤡", "😡"]) - ) + this.random.randElement(["🤡", "😡"]), + ), ); } } @@ -260,7 +263,7 @@ export class FakeHumanExecution implements Execution { } if (this.player.canBuild(UnitType.AtomBomb, tile)) { this.mg.addExecution( - new NukeExecution(UnitType.AtomBomb, this.player.id(), tile) + new NukeExecution(UnitType.AtomBomb, this.player.id(), tile), ); return; } @@ -271,9 +274,9 @@ export class FakeHumanExecution implements Execution { const closest = closestTwoTiles( this.mg, Array.from(this.player.borderTiles()).filter((t) => - this.mg.isOceanShore(t) + this.mg.isOceanShore(t), ), - Array.from(other.borderTiles()).filter((t) => this.mg.isOceanShore(t)) + Array.from(other.borderTiles()).filter((t) => this.mg.isOceanShore(t)), ); if (closest == null) { return; @@ -287,8 +290,8 @@ export class FakeHumanExecution implements Execution { this.player.id(), other.id(), closest.y, - this.player.troops() / 5 - ) + this.player.troops() / 5, + ), ); } } @@ -297,12 +300,12 @@ export class FakeHumanExecution implements Execution { const ports = this.player.units(UnitType.Port); if (ports.length == 0 && this.player.gold() > this.cost(UnitType.Port)) { const oceanTiles = Array.from(this.player.borderTiles()).filter((t) => - this.mg.isOceanShore(t) + this.mg.isOceanShore(t), ); if (oceanTiles.length > 0) { const buildTile = this.random.randElement(oceanTiles); this.mg.addExecution( - new ConstructionExecution(this.player.id(), buildTile, UnitType.Port) + new ConstructionExecution(this.player.id(), buildTile, UnitType.Port), ); } return; @@ -310,7 +313,7 @@ export class FakeHumanExecution implements Execution { this.maybeSpawnStructure( UnitType.City, 2, - (t) => new ConstructionExecution(this.player.id(), t, UnitType.City) + (t) => new ConstructionExecution(this.player.id(), t, UnitType.City), ); if (this.maybeSpawnWarship()) { return; @@ -319,14 +322,14 @@ export class FakeHumanExecution implements Execution { UnitType.MissileSilo, 1, (t) => - new ConstructionExecution(this.player.id(), t, UnitType.MissileSilo) + new ConstructionExecution(this.player.id(), t, UnitType.MissileSilo), ); } private maybeSpawnStructure( type: UnitType, maxNum: number, - build: (tile: TileRef) => Execution + build: (tile: TileRef) => Execution, ) { const units = this.player.units(type); if (units.length >= maxNum) { @@ -373,8 +376,8 @@ export class FakeHumanExecution implements Execution { new ConstructionExecution( this.player.id(), targetTile, - UnitType.Warship - ) + UnitType.Warship, + ), ); return true; } @@ -403,11 +406,11 @@ export class FakeHumanExecution implements Execution { for (let attempts = 0; attempts < 50; attempts++) { const randX = this.random.nextInt( this.mg.x(portTile) - radius, - this.mg.x(portTile) + radius + this.mg.x(portTile) + radius, ); const randY = this.random.nextInt( this.mg.y(portTile) - radius, - this.mg.y(portTile) + radius + this.mg.y(portTile) + radius, ); if (!this.mg.isValidCoord(randX, randY)) { continue; @@ -457,8 +460,8 @@ export class FakeHumanExecution implements Execution { new AllianceRequestReplyExecution( req.requestor().id(), this.player.id(), - accept - ) + accept, + ), ); } @@ -469,7 +472,7 @@ export class FakeHumanExecution implements Execution { if (oceanShore == null) { oceanShore = Array.from(this.player.borderTiles()).filter((t) => - this.mg.isOceanShore(t) + this.mg.isOceanShore(t), ); } if (oceanShore.length == 0) { @@ -482,9 +485,9 @@ export class FakeHumanExecution implements Execution { src, andFN( (gm, t) => gm.isOcean(t) || gm.isOceanShore(t), - manhattanDistFN(src, 200) - ) - ) + manhattanDistFN(src, 200), + ), + ), ).filter((t) => this.mg.isOceanShore(t) && this.mg.owner(t) != this.player); if (otherShore.length == 0) { @@ -508,8 +511,8 @@ export class FakeHumanExecution implements Execution { this.player.id(), this.mg.hasOwner(dst) ? this.mg.owner(dst).id() : null, dst, - this.player.troops() / 5 - ) + this.player.troops() / 5, + ), ); return; } @@ -548,8 +551,8 @@ export class FakeHumanExecution implements Execution { this.player.id(), toAttack.isPlayer() ? toAttack.id() : null, null, - null - ) + null, + ), ); } @@ -557,7 +560,7 @@ export class FakeHumanExecution implements Execution { return ( this.mg.bfs( tile, - andFN((gm, t) => gm.isLand(t), manhattanDistFN(tile, 10)) + andFN((gm, t) => gm.isLand(t), manhattanDistFN(tile, 10)), ).size < 50 ); } diff --git a/src/core/execution/MIRVExecution.ts b/src/core/execution/MIRVExecution.ts index 4f60b0954..b6095ba80 100644 --- a/src/core/execution/MIRVExecution.ts +++ b/src/core/execution/MIRVExecution.ts @@ -37,7 +37,10 @@ export class MirvExecution implements Execution { private separateDst: TileRef; - constructor(private senderID: PlayerID, private dst: TileRef) {} + constructor( + private senderID: PlayerID, + private dst: TileRef, + ) {} init(mg: Game, ticks: number): void { this.random = new PseudoRandom(mg.ticks() + simpleHash(this.senderID)); @@ -57,7 +60,7 @@ export class MirvExecution implements Execution { } this.nuke = this.player.buildUnit(UnitType.MIRV, 0, spawn); const x = Math.floor( - (this.mg.x(this.dst) + this.mg.x(this.mg.x(this.nuke.tile()))) / 2 + (this.mg.x(this.dst) + this.mg.x(this.mg.x(this.nuke.tile()))) / 2, ); const y = Math.max(0, this.mg.y(this.dst) - 500) + 50; this.separateDst = this.mg.ref(x, y); @@ -66,7 +69,7 @@ export class MirvExecution implements Execution { for (let i = 0; i < 4; i++) { const result = this.pathFinder.nextTile( this.nuke.tile(), - this.separateDst + this.separateDst, ); switch (result.type) { case PathFindResultType.Completed: @@ -81,7 +84,7 @@ export class MirvExecution implements Execution { break; case PathFindResultType.PathNotFound: consolex.warn( - `nuke cannot find path from ${this.nuke.tile()} to ${this.dst}` + `nuke cannot find path from ${this.nuke.tile()} to ${this.dst}`, ); this.active = false; return; @@ -103,7 +106,7 @@ export class MirvExecution implements Execution { console.log(`dsts: ${dsts.length}`); dsts.sort( (a, b) => - this.mg.manhattanDist(b, this.dst) - this.mg.manhattanDist(a, this.dst) + this.mg.manhattanDist(b, this.dst) - this.mg.manhattanDist(a, this.dst), ); console.log(`got ${dsts.length} dsts!!`); @@ -116,8 +119,8 @@ export class MirvExecution implements Execution { this.nuke.tile(), 15 + Math.floor((i / this.warheadCount) * 5), // this.random.nextInt(5, 9), - this.random.nextInt(0, 15) - ) + this.random.nextInt(0, 15), + ), ); } if (this.targetPlayer.isPlayer()) { @@ -138,11 +141,11 @@ export class MirvExecution implements Execution { tries++; const x = this.random.nextInt( this.mg.x(ref) - this.mirvRange, - this.mg.x(ref) + this.mirvRange + this.mg.x(ref) + this.mirvRange, ); const y = this.random.nextInt( this.mg.y(ref) - this.mirvRange, - this.mg.y(ref) + this.mirvRange + this.mg.y(ref) + this.mirvRange, ); if (!this.mg.isValidCoord(x, y)) { continue; diff --git a/src/core/execution/NukeExecution.ts b/src/core/execution/NukeExecution.ts index dee6155ac..2bb387c0c 100644 --- a/src/core/execution/NukeExecution.ts +++ b/src/core/execution/NukeExecution.ts @@ -29,7 +29,7 @@ export class NukeExecution implements Execution { private dst: TileRef, private src?: TileRef, private speed: number = 4, - private waitTicks = 0 + private waitTicks = 0, ) {} init(mg: Game, ticks: number): void { @@ -77,7 +77,7 @@ export class NukeExecution implements Execution { let nextY = y; const ratio = Math.floor( - 1 + Math.abs(dstY - y) / (Math.abs(dstX - x) + 1) + 1 + Math.abs(dstY - y) / (Math.abs(dstX - x) + 1), ); if (this.random.chance(ratio) && x != dstX) { @@ -123,7 +123,7 @@ export class NukeExecution implements Execution { const ratio = Object.fromEntries( this.mg .players() - .map((p) => [p.id(), (p.troops() + p.workers()) / p.numTilesOwned()]) + .map((p) => [p.id(), (p.troops() + p.workers()) / p.numTilesOwned()]), ); const attacked = new Map(); for (const tile of toDestroy) { diff --git a/src/core/execution/PortExecution.ts b/src/core/execution/PortExecution.ts index b338c7a92..0d0b99815 100644 --- a/src/core/execution/PortExecution.ts +++ b/src/core/execution/PortExecution.ts @@ -25,7 +25,10 @@ export class PortExecution implements Execution { private portPaths = new Map(); private computingPaths = new Map(); - constructor(private _owner: PlayerID, private tile: TileRef) {} + constructor( + private _owner: PlayerID, + private tile: TileRef, + ) {} init(mg: Game, ticks: number): void { this.mg = mg; @@ -46,7 +49,7 @@ export class PortExecution implements Execution { .filter((t) => this.mg.isOceanShore(t) && this.mg.owner(t) == player) .sort( (a, b) => - this.mg.manhattanDist(a, tile) - this.mg.manhattanDist(b, tile) + this.mg.manhattanDist(a, tile) - this.mg.manhattanDist(b, tile), ); if (spawns.length == 0) { @@ -68,7 +71,7 @@ export class PortExecution implements Execution { const alliedPortsSet = new Set(alliedPorts); const allyConnections = new Set( - Array.from(this.portPaths.keys()).map((p) => p.owner()) + Array.from(this.portPaths.keys()).map((p) => p.owner()), ); allyConnections; @@ -100,7 +103,7 @@ export class PortExecution implements Execution { port.tile(), (tr: TileRef) => this.mg.miniMap().isOcean(tr), 10_000, - 25 + 25, ); this.computingPaths.set(port, pf); } @@ -123,7 +126,7 @@ export class PortExecution implements Execution { if (path != null) { const pf = PathFinder.Mini(this.mg, 10000, false); this.mg.addExecution( - new TradeShipExecution(this.player().id(), this.port, port, pf, path) + new TradeShipExecution(this.player().id(), this.port, port, pf, path), ); } } diff --git a/src/core/execution/WarshipExecution.ts b/src/core/execution/WarshipExecution.ts index 9cd1d40a9..c84cc9823 100644 --- a/src/core/execution/WarshipExecution.ts +++ b/src/core/execution/WarshipExecution.ts @@ -37,7 +37,10 @@ export class WarshipExecution implements Execution { private alreadySentShell = new Set(); - constructor(private playerID: PlayerID, private patrolCenterTile: TileRef) {} + constructor( + private playerID: PlayerID, + private patrolCenterTile: TileRef, + ) {} init(mg: Game, ticks: number): void { this.pathfinder = PathFinder.Mini(mg, 5000, false); @@ -68,7 +71,7 @@ export class WarshipExecution implements Execution { const ships = this.mg .units(UnitType.TransportShip, UnitType.Warship, UnitType.TradeShip) .filter( - (u) => this.mg.manhattanDist(u.tile(), this.warship.tile()) < 130 + (u) => this.mg.manhattanDist(u.tile(), this.warship.tile()) < 130, ) .filter((u) => u.owner() != this.warship.owner()) .filter((u) => u != this.warship) @@ -80,7 +83,7 @@ export class WarshipExecution implements Execution { // Patrol unless we are hunting down a tradeship const result = this.pathfinder.nextTile( this.warship.tile(), - this.patrolTile + this.patrolTile, ); switch (result.type) { case PathFindResultType.Completed: @@ -115,8 +118,8 @@ export class WarshipExecution implements Execution { this.warship.tile(), this.warship.owner(), this.warship, - this.target - ) + this.target, + ), ); if (!this.target.hasHealth()) { // Don't send multiple shells to target that can be oneshotted @@ -134,7 +137,7 @@ export class WarshipExecution implements Execution { const result = this.pathfinder.nextTile( this.warship.tile(), this.target.tile(), - 5 + 5, ); switch (result.type) { case PathFindResultType.Completed: diff --git a/src/core/execution/alliance/AllianceRequestExecution.ts b/src/core/execution/alliance/AllianceRequestExecution.ts index 9ad100564..c5a20843a 100644 --- a/src/core/execution/alliance/AllianceRequestExecution.ts +++ b/src/core/execution/alliance/AllianceRequestExecution.ts @@ -13,7 +13,10 @@ export class AllianceRequestExecution implements Execution { private requestor: Player; private recipient: Player; - constructor(private requestorID: PlayerID, private recipientID: PlayerID) {} + constructor( + private requestorID: PlayerID, + private recipientID: PlayerID, + ) {} init(mg: Game, ticks: number): void { this.mg = mg; diff --git a/src/core/game/AttackImpl.ts b/src/core/game/AttackImpl.ts index 87d7a0017..7444f6b24 100644 --- a/src/core/game/AttackImpl.ts +++ b/src/core/game/AttackImpl.ts @@ -9,7 +9,7 @@ export class AttackImpl implements Attack { private _target: Player | TerraNullius, private _attacker: Player, private _troops: number, - private _sourceTile: TileRef | null + private _sourceTile: TileRef | null, ) {} sourceTile(): TileRef | null { diff --git a/src/core/game/DefensePostGrid.ts b/src/core/game/DefensePostGrid.ts index bafffe6c8..32427982c 100644 --- a/src/core/game/DefensePostGrid.ts +++ b/src/core/game/DefensePostGrid.ts @@ -6,13 +6,16 @@ export class DefenseGrid { private grid: Set[][]; private readonly cellSize = 100; - constructor(private gm: GameMap, private searchRange: number) { + constructor( + private gm: GameMap, + private searchRange: number, + ) { this.grid = Array(Math.ceil(gm.height() / this.cellSize)) .fill(null) .map(() => Array(Math.ceil(gm.width() / this.cellSize)) .fill(null) - .map(() => new Set()) + .map(() => new Set()), ); } diff --git a/src/core/game/Game.ts b/src/core/game/Game.ts index 3f2cb0331..cde3b9360 100644 --- a/src/core/game/Game.ts +++ b/src/core/game/Game.ts @@ -89,7 +89,7 @@ export class Nation { public readonly flag: string, public readonly name: string, public readonly cell: Cell, - public readonly strength: number + public readonly strength: number, ) {} } @@ -98,7 +98,10 @@ export class Cell { private strRepr: string; - constructor(public readonly x, public readonly y) { + constructor( + public readonly x, + public readonly y, + ) { this.strRepr = `Cell[${this.x},${this.y}]`; } @@ -176,7 +179,7 @@ export class PlayerInfo { public readonly clientID: ClientID | null, // TODO: make player id the small id public readonly id: PlayerID, - public readonly nation?: Nation | null + public readonly nation?: Nation | null, ) {} } @@ -302,7 +305,7 @@ export interface Player { createAttack( target: Player | TerraNullius, troops: number, - sourceTile: TileRef + sourceTile: TileRef, ): Attack; outgoingAttacks(): Attack[]; incomingAttacks(): Attack[]; @@ -350,7 +353,7 @@ export interface Game extends GameMap { displayMessage( message: string, type: MessageType, - playerID: PlayerID | null + playerID: PlayerID | null, ): void; // Nations diff --git a/src/core/game/GameImpl.ts b/src/core/game/GameImpl.ts index c47b56bbd..ea1a85a97 100644 --- a/src/core/game/GameImpl.ts +++ b/src/core/game/GameImpl.ts @@ -35,7 +35,7 @@ export function createGame( gameMap: GameMap, miniGameMap: GameMap, nationMap: NationMap, - config: Config + config: Config, ): Game { return new GameImpl(gameMap, miniGameMap, nationMap, config); } @@ -70,7 +70,7 @@ export class GameImpl implements Game { private _map: GameMap, private miniGameMap: GameMap, nationMap: NationMap, - private _config: Config + private _config: Config, ) { this._terraNullius = new TerraNulliusImpl(); this._width = _map.width(); @@ -81,12 +81,12 @@ export class GameImpl implements Game { n.flag || "", n.name, new Cell(n.coordinates[0], n.coordinates[1]), - n.strength - ) + n.strength, + ), ); this.defenseGrid = new DefenseGrid( this._map, - this._config.defensePostRange() + this._config.defensePostRange(), ); } @@ -173,11 +173,11 @@ export class GameImpl implements Game { this, request.requestor() as PlayerImpl, request.recipient() as PlayerImpl, - this._ticks + this._ticks, ); this.alliances_.push(alliance); (request.requestor() as PlayerImpl).pastOutgoingAllianceRequests.push( - request + request, ); this.addUpdate({ type: GameUpdateType.AllianceRequestReply, @@ -189,7 +189,7 @@ export class GameImpl implements Game { rejectAllianceRequest(request: AllianceRequestImpl) { this.allianceRequests = this.allianceRequests.filter((ar) => ar != request); (request.requestor() as PlayerImpl).pastOutgoingAllianceRequests.push( - request + request, ); this.addUpdate({ type: GameUpdateType.AllianceRequestReply, @@ -296,7 +296,7 @@ export class GameImpl implements Game { removeExecution(exec: Execution) { this.execs = this.execs.filter((execution) => execution !== exec); this.unInitExecs = this.unInitExecs.filter( - (execution) => execution !== exec + (execution) => execution !== exec, ); } @@ -448,7 +448,7 @@ export class GameImpl implements Game { } if (!breaker.isAlliedWith(other)) { throw new Error( - `${breaker} not allied with ${other}, cannot break alliance` + `${breaker} not allied with ${other}, cannot break alliance`, ); } if (!other.isTraitor()) { @@ -459,7 +459,7 @@ export class GameImpl implements Game { const alliances = other.alliances().filter((a) => breakerSet.has(a)); if (alliances.length != 1) { throw new Error( - `must have exactly one alliance, have ${alliances.length}` + `must have exactly one alliance, have ${alliances.length}`, ); } this.alliances_ = this.alliances_.filter((a) => a != alliances[0]); @@ -478,7 +478,7 @@ export class GameImpl implements Game { .filter((a) => p1Set.has(a)); if (alliances.length != 1) { throw new Error( - `cannot expire alliance: must have exactly one alliance, have ${alliances.length}` + `cannot expire alliance: must have exactly one alliance, have ${alliances.length}`, ); } this.alliances_ = this.alliances_.filter((a) => a != alliances[0]); @@ -506,7 +506,7 @@ export class GameImpl implements Game { displayMessage( message: string, type: MessageType, - playerID: PlayerID | null + playerID: PlayerID | null, ): void { let id = null; if (playerID != null) { @@ -614,7 +614,7 @@ export class GameImpl implements Game { } bfs( tile: TileRef, - filter: (gm: GameMap, tile: TileRef) => boolean + filter: (gm: GameMap, tile: TileRef) => boolean, ): Set { return this._map.bfs(tile, filter); } diff --git a/src/core/game/GameUpdates.ts b/src/core/game/GameUpdates.ts index 1ced76389..c7f7faafe 100644 --- a/src/core/game/GameUpdates.ts +++ b/src/core/game/GameUpdates.ts @@ -80,7 +80,7 @@ export interface PlayerUpdate { type: GameUpdateType.Player; nameViewData?: NameViewData; clientID: ClientID; - flag: string, + flag: string; name: string; displayName: string; id: PlayerID; diff --git a/src/core/game/GameView.ts b/src/core/game/GameView.ts index ae893438e..e79922c7c 100644 --- a/src/core/game/GameView.ts +++ b/src/core/game/GameView.ts @@ -36,7 +36,10 @@ export class UnitView { public _wasUpdated = true; public lastPos: MapPos[] = []; - constructor(private gameView: GameView, private data: UnitUpdate) { + constructor( + private gameView: GameView, + private data: UnitUpdate, + ) { this.lastPos.push(data.pos); } @@ -95,14 +98,14 @@ export class PlayerView { constructor( private game: GameView, public data: PlayerUpdate, - public nameData: NameViewData + public nameData: NameViewData, ) {} async actions(tile: TileRef): Promise { return this.game.worker.playerInteraction( this.id(), this.game.x(tile), - this.game.y(tile) + this.game.y(tile), ); } @@ -156,12 +159,12 @@ export class PlayerView { } allies(): PlayerView[] { return this.data.allies.map( - (a) => this.game.playerBySmallID(a) as PlayerView + (a) => this.game.playerBySmallID(a) as PlayerView, ); } targets(): PlayerView[] { return this.data.targets.map( - (id) => this.game.playerBySmallID(id) as PlayerView + (id) => this.game.playerBySmallID(id) as PlayerView, ); } gold(): Gold { @@ -199,7 +202,13 @@ export class PlayerView { return this.data.outgoingEmojis; } info(): PlayerInfo { - return new PlayerInfo(this.flag(), this.name(), this.type(), this.clientID(), this.id()); + return new PlayerInfo( + this.flag(), + this.name(), + this.type(), + this.clientID(), + this.id(), + ); } } @@ -218,7 +227,7 @@ export class GameView implements GameMap { public worker: WorkerClient, private _config: Config, private _map: GameMap, - private _myClientID: ClientID + private _myClientID: ClientID, ) { this.lastUpdate = { tick: 0, @@ -250,7 +259,7 @@ export class GameView implements GameMap { } else { this._players.set( pu.id, - new PlayerView(this, pu, gu.playerNameViewData[pu.id]) + new PlayerView(this, pu, gu.playerNameViewData[pu.id]), ); } }); @@ -347,7 +356,7 @@ export class GameView implements GameMap { return Array.from(this._units.values()).filter((u) => u.isActive()); } return Array.from(this._units.values()).filter( - (u) => u.isActive() && types.includes(u.type()) + (u) => u.isActive() && types.includes(u.type()), ); } unit(id: number): UnitView { @@ -443,7 +452,7 @@ export class GameView implements GameMap { } bfs( tile: TileRef, - filter: (gm: GameMap, tile: TileRef) => boolean + filter: (gm: GameMap, tile: TileRef) => boolean, ): Set { return this._map.bfs(tile, filter); } diff --git a/src/core/game/PlayerImpl.ts b/src/core/game/PlayerImpl.ts index 279bc4167..20fed8325 100644 --- a/src/core/game/PlayerImpl.ts +++ b/src/core/game/PlayerImpl.ts @@ -46,7 +46,10 @@ interface Target { } class Donation { - constructor(public readonly recipient: Player, public readonly tick: Tick) {} + constructor( + public readonly recipient: Player, + public readonly tick: Tick, + ) {} } export class PlayerImpl implements Player { @@ -85,7 +88,7 @@ export class PlayerImpl implements Player { private mg: GameImpl, private _smallID: number, private readonly playerInfo: PlayerInfo, - startPopulation: number + startPopulation: number, ) { this._flag = playerInfo.flag; this._name = playerInfo.name; @@ -125,7 +128,7 @@ export class PlayerImpl implements Player { attackerID: a.attacker().smallID(), targetID: a.target().smallID(), troops: a.troops(), - } as AttackUpdate) + }) as AttackUpdate, ), incomingAttacks: this._incomingAttacks.map( (a) => @@ -133,7 +136,7 @@ export class PlayerImpl implements Player { attackerID: a.attacker().smallID(), targetID: a.target().smallID(), troops: a.troops(), - } as AttackUpdate) + }) as AttackUpdate, ), }; } @@ -203,7 +206,7 @@ export class PlayerImpl implements Player { const owner = this.mg.map().ownerID(neighbor); if (owner != this.smallID()) { ns.add( - this.mg.playerBySmallID(owner) as PlayerImpl | TerraNulliusImpl + this.mg.playerBySmallID(owner) as PlayerImpl | TerraNulliusImpl, ); } } @@ -249,7 +252,7 @@ export class PlayerImpl implements Player { alliances(): MutableAlliance[] { return this.mg.alliances_.filter( - (a) => a.requestor() == this || a.recipient() == this + (a) => a.requestor() == this || a.recipient() == this, ); } @@ -269,7 +272,7 @@ export class PlayerImpl implements Player { return null; } return this.alliances().find( - (a) => a.recipient() == other || a.requestor() == other + (a) => a.recipient() == other || a.requestor() == other, ); } @@ -398,7 +401,7 @@ export class PlayerImpl implements Player { targets(): PlayerImpl[] { return this.targets_ .filter( - (t) => this.mg.ticks() - t.tick < this.mg.config().targetDuration() + (t) => this.mg.ticks() - t.tick < this.mg.config().targetDuration(), ) .map((t) => t.target as PlayerImpl); } @@ -430,7 +433,7 @@ export class PlayerImpl implements Player { .filter( (e) => this.mg.ticks() - e.createdAt < - this.mg.config().emojiMessageDuration() + this.mg.config().emojiMessageDuration(), ) .sort((a, b) => b.createdAt - a.createdAt); } @@ -439,7 +442,7 @@ export class PlayerImpl implements Player { const recipientID = recipient == AllPlayers ? AllPlayers : recipient.smallID(); const prevMsgs = this.outgoingEmojis_.filter( - (msg) => msg.recipientID == recipientID + (msg) => msg.recipientID == recipientID, ); for (const msg of prevMsgs) { if ( @@ -475,12 +478,12 @@ export class PlayerImpl implements Player { this.mg.displayMessage( `Sent ${renderTroops(troops)} troops to ${recipient.name()}`, MessageType.INFO, - this.id() + this.id(), ); this.mg.displayMessage( `Recieved ${renderTroops(troops)} troops from ${this.name()}`, MessageType.SUCCESS, - recipient.id() + recipient.id(), ); } @@ -495,7 +498,7 @@ export class PlayerImpl implements Player { removeGold(toRemove: Gold): void { if (toRemove > this._gold) { throw Error( - `Player ${this} does not enough gold (${toRemove} vs ${this._gold}))` + `Player ${this} does not enough gold (${toRemove} vs ${this._gold}))`, ); } this._gold -= toRemove; @@ -521,7 +524,7 @@ export class PlayerImpl implements Player { setTargetTroopRatio(target: number): void { if (target < 0 || target > 1) { throw new Error( - `invalid targetTroopRatio ${target} set on player ${PlayerImpl}` + `invalid targetTroopRatio ${target} set on player ${PlayerImpl}`, ); } this._targetTroopRatio = target; @@ -553,7 +556,7 @@ export class PlayerImpl implements Player { } const prev = unit.owner(); (prev as PlayerImpl)._units = (prev as PlayerImpl)._units.filter( - (u) => u != unit + (u) => u != unit, ); (unit as UnitImpl)._owner = this; this._units.push(unit as UnitImpl); @@ -561,12 +564,12 @@ export class PlayerImpl implements Player { this.mg.displayMessage( `${unit.type()} captured by ${this.displayName()}`, MessageType.ERROR, - prev.id() + prev.id(), ); this.mg.displayMessage( `Captured ${unit.type()} from ${prev.displayName()}`, MessageType.SUCCESS, - this.id() + this.id(), ); } @@ -578,7 +581,7 @@ export class PlayerImpl implements Player { spawnTile, troops, this.mg.nextUnitID(), - this + this, ); this._units.push(b); this.removeGold(cost); @@ -641,7 +644,7 @@ export class PlayerImpl implements Player { .filter((t) => this.mg.owner(t) == this && this.mg.isOceanShore(t)) .sort( (a, b) => - this.mg.manhattanDist(a, tile) - this.mg.manhattanDist(b, tile) + this.mg.manhattanDist(a, tile) - this.mg.manhattanDist(b, tile), ); if (spawns.length == 0) { return false; @@ -657,12 +660,12 @@ export class PlayerImpl implements Player { .filter( (u) => this.mg.manhattanDist(u.tile(), tile) < - this.mg.config().boatMaxDistance() + this.mg.config().boatMaxDistance(), ) .sort( (a, b) => this.mg.manhattanDist(a.tile(), tile) - - this.mg.manhattanDist(b.tile(), tile) + this.mg.manhattanDist(b.tile(), tile), ); if (spawns.length == 0) { return false; @@ -690,7 +693,7 @@ export class PlayerImpl implements Player { tradeShipSpawn(targetTile: TileRef): TileRef | false { const spawns = this.units(UnitType.Port).filter( - (u) => u.tile() == targetTile + (u) => u.tile() == targetTile, ); if (spawns.length == 0) { return false; @@ -721,7 +724,7 @@ export class PlayerImpl implements Player { this.allRelationsSorted().map(({ player, relation }) => [ player.smallID(), relation, - ]) + ]), ), alliances: this.alliances().map((a) => a.other(this).smallID()), }; @@ -765,8 +768,8 @@ export class PlayerImpl implements Player { tile, andFN( (gm, t) => gm.ownerID(t) == gm.ownerID(tile) && gm.isLand(t), - manhattanDistFN(tile, 25) - ) + manhattanDistFN(tile, 25), + ), )) { if (this.mg.isOceanShore(t)) { nearOcean = true; @@ -790,7 +793,7 @@ export class PlayerImpl implements Player { createAttack( target: Player | TerraNullius, troops: number, - sourceTile: TileRef + sourceTile: TileRef, ): Attack { const attack = new AttackImpl(target, this, troops, sourceTile); this._outgoingAttacks.push(attack); @@ -835,8 +838,8 @@ export class PlayerImpl implements Player { tile, andFN( (gm, t) => !gm.hasOwner(t) && gm.isLand(t), - manhattanDistFN(tile, 200) - ) + manhattanDistFN(tile, 200), + ), )) { for (const n of this.mg.neighbors(t)) { if (this.mg.owner(n) == this) { diff --git a/src/core/game/UnitImpl.ts b/src/core/game/UnitImpl.ts index 1cc90a682..5c398ead3 100644 --- a/src/core/game/UnitImpl.ts +++ b/src/core/game/UnitImpl.ts @@ -20,7 +20,7 @@ export class UnitImpl implements Unit { private _tile: TileRef, private _troops: number, private _id: number, - public _owner: PlayerImpl + public _owner: PlayerImpl, ) { // default to half health (or 1 is no health specified) this._health = (this.mg.unitInfo(_type).maxHealth ?? 2) / 2; @@ -89,7 +89,7 @@ export class UnitImpl implements Unit { this.mg.displayMessage( `Your ${this.type()} was captured by ${newOwner.displayName()}`, MessageType.ERROR, - oldOwner.id() + oldOwner.id(), ); } @@ -111,7 +111,7 @@ export class UnitImpl implements Unit { this.mg.displayMessage( `Your ${this.type()} was destroyed`, MessageType.ERROR, - this.owner().id() + this.owner().id(), ); } } diff --git a/src/core/validations/username.ts b/src/core/validations/username.ts index c1de0c357..c22ff4fa6 100644 --- a/src/core/validations/username.ts +++ b/src/core/validations/username.ts @@ -61,7 +61,8 @@ export function validateUsername(username: string): { if (!validPattern.test(username)) { return { isValid: false, - error: "Username can only contain letters, numbers, spaces, underscores, and [square brackets].", + error: + "Username can only contain letters, numbers, spaces, underscores, and [square brackets].", }; } diff --git a/src/core/worker/Worker.worker.ts b/src/core/worker/Worker.worker.ts index e309302b1..544d067c4 100644 --- a/src/core/worker/Worker.worker.ts +++ b/src/core/worker/Worker.worker.ts @@ -35,7 +35,7 @@ ctx.addEventListener("message", async (e: MessageEvent) => { message.gameID, message.gameConfig, message.clientID, - gameUpdate + gameUpdate, ).then((gr) => { sendMessage({ type: "initialized", @@ -72,7 +72,7 @@ ctx.addEventListener("message", async (e: MessageEvent) => { const actions = (await gameRunner).playerActions( message.playerID, message.x, - message.y + message.y, ); sendMessage({ type: "player_actions_result", diff --git a/src/core/worker/WorkerClient.ts b/src/core/worker/WorkerClient.ts index 843bf0ea2..6a739ddac 100644 --- a/src/core/worker/WorkerClient.ts +++ b/src/core/worker/WorkerClient.ts @@ -14,13 +14,13 @@ export class WorkerClient { private isInitialized = false; private messageHandlers: Map void>; private gameUpdateCallback?: ( - update: GameUpdateViewData | ErrorUpdate + update: GameUpdateViewData | ErrorUpdate, ) => void; constructor( private gameID: GameID, private gameConfig: GameConfig, - private clientID: ClientID + private clientID: ClientID, ) { this.worker = new Worker(new URL("./Worker.worker.ts", import.meta.url)); this.messageHandlers = new Map(); @@ -28,7 +28,7 @@ export class WorkerClient { // Set up global message handler this.worker.addEventListener( "message", - this.handleWorkerMessage.bind(this) + this.handleWorkerMessage.bind(this), ); } @@ -135,7 +135,7 @@ export class WorkerClient { playerInteraction( playerID: PlayerID, x: number, - y: number + y: number, ): Promise { return new Promise((resolve, reject) => { if (!this.isInitialized) { diff --git a/src/server/GameManager.ts b/src/server/GameManager.ts index 0e0c6d80e..49de68163 100644 --- a/src/server/GameManager.ts +++ b/src/server/GameManager.ts @@ -52,7 +52,7 @@ export class GameManager { disableBots: false, disableNPCs: false, creativeMode: false, - }) + }), ); return id; } @@ -60,7 +60,7 @@ export class GameManager { hasActiveGame(gameID: GameID): boolean { const game = this.games .filter( - (g) => g.phase() == GamePhase.Lobby || g.phase() == GamePhase.Active + (g) => g.phase() == GamePhase.Lobby || g.phase() == GamePhase.Active, ) .find((g) => g.id == gameID); return game != null; @@ -93,7 +93,7 @@ export class GameManager { disableBots: false, disableNPCs: false, creativeMode: false, - }) + }), ); } diff --git a/src/server/Server.ts b/src/server/Server.ts index 1931b2d31..a81464a0a 100644 --- a/src/server/Server.ts +++ b/src/server/Server.ts @@ -134,7 +134,7 @@ wss.on("connection", (ws, req) => { ws.on("message", (message: string) => { try { const clientMsg: ClientMessage = ClientMessageSchema.parse( - JSON.parse(message) + JSON.parse(message), ); if (clientMsg.type == "join") { const forwarded = req.headers["x-forwarded-for"]; @@ -147,7 +147,7 @@ wss.on("connection", (ws, req) => { const { isValid, error } = validateUsername(clientMsg.username); if (!isValid) { console.log( - `game ${clientMsg.gameID}, client ${clientMsg.clientID} received invalid username, ${error}` + `game ${clientMsg.gameID}, client ${clientMsg.clientID} received invalid username, ${error}`, ); return; } @@ -158,10 +158,10 @@ wss.on("connection", (ws, req) => { clientMsg.persistentID, ip, clientMsg.username, - ws + ws, ), clientMsg.gameID, - clientMsg.lastTurn + clientMsg.lastTurn, ); } if (clientMsg.type == "log") {