From 3fc140c5473890c7698cc8bc06946678e38a75bc Mon Sep 17 00:00:00 2001 From: RyanGrieb Date: Sat, 25 Nov 2023 10:44:20 -0600 Subject: [PATCH] Formatting: Improve general code design and format --- .prettierrc | 8 + client/src/Assets.ts | 6 +- client/src/Game.ts | 214 ++++++++------------ client/src/Index.ts | 14 +- client/src/Unit.ts | 64 ++---- client/src/city/City.ts | 46 ++--- client/src/map/GameMap.ts | 108 ++++------ client/src/map/HoveredTile.ts | 10 +- client/src/map/River.ts | 4 +- client/src/map/Tile.ts | 29 +-- client/src/network/Client.ts | 22 +- client/src/player/AbstractPlayer.ts | 2 +- client/src/player/ClientPlayer.ts | 244 ++++++++++------------- client/src/scene/Actor.ts | 33 ++- client/src/scene/ActorGroup.ts | 2 +- client/src/scene/Camera.ts | 27 +-- client/src/scene/Line.ts | 14 +- client/src/scene/Scene.ts | 23 +-- client/src/scene/SceneBackground.ts | 36 ++-- client/src/scene/type/InGameScene.ts | 51 +++-- client/src/scene/type/JoinGameScene.ts | 48 ++--- client/src/scene/type/LoadingScene.ts | 6 +- client/src/scene/type/LobbyScene.ts | 55 +++-- client/src/scene/type/MainMenuScene.ts | 33 ++- client/src/ui/Button.ts | 35 ++-- client/src/ui/CityDisplayInfo.ts | 125 +++++------- client/src/ui/Label.ts | 24 +-- client/src/ui/Listbox.ts | 27 +-- client/src/ui/RadioButton.ts | 10 +- client/src/ui/SelectCivilizationGroup.ts | 71 +++---- client/src/ui/StatusBar.ts | 109 ++++------ client/src/ui/Textbox.ts | 32 +-- client/src/ui/UnitDisplayInfo.ts | 31 ++- client/src/util/Numbers.ts | 6 +- client/src/util/Vector.ts | 24 +-- package.json | 3 +- server/src/Events.ts | 24 +-- server/src/Game.ts | 50 +++-- server/src/Player.ts | 14 +- server/src/Server.ts | 14 +- server/src/city/City.ts | 23 +-- server/src/map/GameMap.ts | 228 ++++++--------------- server/src/map/MapResources.ts | 26 +-- server/src/map/Tile.ts | 98 +++------ server/src/state/type/InGameState.ts | 205 +++++++++---------- server/src/state/type/LobbyState.ts | 68 ++++--- server/src/{ => unit}/Unit.ts | 107 +++++----- server/src/unit/UnitActions.ts | 41 ++++ 48 files changed, 1022 insertions(+), 1472 deletions(-) create mode 100644 .prettierrc rename server/src/{ => unit}/Unit.ts (77%) create mode 100644 server/src/unit/UnitActions.ts diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..0ef1de00 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "printWidth": 120, + "jsxSingleQuote": false, + "trailingComma": "none" +} \ No newline at end of file diff --git a/client/src/Assets.ts b/client/src/Assets.ts index 72266796..e8c98ba9 100644 --- a/client/src/Assets.ts +++ b/client/src/Assets.ts @@ -13,7 +13,7 @@ export enum GameImage { SPRITESHEET, RIVER, POPUP_BOX, - DEBUG, + DEBUG } export enum SpriteRegion { @@ -89,7 +89,7 @@ export enum SpriteRegion { FAITH_ICON = "2,13", TRADE_ICON = "5,14", SETTLE_ICON = "11,11", - BUILDING_PALACE = "5,18", + BUILDING_PALACE = "5,18" } export const assetList = [ @@ -102,5 +102,5 @@ export const assetList = [ require("../assets/images/ui_popup_box.png"), require("../assets/images/debug.png"), require("../assets/images/font.png"), - require("../assets/images/logo.png"), + require("../assets/images/logo.png") ]; diff --git a/client/src/Game.ts b/client/src/Game.ts index bc89d518..2e69f016 100644 --- a/client/src/Game.ts +++ b/client/src/Game.ts @@ -33,29 +33,28 @@ export interface GameOptions { } export class Game { - private static canvas: HTMLCanvasElement; - private static canvasContext: CanvasRenderingContext2D; - private static scenes: Map; - private static currentScene: Scene; - private static images = []; - private static countedFrames: number = 0; - private static lastTimeUpdate = Date.now(); - private static fps: number = 0; - private static actors: Actor[] = []; - private static lines: Line[] = []; - private static measureQueue: string[]; - private static mouseX: number; - private static mouseY: number; - private static runGameLoop: boolean; - private static wrappedTextCache: { [key: string]: [string, number, number] } = - {}; - private static resizeTimer: NodeJS.Timeout; - private static oldWidth: number; - private static oldHeight: number; - - private constructor() {} - - public static init(options: GameOptions, callback: () => void) { + private static gameInstance: Game; + + private canvas: HTMLCanvasElement; + private canvasContext: CanvasRenderingContext2D; + private scenes: Map; + private currentScene: Scene; + private images = []; + private countedFrames: number = 0; + private lastTimeUpdate = Date.now(); + private fps: number = 0; + private actors: Actor[] = []; + private lines: Line[] = []; + private measureQueue: string[]; + private mouseX: number; + private mouseY: number; + private runGameLoop: boolean; + private wrappedTextCache: { [key: string]: [string, number, number] } = {}; + private resizeTimer: NodeJS.Timeout; + private oldWidth: number; + private oldHeight: number; + + private constructor(options: GameOptions, assetsLoadedCallback: () => void) { this.scenes = new Map(); //Initialize canvas this.canvas = document.getElementById("canvas") as HTMLCanvasElement; @@ -74,7 +73,7 @@ export class Game { this.actors.forEach((actor) => { actor.call("mousemove", { x: event.clientX, - y: event.clientY, + y: event.clientY }); }); @@ -82,7 +81,7 @@ export class Game { this.currentScene.call("mousemove", { x: event.clientX, y: event.clientY, - button: event.button, + button: event.button }); } @@ -95,7 +94,7 @@ export class Game { actor.call("mousedown", { x: event.clientX, y: event.clientY, - button: event.button, + button: event.button }); }); @@ -103,7 +102,7 @@ export class Game { this.currentScene.call("mousedown", { x: event.clientX, y: event.clientY, - button: event.button, + button: event.button }); } }); @@ -113,7 +112,7 @@ export class Game { actor.call("mouseup", { x: event.clientX, y: event.clientY, - button: event.button, + button: event.button }); }); @@ -121,7 +120,7 @@ export class Game { this.currentScene.call("mouseup", { x: event.clientX, y: event.clientY, - button: event.button, + button: event.button }); } }); @@ -134,7 +133,7 @@ export class Game { if (this.currentScene) { this.currentScene.call("mouseleave", { x: event.clientX, - y: event.clientY, + y: event.clientY }); } }); @@ -148,7 +147,7 @@ export class Game { this.currentScene.call("wheel", { x: event.offsetX, y: event.offsetY, - deltaY: event.deltaY, + deltaY: event.deltaY }); } }); @@ -186,12 +185,7 @@ export class Game { this.currentScene.redraw(); } this.canvasContext.fillStyle = options.canvasColor ?? "white"; - this.canvasContext.fillRect( - 0, - 0, - this.canvas.width, - this.canvas.height - ); + this.canvasContext.fillRect(0, 0, this.canvas.width, this.canvas.height); this.canvasContext.font = "12px Times new Roman"; this.canvasContext.imageSmoothingEnabled = false; }, 300); @@ -210,7 +204,7 @@ export class Game { }); // Call the callback loop, now we can progress with adding actors,scenes,ect. - callback(); + assetsLoadedCallback(); }); // Initialize our global network events @@ -220,7 +214,7 @@ export class Game { callback: (data) => { this.setScene(data["scene"]); }, - globalEvent: true, + globalEvent: true }); NetworkEvents.on({ eventName: "messageBox", @@ -230,11 +224,19 @@ export class Game { const message = data["message"]; alert(message); }, - globalEvent: true, + globalEvent: true }); } - public static gameLoop() { + public static getInstance() { + return this.gameInstance; + } + + public static createInstance(options: GameOptions, assetsLoadedCallback: () => void) { + this.gameInstance = new Game(options, assetsLoadedCallback); + } + + public gameLoop() { if (!this.runGameLoop) return; this.canvasContext.fillRect(0, 0, this.canvas.width, this.canvas.height); @@ -251,10 +253,10 @@ export class Game { this.drawText( { text: "FPS: " + this.fps, - x: Game.getWidth() - 40, - y: Game.getHeight() - 12, + x: this.getWidth() - 40, + y: this.getHeight() - 12, color: "white", - font: "12px sans", + font: "12px sans" }, this.canvasContext ); @@ -265,7 +267,7 @@ export class Game { }); } - public static loadAssetPromise(assetList): Promise { + private loadAssetPromise(assetList): Promise { let imagesLoaded: number = 0; const resultPromise = new Promise((resolve, reject) => { @@ -287,12 +289,12 @@ export class Game { return resultPromise; } - public static addScene(sceneName: string, scene: Scene) { + public addScene(sceneName: string, scene: Scene) { this.scenes.set(sceneName, scene); scene.setName(sceneName); } - public static setScene(sceneName: string) { + public setScene(sceneName: string) { this.actors = []; this.wrappedTextCache = {}; @@ -306,32 +308,27 @@ export class Game { this.currentScene.onInitialize(); } - public static addActor(actor: Actor) { + public addActor(actor: Actor) { this.actors.push(actor); actor.onCreated(); } - public static addLine(line: Line) { + public addLine(line: Line) { this.lines.push(line); } - public static removeLine(line: Line) { + public removeLine(line: Line) { this.lines = this.lines.filter((element) => element !== line); } - public static removeActor(actor: Actor) { + public removeActor(actor: Actor) { this.actors = this.actors.filter((element) => element !== actor); actor.onDestroyed(); } - public static drawImageFromActor( - actor: Actor, - context: CanvasRenderingContext2D - ) { + public drawImageFromActor(actor: Actor, context: CanvasRenderingContext2D) { if (!actor.getImage()) { - console.log( - "Warning: Attempted to draw empty actor: " + actor.getWidth() - ); + console.log("Warning: Attempted to draw empty actor: " + actor.getWidth()); return; } @@ -340,26 +337,16 @@ export class Game { canvasContext.save(); // Only apply camera to the Game's main canvas context. - if ( - actor.isCameraApplied() && - this.currentScene.getCamera() && - canvasContext === this.canvasContext - ) { + if (actor.isCameraApplied() && this.currentScene.getCamera() && canvasContext === this.canvasContext) { const zoom = this.currentScene.getCamera().getZoomAmount(); const cameraX = this.currentScene.getCamera().getX(); const cameraY = this.currentScene.getCamera().getY(); canvasContext.setTransform(zoom, 0, 0, zoom, cameraX, cameraY); } - canvasContext.translate( - actor.getRotationOriginX(), - actor.getRotationOriginY() - ); + canvasContext.translate(actor.getRotationOriginX(), actor.getRotationOriginY()); canvasContext.rotate(actor.getRotation()); - canvasContext.translate( - -actor.getRotationOriginX(), - -actor.getRotationOriginY() - ); + canvasContext.translate(-actor.getRotationOriginX(), -actor.getRotationOriginY()); canvasContext.globalAlpha = actor.getTransparency(); @@ -380,13 +367,7 @@ export class Game { actor.getHeight() ); } else { - canvasContext.drawImage( - actor.getImage(), - actor.getX(), - actor.getY(), - actor.getWidth(), - actor.getHeight() - ); + canvasContext.drawImage(actor.getImage(), actor.getX(), actor.getY(), actor.getWidth(), actor.getHeight()); } canvasContext.globalAlpha = 1; @@ -394,7 +375,7 @@ export class Game { canvasContext.restore(); } - public static async waitUntilMeasureQueueIsEmpty(): Promise { + public async waitUntilMeasureQueueIsEmpty(): Promise { return new Promise((resolve) => { const interval = setInterval(() => { if (this.measureQueue.length < 1) { @@ -405,10 +386,7 @@ export class Game { }); } - public static async measureText( - text: string, - font: string - ): Promise<[number, number]> { + public async measureText(text: string, font: string): Promise<[number, number]> { await this.waitUntilMeasureQueueIsEmpty(); // Wait for other measurements to complete, then continue.. this.measureQueue.push(text); this.canvasContext.save(); @@ -417,8 +395,7 @@ export class Game { await document.fonts.ready; // Wait for the async function to complete, then measure text.s const metrics = this.canvasContext.measureText(text); - let height = - metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; + let height = metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent; this.canvasContext.restore(); //FIXME: This fails when we have a queue of the same text, support text & font simultaneously this.measureQueue = this.measureQueue.filter((element) => element !== text); @@ -429,11 +406,7 @@ export class Game { /** * Returns a wrapped text string and height of the wrapped text, and stores the wrapped text in a cache. */ - public static async getWrappedText( - text: string, - font: string, - maxWidth: number - ): Promise<[string, number, number]> { + public async getWrappedText(text: string, font: string, maxWidth: number): Promise<[string, number, number]> { let currentWidth = 0; // Check if we have the wrapped text in cache: @@ -460,19 +433,12 @@ export class Game { } //Store wrapped text in cache - this.wrappedTextCache[text] = [ - modifiedText, - wrappedHeight, - unwrappedWordHeight, - ]; + this.wrappedTextCache[text] = [modifiedText, wrappedHeight, unwrappedWordHeight]; return [modifiedText, wrappedHeight, unwrappedWordHeight]; } - public static drawText( - textOptions: TextOptions, - canvasContext: CanvasRenderingContext2D - ) { + public drawText(textOptions: TextOptions, canvasContext: CanvasRenderingContext2D) { //FIXME: Use cache for meausring text.. let text = textOptions.text; @@ -484,11 +450,7 @@ export class Game { canvasContext.textBaseline = "top"; // Only apply camera to the Game's main canvas context. (canvasContext === this.canvasContext) - if ( - textOptions.applyCamera && - this.currentScene.getCamera() && - canvasContext === this.canvasContext - ) { + if (textOptions.applyCamera && this.currentScene.getCamera() && canvasContext === this.canvasContext) { const zoom = this.currentScene.getCamera().getZoomAmount(); const cameraX = this.currentScene.getCamera().getX(); const cameraY = this.currentScene.getCamera().getY(); @@ -507,11 +469,7 @@ export class Game { if (textOptions.lineWidth > 0) { if (text.includes("\n")) { for (const [index, line] of text.split("\n").entries()) { - canvasContext.strokeText( - line, - xPos, - yPos + textOptions.height * index - ); + canvasContext.strokeText(line, xPos, yPos + textOptions.height * index); } } else { canvasContext.strokeText(text, xPos, yPos); @@ -529,7 +487,7 @@ export class Game { canvasContext.restore(); } - public static drawLine(line: Line, canvasContext: CanvasRenderingContext2D) { + public drawLine(line: Line, canvasContext: CanvasRenderingContext2D) { canvasContext.save(); // Only apply camera to the Game's main canvas context. @@ -558,14 +516,14 @@ export class Game { canvasContext.restore(); } - public static drawRect({ + public drawRect({ x, y, width, height, color, canvasContext, - fill, + fill }: { x: number; y: number; @@ -586,35 +544,35 @@ export class Game { canvasContext.restore(); } - public static getImage(gameImage: GameImage) { + public getImage(gameImage: GameImage) { return this.images[gameImage]; } - public static getHeight(): number { + public getHeight(): number { return this.canvas.height; } - public static getWidth(): number { + public getWidth(): number { return this.canvas.width; } - public static getOldHeight(): number { + public getOldHeight(): number { return this.oldHeight; } - public static getOldWidth(): number { + public getOldWidth(): number { return this.oldWidth; } - - public static getCanvasContext() { + + public getCanvasContext() { return this.canvasContext; } - public static getCanvas() { + public getCanvas() { return this.canvas; } - public static getCurrentScene() { + public getCurrentScene() { return this.currentScene; } @@ -622,29 +580,29 @@ export class Game { * Return the current scene & cast the class specified in the generic type. * @returns */ - public static getCurrentSceneAs(): T { + public getCurrentSceneAs(): T { return this.currentScene as T; } - public static getMouseX() { + public getMouseX() { return this.mouseX; } - public static getMouseY() { + public getMouseY() { return this.mouseY; } - public static getRelativeMouseX() { + public getRelativeMouseX() { return this.mouseX - (this.currentScene.getCamera()?.getX() ?? 0); } - public static getRelativeMouseY() { + public getRelativeMouseY() { return this.mouseY - (this.currentScene.getCamera()?.getY() ?? 0); } - public static toggleGameLoop() { + public toggleGameLoop() { this.runGameLoop = !this.runGameLoop; } - public static setCursor(type: string) { + public setCursor(type: string) { this.canvas.style.cursor = type; } } diff --git a/client/src/Index.ts b/client/src/Index.ts index 29d179fb..b027a232 100644 --- a/client/src/Index.ts +++ b/client/src/Index.ts @@ -6,11 +6,11 @@ import { LoadingScene } from "./scene/type/LoadingScene"; import { LobbyScene } from "./scene/type/LobbyScene"; import { MainMenuScene } from "./scene/type/MainMenuScene"; -Game.init({ assetList: assetList, canvasColor: "gray" }, () => { - Game.addScene("main_menu", new MainMenuScene()); - Game.addScene("join_game", new JoinGameScene()); - Game.addScene("lobby", new LobbyScene()); - Game.addScene("in_game", new InGameScene()); - Game.addScene("loading_scene", new LoadingScene()); - Game.setScene("main_menu"); +Game.createInstance({ assetList: assetList, canvasColor: "gray" }, () => { + Game.getInstance().addScene("main_menu", new MainMenuScene()); + Game.getInstance().addScene("join_game", new JoinGameScene()); + Game.getInstance().addScene("lobby", new LobbyScene()); + Game.getInstance().addScene("in_game", new InGameScene()); + Game.getInstance().addScene("loading_scene", new LoadingScene()); + Game.getInstance().setScene("main_menu"); }); diff --git a/client/src/Unit.ts b/client/src/Unit.ts index 9f08e419..6fe1604f 100644 --- a/client/src/Unit.ts +++ b/client/src/Unit.ts @@ -37,12 +37,7 @@ export class UnitAction { private requirements: string[]; // We assign these strings to client-side functions to check if there met. private icon: SpriteRegion; - public constructor( - actionName: string, - desc: string, - requirements: string[], - icon: SpriteRegion - ) { + public constructor(actionName: string, desc: string, requirements: string[], icon: SpriteRegion) { this.actionName = actionName; this.desc = desc; this.requirements = requirements; @@ -122,20 +117,20 @@ export class Unit extends ActorGroup { y: tile.getCenterPosition()[1] - 28 / 2, z: 2, width: 28, - height: 28, + height: 28 }); this.tile = tile; this.name = unitJSON["name"]; this.unitActor = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion[this.name.toUpperCase()], x: tile.getCenterPosition()[0] - 28 / 2, y: tile.getCenterPosition()[1] - 28 / 2, z: 2, width: 28, - height: 28, + height: 28 }); this.addActor(this.unitActor); @@ -148,9 +143,7 @@ export class Unit extends ActorGroup { this.queuedMovementTiles = []; for (const jsonTile of unitJSON["queuedTiles"]) { - this.queuedMovementTiles.push( - GameMap.getInstance().getTiles()[jsonTile["x"]][jsonTile["y"]] - ); + this.queuedMovementTiles.push(GameMap.getInstance().getTiles()[jsonTile["x"]][jsonTile["y"]]); } this.selectionActors = []; @@ -158,12 +151,7 @@ export class Unit extends ActorGroup { for (const actionJSON of unitJSON["actions"]) { this.actions.push( - new UnitAction( - actionJSON.name, - actionJSON.desc, - actionJSON.requirements, - SpriteRegion[actionJSON.icon] - ) + new UnitAction(actionJSON.name, actionJSON.desc, actionJSON.requirements, SpriteRegion[actionJSON.icon]) ); } @@ -173,10 +161,8 @@ export class Unit extends ActorGroup { eventName: "moveUnit", parentObject: this, callback: (data) => { - const unitTile = - GameMap.getInstance().getTiles()[data["unitX"]][data["unitY"]]; - const targetTile = - GameMap.getInstance().getTiles()[data["targetX"]][data["targetY"]]; + const unitTile = GameMap.getInstance().getTiles()[data["unitX"]][data["unitY"]]; + const targetTile = GameMap.getInstance().getTiles()[data["targetX"]][data["targetY"]]; if (this.tile !== unitTile || this.id !== data["id"]) { return; @@ -203,12 +189,11 @@ export class Unit extends ActorGroup { //console.log("Unit assigned a movement queue from server:"); for (const tileJSON of data["queuedTiles"] as []) { - const tile = - GameMap.getInstance().getTiles()[tileJSON["x"]][tileJSON["y"]]; + const tile = GameMap.getInstance().getTiles()[tileJSON["x"]][tileJSON["y"]]; this.queuedMovementTiles.push(tile); } } - }, + } }); NetworkEvents.on({ @@ -216,15 +201,14 @@ export class Unit extends ActorGroup { parentObject: this, callback: (data) => { this.availableMovement = this.defaultMoveDistance; - }, + } }); NetworkEvents.on({ eventName: "removeUnit", parentObject: this, callback: (data) => { - const unitTile = - GameMap.getInstance().getTiles()[data["unitX"]][data["unitY"]]; + const unitTile = GameMap.getInstance().getTiles()[data["unitX"]][data["unitY"]]; if (this.tile !== unitTile) { return; @@ -233,8 +217,8 @@ export class Unit extends ActorGroup { //FIXME: Tell client player to stop drawing lines. this.unselect(); this.tile.removeUnit(this); - Game.getCurrentScene().removeActor(this); - }, + Game.getInstance().getCurrentScene().removeActor(this); + } }); } @@ -276,7 +260,7 @@ export class Unit extends ActorGroup { public unselect() { this.selected = false; this.removeSelectionActors(); - Game.getCurrentScene().removeActor(this.unitDisplayInfo); + Game.getInstance().getCurrentScene().removeActor(this.unitDisplayInfo); } public select() { @@ -285,7 +269,7 @@ export class Unit extends ActorGroup { this.addSelectionActors(); this.unitDisplayInfo = new UnitDisplayInfo(this); - Game.getCurrentScene().addActor(this.unitDisplayInfo); + Game.getInstance().getCurrentScene().addActor(this.unitDisplayInfo); } public getQueuedMovementTiles() { @@ -328,16 +312,10 @@ export class Unit extends ActorGroup { */ public updatePosition(tile: Tile): void { // Ensure group-actor location is updated - super.setPosition( - tile.getCenterPosition()[0] - 28 / 2, - tile.getCenterPosition()[1] - 28 / 2 - ); + super.setPosition(tile.getCenterPosition()[0] - 28 / 2, tile.getCenterPosition()[1] - 28 / 2); // Update unit sub-actor location - this.unitActor.setPosition( - tile.getCenterPosition()[0] - 28 / 2, - tile.getCenterPosition()[1] - 28 / 2 - ); + this.unitActor.setPosition(tile.getCenterPosition()[0] - 28 / 2, tile.getCenterPosition()[1] - 28 / 2); } private removeSelectionActors() { @@ -348,19 +326,19 @@ export class Unit extends ActorGroup { GameMap.getInstance().removeOutline({ tile: this.tile, - cityOutline: false, + cityOutline: false }); } private addSelectionActors() { this.selectionActors.push( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.UNIT_SELECTION_TILE, x: this.getTile().getX(), y: this.getTile().getY(), width: 32, - height: 32, + height: 32 }) ); diff --git a/client/src/city/City.ts b/client/src/city/City.ts index 7120a86f..0b171b12 100644 --- a/client/src/city/City.ts +++ b/client/src/city/City.ts @@ -44,10 +44,8 @@ export class City extends ActorGroup { this.stats = new Map(); this.statsPresent = false; - this.innerBorderColor = - this.player.getCivilizationData()["inside_border_color"]; - this.outsideBorderColor = - this.player.getCivilizationData()["outside_border_color"]; + this.innerBorderColor = this.player.getCivilizationData()["inside_border_color"]; + this.outsideBorderColor = this.player.getCivilizationData()["outside_border_color"]; this.territoryOverlays = []; @@ -65,62 +63,52 @@ export class City extends ActorGroup { shadowBlur: 1, shadowColor: "black", lineWidth: 1, - z: 4, + z: 4 }); - if ( - this.player == Game.getCurrentSceneAs().getClientPlayer() - ) { + if (this.player == Game.getInstance().getCurrentSceneAs().getClientPlayer()) { this.nameLabel.setOnClick(() => { - Game.getCurrentSceneAs().toggleCityUI(this); + Game.getInstance().getCurrentSceneAs().toggleCityUI(this); }); } this.nameLabel.conformSize().then(() => { this.nameLabel.setPosition( - this.tile.getX() - - this.nameLabel.getWidth() / 2 + - this.tile.getWidth() / 2 + - 7, + this.tile.getX() - this.nameLabel.getWidth() / 2 + this.tile.getWidth() / 2 + 7, this.tile.getY() - this.nameLabel.getHeight() ); - Game.getCurrentScene().addActor(this.nameLabel); + Game.getInstance().getCurrentScene().addActor(this.nameLabel); this.civIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), - spriteRegion: - SpriteRegion[this.player.getCivilizationData()["icon_name"]], + image: Game.getInstance().getImage(GameImage.SPRITESHEET), + spriteRegion: SpriteRegion[this.player.getCivilizationData()["icon_name"]], x: this.nameLabel.getX() - 14, y: this.nameLabel.getY(), z: 4, width: 12, - height: 12, + height: 12 }); //this.addActor(this.civIcon); - Game.getCurrentScene().addActor(this.civIcon); + Game.getInstance().getCurrentScene().addActor(this.civIcon); }); for (const tile of this.territory) { const territoryOverlay = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.BLANK_TILE, x: tile.getX(), y: tile.getY(), width: 32, height: 32, - color: this.innerBorderColor, + color: this.innerBorderColor }); this.addActor(territoryOverlay); this.territoryOverlays.push(territoryOverlay); } - GameMap.getInstance().drawBorder( - this.territory, - this.outsideBorderColor, - 3 - ); + GameMap.getInstance().drawBorder(this.territory, this.outsideBorderColor, 3); NetworkEvents.on({ eventName: "addBuilding", @@ -128,7 +116,7 @@ export class City extends ActorGroup { callback: (data: any) => { const buildingData = data["building"]; this.buildings.push(new Buidling(buildingData)); - }, + } }); NetworkEvents.on({ @@ -143,7 +131,7 @@ export class City extends ActorGroup { } this.statsPresent = true; - }, + } }); } @@ -157,7 +145,7 @@ export class City extends ActorGroup { public onDestroyed(): void { super.onDestroyed(); - Game.getCurrentScene().removeActor(this.nameLabel); + Game.getInstance().getCurrentScene().removeActor(this.nameLabel); } public getTerritory() { diff --git a/client/src/map/GameMap.ts b/client/src/map/GameMap.ts index 137b77e9..b63f48ef 100644 --- a/client/src/map/GameMap.ts +++ b/client/src/map/GameMap.ts @@ -20,7 +20,7 @@ export class GameMap { [1, 0], [1, 1], [0, 1], - [-1, 0], + [-1, 0] ]; private evenEdgeAxis = [ [-1, -1], @@ -28,7 +28,7 @@ export class GameMap { [1, 0], [0, 1], [-1, 1], - [-1, 0], + [-1, 0] ]; private tiles: Tile[][]; @@ -66,8 +66,8 @@ export class GameMap { const city = this.getCityFromJSONData(data); city.getTile().setCity(city); // Assign the city variable inside the tile variable. // Add the city actor to the scene (borders, nametag) - Game.getCurrentScene().addActor(city); - }, + Game.getInstance().getCurrentScene().addActor(city); + } }); } @@ -161,7 +161,7 @@ export class GameMap { return 0; // fscoreA and fscoreB are equal } }, - initialValues: [startTile], + initialValues: [startTile] }); //cameFrom.fill(undefined, 0, totalNodes); @@ -178,25 +178,16 @@ export class GameMap { for (let neighborTile of currentTile.getAdjacentTiles()) { if (!neighborTile) continue; - let d = (current: Tile, neighbor: Tile) => - unit.getTileWeight(current, neighbor); + let d = (current: Tile, neighbor: Tile) => unit.getTileWeight(current, neighbor); - let tentativeGScore = - gScore[currentTile.getGridX()][currentTile.getGridY()] + - d(currentTile, neighborTile); + let tentativeGScore = gScore[currentTile.getGridX()][currentTile.getGridY()] + d(currentTile, neighborTile); //console.log(neighborTile.getNodeIndex()); //console.log(gScore[neighborTile.getNodeIndex()]); - if ( - tentativeGScore < - gScore[neighborTile.getGridX()][neighborTile.getGridY()] - ) { - cameFrom[neighborTile.getGridX()][neighborTile.getGridY()] = - currentTile; - gScore[neighborTile.getGridX()][neighborTile.getGridY()] = - tentativeGScore; - fScore[neighborTile.getGridX()][neighborTile.getGridY()] = - tentativeGScore + h(neighborTile); + if (tentativeGScore < gScore[neighborTile.getGridX()][neighborTile.getGridY()]) { + cameFrom[neighborTile.getGridX()][neighborTile.getGridY()] = currentTile; + gScore[neighborTile.getGridX()][neighborTile.getGridY()] = tentativeGScore; + fScore[neighborTile.getGridX()][neighborTile.getGridY()] = tentativeGScore + h(neighborTile); //if (!QueueUtils.valuePresent(openSet, neighborTile)) { openSet.queue(neighborTile); @@ -232,7 +223,7 @@ export class GameMap { } private requestMapFromServer() { - const scene = Game.getCurrentScene(); + const scene = Game.getInstance().getCurrentScene(); this.tiles = []; const baseLayerTiles = []; const riverActors = []; @@ -254,7 +245,7 @@ export class GameMap { //this.tiles[x][y] = undefined; } } - }, + } }); NetworkEvents.on({ @@ -310,16 +301,14 @@ export class GameMap { y: yPos, gridX: gridX, gridY: gridY, - movementCost: movementCost, + movementCost: movementCost }); this.tiles[gridX][gridY] = tile; baseLayerTiles.push(tile); if (tile.hasRiver()) { for (let numberedRiverSide of tile.getNumberedRiverSides()) { - riverActors.push( - new River({ tile: tile, side: numberedRiverSide }) - ); + riverActors.push(new River({ tile: tile, side: numberedRiverSide })); } } if (tileTypes.length > 1) { @@ -331,7 +320,7 @@ export class GameMap { y: yPosRelative, gridX: gridX, gridY: gridY, - movementCost: movementCost, + movementCost: movementCost }); topLayerTiles.push(topLayerTile); @@ -361,7 +350,7 @@ export class GameMap { x: 0, y: 0, width: 0, - height: 0, + height: 0 }); mapActors.push(placeholderActor); @@ -372,7 +361,7 @@ export class GameMap { actors: mapActors, spriteRegion: false, canvasWidth: canvasWidth, - canvasHeight: canvasHeight, + canvasHeight: canvasHeight }); mapChunk.setPosition(chunkX, chunkY); @@ -389,7 +378,7 @@ export class GameMap { const bottomLayerActors = [...baseLayerTiles, ...riverActors]; const bottomLayerActor = Actor.mergeActors({ actors: bottomLayerActors, - spriteRegion: false, + spriteRegion: false }); scene.addActor(bottomLayerActor); @@ -409,12 +398,9 @@ export class GameMap { // Now combine the base tile-type layer & the rest of the layers above.. for (let topLayerTile of this.topLayerTileActorList) { - const baseLayerTile = - this.tiles[topLayerTile.getGridX()][topLayerTile.getGridY()]; + const baseLayerTile = this.tiles[topLayerTile.getGridX()][topLayerTile.getGridY()]; - baseLayerTile.setTileTypes( - baseLayerTile.getTileTypes().concat(topLayerTile.getTileTypes()) - ); + baseLayerTile.setTileTypes(baseLayerTile.getTileTypes().concat(topLayerTile.getTileTypes())); } // Now create any cities that already exist on the map @@ -425,13 +411,13 @@ export class GameMap { WebsocketClient.sendMessage({ event: "requestCityStats", - cityName: city.getName(), + cityName: city.getName() }); } - Game.getCurrentScene().call("mapLoaded"); + Game.getInstance().getCurrentScene().call("mapLoaded"); } - }, + } }); } @@ -441,9 +427,7 @@ export class GameMap { //1. Get outter tiles // Condition: At least 1 adj tile is NOT in tiles list. const outerTiles: Tile[] = tiles.filter((tile) => { - return !tile - .getAdjacentTiles() - .every((adjTile) => tiles.includes(adjTile)); + return !tile.getAdjacentTiles().every((adjTile) => tiles.includes(adjTile)); }); //2. Apply outline to the outer tiles. We want to only apply outlines on the exterior @@ -468,7 +452,7 @@ export class GameMap { thickness: 1, color: color, cityOutline: true, - z: z, + z: z }); } } @@ -484,13 +468,11 @@ export class GameMap { for (const outline of [...outlines]) { if (outline.cityOutline && !options.cityOutline) continue; - Game.getCurrentScene().removeLine(outline.line); + Game.getInstance().getCurrentScene().removeLine(outline.line); outlines.splice(outlines.indexOf(outline), 1); // Remove outline from list (NO CITY OUTLINES EVER!!! UNLESS SPECIFIED) // Reset any outlines effected by this outline - for (const [_, effectedOutlines] of outline - .getEffectedOutlines() - .entries()) { + for (const [_, effectedOutlines] of outline.getEffectedOutlines().entries()) { for (const effectedOutline of effectedOutlines) { effectedOutline.line.setZValue(2); effectedOutline.line.setToOriginalPositions(); @@ -513,7 +495,7 @@ export class GameMap { thickness: 1, color: color, cityOutline: false, - z: 3, + z: 3 }); } @@ -540,7 +522,7 @@ export class GameMap { y1: tile.getVectors()[i].y, x2: tile.getVectors()[iNext].x, y2: tile.getVectors()[iNext].y, - z: options.z ?? 2, + z: options.z ?? 2 }); // Draw non-city outlines closer to the tile @@ -580,7 +562,7 @@ export class GameMap { } for (const outline of tileOutlines) { - Game.getCurrentScene().addLine(outline.line); + Game.getInstance().getCurrentScene().addLine(outline.line); } // Update our tileOutlines map @@ -603,7 +585,7 @@ export class GameMap { x1: shiftedTileVectors[0].x, y1: shiftedTileVectors[0].y, x2: shiftedTileVectors[1].x, - y2: shiftedTileVectors[1].y, + y2: shiftedTileVectors[1].y }); } @@ -636,7 +618,7 @@ export class GameMap { y: yPosRelative, gridX: tile.getGridX(), gridY: tile.getGridY(), - movementCost: tile.getMovementCost(), + movementCost: tile.getMovementCost() }); this.topLayerTileActorList.push(topLayerTile); // Not needed, but for continuity. @@ -654,12 +636,12 @@ export class GameMap { actors: chunkTileActors, spriteRegion: false, canvasWidth: canvasWidth, - canvasHeight: canvasHeight, + canvasHeight: canvasHeight }); updatedMapChunk.setPosition(chunk.getX(), chunk.getY()); - Game.getCurrentScene().addActor(updatedMapChunk); - Game.getCurrentScene().removeActor(chunk); + Game.getInstance().getCurrentScene().addActor(updatedMapChunk); + Game.getInstance().getCurrentScene().removeActor(chunk); // Update the chunk map this.topLayerMapChunks.delete(chunk); @@ -685,20 +667,12 @@ export class GameMap { let edgeX = x + edgeAxis[i][0]; let edgeY = y + edgeAxis[i][1]; - if ( - edgeX == -1 || - edgeY == -1 || - edgeX > this.mapWidth - 1 || - edgeY > this.mapHeight - 1 - ) { + if (edgeX == -1 || edgeY == -1 || edgeX > this.mapWidth - 1 || edgeY > this.mapHeight - 1) { this.tiles[x][y].setAdjacentTile(i, null); continue; } - this.tiles[x][y].setAdjacentTile( - i, - this.tiles[x + edgeAxis[i][0]][y + edgeAxis[i][1]] - ); + this.tiles[x][y].setAdjacentTile(i, this.tiles[x + edgeAxis[i][0]][y + edgeAxis[i][1]]); } } } @@ -714,15 +688,13 @@ export class GameMap { const cityName = data["cityName"]; const territory: Tile[] = []; for (const territoryJSON of data["territory"]) { - territory.push( - this.tiles[territoryJSON["tileX"]][territoryJSON["tileY"]] - ); + territory.push(this.tiles[territoryJSON["tileX"]][territoryJSON["tileY"]]); } const city = new City({ tile: tile, territory: territory, player: player, - name: cityName, + name: cityName }); return city; diff --git a/client/src/map/HoveredTile.ts b/client/src/map/HoveredTile.ts index 912533a2..02bc707f 100644 --- a/client/src/map/HoveredTile.ts +++ b/client/src/map/HoveredTile.ts @@ -15,7 +15,7 @@ export class HoveredTile extends Tile { tileTypes: ["hovered_tile"], width: 32, height: 32, - movementCost: 0, + movementCost: 0 }); } @@ -23,16 +23,16 @@ export class HoveredTile extends Tile { this.representedTile = representedTile; if (!representedTile) { - Game.getCurrentScene().call("tileHovered", { - tile: undefined, + Game.getInstance().getCurrentScene().call("tileHovered", { + tile: undefined }); this.setPosition(9999, 9999); return; } - Game.getCurrentScene().call("tileHovered", { - tile: representedTile, + Game.getInstance().getCurrentScene().call("tileHovered", { + tile: representedTile }); this.setPosition(representedTile.getX(), representedTile.getY()); diff --git a/client/src/map/River.ts b/client/src/map/River.ts index c05187d4..c8c0d3c0 100644 --- a/client/src/map/River.ts +++ b/client/src/map/River.ts @@ -45,10 +45,10 @@ export class River extends Actor { super({ x: x, y: y, - image: Game.getImage(GameImage.RIVER), + image: Game.getInstance().getImage(GameImage.RIVER), width: distance, height: 3, - transparency: 0.95, + transparency: 0.95 }); this.setRotation(rotation * (Math.PI / 180)); diff --git a/client/src/map/Tile.ts b/client/src/map/Tile.ts index 448ed150..6dd0f5f0 100644 --- a/client/src/map/Tile.ts +++ b/client/src/map/Tile.ts @@ -45,7 +45,7 @@ export class Tile extends Actor { z: options.z || 0, width: options.width ?? Tile.WIDTH, height: options.height ?? Tile.HEIGHT, - color: options.color, + color: options.color }); this.tileTypes = options.tileTypes; this.adjacentTiles = []; @@ -62,8 +62,7 @@ export class Tile extends Actor { public static gridDistance(tile1: Tile, tile2: Tile) { return Math.sqrt( - Math.pow(tile2.getGridX() - tile1.getGridX(), 2) + - Math.pow(tile2.getGridY() - tile1.getGridY(), 2) + Math.pow(tile2.getGridX() - tile1.getGridX(), 2) + Math.pow(tile2.getGridY() - tile1.getGridY(), 2) ); } @@ -170,12 +169,8 @@ export class Tile extends Actor { return this.gridY; } - public static async generateImageFromTileTypes( - tileTypes: string[] - ): Promise { - let canvas = document.getElementById( - "auxillary_canvas" - ) as HTMLCanvasElement; + public static async generateImageFromTileTypes(tileTypes: string[]): Promise { + let canvas = document.getElementById("auxillary_canvas") as HTMLCanvasElement; canvas.width = Tile.WIDTH; canvas.height = Tile.HEIGHT; @@ -184,23 +179,11 @@ export class Tile extends Actor { //Note: Tile sizes in spritesheet are always 32x32 regardless of anything else. for (let tileType of tileTypes) { - const spritesheetImage = Game.getImage(GameImage.SPRITESHEET); + const spritesheetImage = Game.getInstance().getImage(GameImage.SPRITESHEET); const spriteRegion = SpriteRegion[tileType.toUpperCase()]; const spriteX = parseInt(spriteRegion.split(",")[0]) * 32; const spriteY = parseInt(spriteRegion.split(",")[1]) * 32; - canvas - .getContext("2d") - .drawImage( - spritesheetImage, - spriteX, - spriteY, - 32, - 32, - 0, - 0, - Tile.WIDTH, - Tile.HEIGHT - ); + canvas.getContext("2d").drawImage(spritesheetImage, spriteX, spriteY, 32, 32, 0, 0, Tile.WIDTH, Tile.HEIGHT); } //canvas.getContext("2d").globalCompositeOperation = "saturation"; diff --git a/client/src/network/Client.ts b/client/src/network/Client.ts index 960c91b9..ce428874 100644 --- a/client/src/network/Client.ts +++ b/client/src/network/Client.ts @@ -3,11 +3,7 @@ export class CallbackData { public callbackFunction: Function; public globalEvent: boolean; // Not associated with the current scene. - constructor( - parentObject: object, - callbackFunctions: Function, - globalEvent: boolean - ) { + constructor(parentObject: object, callbackFunctions: Function, globalEvent: boolean) { this.parentObject = parentObject; this.callbackFunction = callbackFunctions; this.globalEvent = globalEvent; @@ -61,17 +57,13 @@ export class NetworkEvents { * Removes all associated callback functions that isn't a globalEvent */ public static clear() { - const globalEventCallbacks = this.getGlobalEventCallbacks( - this.storedEvents - ); + const globalEventCallbacks = this.getGlobalEventCallbacks(this.storedEvents); this.storedEvents = globalEventCallbacks; } public static removeCallbacksByParentObject(parentObj: object): void { this.storedEvents.forEach((callbackDataList, eventName) => { - const filteredDataList = callbackDataList.filter( - (callbackData) => callbackData.parentObject !== parentObj - ); + const filteredDataList = callbackDataList.filter((callbackData) => callbackData.parentObject !== parentObj); if (filteredDataList.length === 0) { this.storedEvents.delete(eventName); @@ -81,9 +73,7 @@ export class NetworkEvents { }); } - private static getGlobalEventCallbacks( - storedEvents: Map - ) { + private static getGlobalEventCallbacks(storedEvents: Map) { const globalEventCallbacks = new Map(); this.storedEvents.forEach((callbackDataList, eventName) => { @@ -113,9 +103,7 @@ export class NetworkEvents { //Get the list of stored callback functions or an empty list let callbackDataList: CallbackData[] = storedEvents.get(eventName) ?? []; // Append the to functions - callbackDataList.push( - new CallbackData(parentObject, callback, globalEvent) - ); + callbackDataList.push(new CallbackData(parentObject, callback, globalEvent)); storedEvents.set(eventName, callbackDataList); } } diff --git a/client/src/player/AbstractPlayer.ts b/client/src/player/AbstractPlayer.ts index 09492125..049393ee 100644 --- a/client/src/player/AbstractPlayer.ts +++ b/client/src/player/AbstractPlayer.ts @@ -11,7 +11,7 @@ export class AbstractPlayer { } public static getPlayerByName(name: string) { - const players = Game.getCurrentSceneAs().getPlayers(); + const players = Game.getInstance().getCurrentSceneAs().getPlayers(); for (const player of players) { if (player.getName() === name) { return player; diff --git a/client/src/player/ClientPlayer.ts b/client/src/player/ClientPlayer.ts index 890399b1..9ac03f60 100644 --- a/client/src/player/ClientPlayer.ts +++ b/client/src/player/ClientPlayer.ts @@ -27,88 +27,87 @@ export class ClientPlayer extends AbstractPlayer { this.movementLines = []; this.requestedNextTurn = playerJSON["requestedNextTurn"]; - Game.getCurrentScene().on("mapLoaded", () => { - this.hoveredTile = new HoveredTile(9999, 9999); - this.hoveredTile.loadImage().then(() => { - Game.getCurrentScene().addActor(this.hoveredTile); - this.updateHoveredTile(Game.getMouseX(), Game.getMouseY()); + Game.getInstance() + .getCurrentScene() + .on("mapLoaded", () => { + this.hoveredTile = new HoveredTile(9999, 9999); + this.hoveredTile.loadImage().then(() => { + Game.getInstance().getCurrentScene().addActor(this.hoveredTile); + this.updateHoveredTile(Game.getInstance().getMouseX(), Game.getInstance().getMouseY()); + }); }); - }); - Game.getCurrentScene().on("mousemove", (options) => { - const mouseX = options.x; - const mouseY = options.y; + Game.getInstance() + .getCurrentScene() + .on("mousemove", (options) => { + const mouseX = options.x; + const mouseY = options.y; - let oldHoveredTile = this.hoveredTile - ? this.hoveredTile.getRepresentedTile() - : undefined; + let oldHoveredTile = this.hoveredTile ? this.hoveredTile.getRepresentedTile() : undefined; - this.updateHoveredTile(mouseX, mouseY); + this.updateHoveredTile(mouseX, mouseY); - if ( - !this.selectedUnit || - oldHoveredTile === this.hoveredTile.getRepresentedTile() || - !this.rightMouseDrag - ) { - return; - } + if (!this.selectedUnit || oldHoveredTile === this.hoveredTile.getRepresentedTile() || !this.rightMouseDrag) { + return; + } - // Remove target-outline from previous hovered tile. - if (oldHoveredTile !== this.selectedUnit.getTile()) { - GameMap.getInstance().removeOutline({ - tile: oldHoveredTile, - cityOutline: false, - }); - } + // Remove target-outline from previous hovered tile. + if (oldHoveredTile !== this.selectedUnit.getTile()) { + GameMap.getInstance().removeOutline({ + tile: oldHoveredTile, + cityOutline: false + }); + } - if (!this.hoveredTile.getRepresentedTile()) { - this.clearMovementPath(); - return; - } + if (!this.hoveredTile.getRepresentedTile()) { + this.clearMovementPath(); + return; + } - // Draw movement lines to new target tile - const isQueuedMovement = this.drawMovementPath( - this.selectedUnit.getTile(), - this.hoveredTile.getRepresentedTile() - ); - - //Draw outline of final target tile - if (this.movementLines.length > 0) { - this.drawTargetTileOutline( - this.hoveredTile.getRepresentedTile(), - isQueuedMovement + // Draw movement lines to new target tile + const isQueuedMovement = this.drawMovementPath( + this.selectedUnit.getTile(), + this.hoveredTile.getRepresentedTile() ); - } - }); - Game.getCurrentScene().on("mousedown", (options) => { - if (options.button === 2) { - this.onMouseRightClick(); - } - }); + //Draw outline of final target tile + if (this.movementLines.length > 0) { + this.drawTargetTileOutline(this.hoveredTile.getRepresentedTile(), isQueuedMovement); + } + }); - Game.getCurrentScene().on("mouseup", (options) => { - if (Game.getCurrentScene().getCamera().isLocked() || !this.hoveredTile) { - return; - } + Game.getInstance() + .getCurrentScene() + .on("mousedown", (options) => { + if (options.button === 2) { + this.onMouseRightClick(); + } + }); + + Game.getInstance() + .getCurrentScene() + .on("mouseup", (options) => { + if (Game.getInstance().getCurrentScene().getCamera().isLocked() || !this.hoveredTile) { + return; + } - const clickedTile = this.hoveredTile.getRepresentedTile(); + const clickedTile = this.hoveredTile.getRepresentedTile(); - //left-click - if (options.button === 0) { - if (clickedTile && clickedTile.getUnits().length > 0) { - this.onClickedTileWithUnit(clickedTile); + //left-click + if (options.button === 0) { + if (clickedTile && clickedTile.getUnits().length > 0) { + this.onClickedTileWithUnit(clickedTile); + } } - } - //right-click - if (options.button === 2) { - this.rightMouseDrag = false; - if (clickedTile && this.selectedUnit) { - this.moveSelectedUnit(clickedTile); + //right-click + if (options.button === 2) { + this.rightMouseDrag = false; + if (clickedTile && this.selectedUnit) { + this.moveSelectedUnit(clickedTile); + } } - } - }); + }); NetworkEvents.on({ eventName: "zoomToLocation", @@ -118,8 +117,8 @@ export class ClientPlayer extends AbstractPlayer { const gridY = data["y"]; const tile = GameMap.getInstance().getTiles()[gridX][gridY]; const zoomAmount = data["zoomAmount"]; - Game.getCurrentSceneAs().focusOnTile(tile, zoomAmount); - }, + Game.getInstance().getCurrentSceneAs().focusOnTile(tile, zoomAmount); + } }); NetworkEvents.on({ @@ -134,10 +133,10 @@ export class ClientPlayer extends AbstractPlayer { GameMap.getInstance().removeOutline({ tile: this.hoveredTile.getRepresentedTile(), - cityOutline: false, + cityOutline: false }); } - }, + } }); NetworkEvents.on({ @@ -154,31 +153,29 @@ export class ClientPlayer extends AbstractPlayer { const movementPath: Tile[] = [this.selectedUnit.getTile()]; for (const tileLocation of data["queuedTiles"] as []) { - movementPath.push( - GameMap.getInstance().getTiles()[tileLocation["x"]][ - tileLocation["y"] - ] - ); + movementPath.push(GameMap.getInstance().getTiles()[tileLocation["x"]][tileLocation["y"]]); } this.drawMovementPathFromTiles(movementPath); } - }, - }); - - Game.getCurrentScene().on("toggleCityUI", () => { - if (this.selectedUnit) { - this.unselectUnit(); } }); + Game.getInstance() + .getCurrentScene() + .on("toggleCityUI", () => { + if (this.selectedUnit) { + this.unselectUnit(); + } + }); + NetworkEvents.on({ eventName: "newTurn", parentObject: this, callback: (data) => { this.unselectUnit(); this.clearMovementPath(); - }, + } }); } @@ -197,23 +194,17 @@ export class ClientPlayer extends AbstractPlayer { return; } - const isQueuedMovement = this.drawMovementPath( - this.selectedUnit.getTile(), - this.hoveredTile.getRepresentedTile() - ); + const isQueuedMovement = this.drawMovementPath(this.selectedUnit.getTile(), this.hoveredTile.getRepresentedTile()); // Remove queued target outline if it exists if (this.selectedUnit.hasMovementQueue()) { GameMap.getInstance().removeOutline({ tile: this.selectedUnit.getTargetQueuedTile(), - cityOutline: false, + cityOutline: false }); } - this.drawTargetTileOutline( - this.hoveredTile.getRepresentedTile(), - isQueuedMovement - ); + this.drawTargetTileOutline(this.hoveredTile.getRepresentedTile(), isQueuedMovement); } private moveSelectedUnit(targetTile: Tile) { @@ -223,13 +214,13 @@ export class ClientPlayer extends AbstractPlayer { unitY: this.selectedUnit.getTile().getGridY(), id: this.selectedUnit.getID(), targetX: targetTile.getGridX(), - targetY: targetTile.getGridY(), + targetY: targetTile.getGridY() }); // Remove target tile outline GameMap.getInstance().removeOutline({ tile: targetTile, - cityOutline: false, + cityOutline: false }); // Unselect unit before moving @@ -262,15 +253,9 @@ export class ClientPlayer extends AbstractPlayer { this.selectedUnit = unit; if (this.selectedUnit.hasMovementQueue()) { - const isQueuedMovement = this.drawMovementPathFromTiles([ - unit.getTile(), - ...unit.getQueuedMovementTiles(), - ]); - - this.drawTargetTileOutline( - this.selectedUnit.getTargetQueuedTile(), - isQueuedMovement - ); + const isQueuedMovement = this.drawMovementPathFromTiles([unit.getTile(), ...unit.getQueuedMovementTiles()]); + + this.drawTargetTileOutline(this.selectedUnit.getTargetQueuedTile(), isQueuedMovement); } } @@ -282,7 +267,7 @@ export class ClientPlayer extends AbstractPlayer { if (this.selectedUnit.hasMovementQueue()) { GameMap.getInstance().removeOutline({ tile: this.selectedUnit.getTargetQueuedTile(), - cityOutline: false, + cityOutline: false }); } } @@ -294,10 +279,10 @@ export class ClientPlayer extends AbstractPlayer { private updateHoveredTile(mouseX: number, mouseY: number) { if (!this.hoveredTile) return; - let zoom = Game.getCurrentScene().getCamera().getZoomAmount(); + let zoom = Game.getInstance().getCurrentScene().getCamera().getZoomAmount(); - let camX = -Game.getCurrentScene().getCamera().getX(); - let camY = -Game.getCurrentScene().getCamera().getY(); + let camX = -Game.getInstance().getCurrentScene().getCamera().getX(); + let camY = -Game.getInstance().getCurrentScene().getCamera().getY(); // Adjust mouse position base on where the camera is located mouseX += camX; @@ -330,26 +315,17 @@ export class ClientPlayer extends AbstractPlayer { mouseX < 15 || mouseX > GameMap.getInstance().getWidth() * 32 ) { - const adjBorderTiles = GameMap.getInstance().getAdjacentTiles( - gridX, - gridY - ); + const adjBorderTiles = GameMap.getInstance().getAdjacentTiles(gridX, gridY); const clampedBorderTile = - GameMap.getInstance().getTiles()[ - Numbers.clamp(gridX, 0, GameMap.getInstance().getWidth() - 1) - ][Numbers.clamp(gridY, 0, GameMap.getInstance().getHeight() - 1)]; + GameMap.getInstance().getTiles()[Numbers.clamp(gridX, 0, GameMap.getInstance().getWidth() - 1)][ + Numbers.clamp(gridY, 0, GameMap.getInstance().getHeight() - 1) + ]; adjBorderTiles.push(clampedBorderTile); // Also push clamped tile. let foundAdjBorderTile = false; for (const adjTile of adjBorderTiles) { if (!adjTile) continue; - if ( - Vector.isInsidePolygon( - adjTile.getVectors(), - mouseVector, - mouseExtremeVector - ) - ) { + if (Vector.isInsidePolygon(adjTile.getVectors(), mouseVector, mouseExtremeVector)) { accurateTile = adjTile; foundAdjBorderTile = true; } @@ -367,24 +343,12 @@ export class ClientPlayer extends AbstractPlayer { return; } - if ( - Vector.isInsidePolygon( - estimatedTile.getVectors(), - mouseVector, - mouseExtremeVector - ) - ) { + if (Vector.isInsidePolygon(estimatedTile.getVectors(), mouseVector, mouseExtremeVector)) { accurateTile = estimatedTile; } else { for (const adjTile of estimatedTile.getAdjacentTiles()) { if (!adjTile) continue; - if ( - Vector.isInsidePolygon( - adjTile.getVectors(), - mouseVector, - mouseExtremeVector - ) - ) { + if (Vector.isInsidePolygon(adjTile.getVectors(), mouseVector, mouseExtremeVector)) { accurateTile = adjTile; } } @@ -404,7 +368,7 @@ export class ClientPlayer extends AbstractPlayer { private clearMovementPath() { for (const line of this.movementLines) { - Game.getCurrentScene().removeLine(line); + Game.getInstance().getCurrentScene().removeLine(line); } this.movementLines = []; } @@ -419,11 +383,7 @@ export class ClientPlayer extends AbstractPlayer { //); //console.time("constructShortestPath()"); - const pathTiles = GameMap.getInstance().constructShortestPath( - this.selectedUnit, - startTile, - goalTile - ); + const pathTiles = GameMap.getInstance().constructShortestPath(this.selectedUnit, startTile, goalTile); return this.drawMovementPathFromTiles(pathTiles); } @@ -455,10 +415,10 @@ export class ClientPlayer extends AbstractPlayer { x1: tile1.getCenterPosition()[0], y1: tile1.getCenterPosition()[1], x2: tile2.getCenterPosition()[0], - y2: tile2.getCenterPosition()[1], + y2: tile2.getCenterPosition()[1] }); this.movementLines.push(line); - Game.getCurrentScene().addLine(line); + Game.getInstance().getCurrentScene().addLine(line); } return queuedPath; diff --git a/client/src/scene/Actor.ts b/client/src/scene/Actor.ts index 705519e1..ce07605d 100644 --- a/client/src/scene/Actor.ts +++ b/client/src/scene/Actor.ts @@ -45,10 +45,7 @@ export class Actor implements SceneObject { this.height = actorOptions.height; this.rotation = actorOptions.rotation ?? 0; this.transparency = actorOptions.transparency ?? 1; - this.cameraApplies = - actorOptions.cameraApplies === undefined - ? true - : actorOptions.cameraApplies; + this.cameraApplies = actorOptions.cameraApplies === undefined ? true : actorOptions.cameraApplies; this.on("mousemove", (options) => { if (this.insideActor(options.x, options.y)) { @@ -84,9 +81,7 @@ export class Actor implements SceneObject { public setColor(color: string) { this.color = color; - const canvas = document.getElementById( - "auxillary_canvas" - ) as HTMLCanvasElement; + const canvas = document.getElementById("auxillary_canvas") as HTMLCanvasElement; const context = canvas.getContext("2d"); // Set the canvas dimensions to match the image dimensions. @@ -101,7 +96,7 @@ export class Actor implements SceneObject { const spriteY = parseInt(this.getSpriteRegion().split(",")[1]) * 32; context.drawImage( - Game.getImage(GameImage.SPRITESHEET), + Game.getInstance().getImage(GameImage.SPRITESHEET), spriteX, spriteY, 32, @@ -141,17 +136,17 @@ export class Actor implements SceneObject { public draw(canvasContext: CanvasRenderingContext2D) { if (!this.image && this.color) { - Game.drawRect({ + Game.getInstance().drawRect({ x: this.x, y: this.y, width: this.width, height: this.height, color: this.color, fill: true, - canvasContext: canvasContext, + canvasContext: canvasContext }); } else if (this.image) { - Game.drawImageFromActor(this, canvasContext); + Game.getInstance().drawImageFromActor(this, canvasContext); } else { console.log("Warning: Nothing for actor can be drawn:" + this); } @@ -180,10 +175,10 @@ export class Actor implements SceneObject { public insideActor(x: number, y: number): boolean { //FIXME: The actor should have a scene parent object - if (this.cameraApplies && Game.getCurrentScene().getCamera()) { - const zoom = Game.getCurrentScene().getCamera().getZoomAmount(); - const cameraX = Game.getCurrentScene().getCamera().getX(); - const cameraY = Game.getCurrentScene().getCamera().getY(); + if (this.cameraApplies && Game.getInstance().getCurrentScene().getCamera()) { + const zoom = Game.getInstance().getCurrentScene().getCamera().getZoomAmount(); + const cameraX = Game.getInstance().getCurrentScene().getCamera().getX(); + const cameraY = Game.getInstance().getCurrentScene().getCamera().getY(); // Adjust the x and y coordinates relative to the camera x = (x - cameraX) / zoom; @@ -200,7 +195,7 @@ export class Actor implements SceneObject { public setImage(image: GameImage) { //TODO: Support HTMLImageElement - this.image = Game.getImage(image); + this.image = Game.getInstance().getImage(image); } public setSpriteRegion(spriteRegion: SpriteRegion) { @@ -273,9 +268,7 @@ export class Actor implements SceneObject { }): Actor { // Create dummy canvas to get pixel data of the actor sprite - let canvas = document.getElementById( - "auxillary_canvas" - ) as HTMLCanvasElement; + let canvas = document.getElementById("auxillary_canvas") as HTMLCanvasElement; let greatestXWidth = 0; // The width of the actor w/ the greatest x. let greatestYHeight = 0; // The height of the actor w/ the greatest y. let greatestX = 0; @@ -313,7 +306,7 @@ export class Actor implements SceneObject { y: options.actors[0].getY(), z: greatestZ, width: canvas.width, - height: canvas.height, + height: canvas.height }); return mergedActor; diff --git a/client/src/scene/ActorGroup.ts b/client/src/scene/ActorGroup.ts index 96ff0525..9c3e20d0 100644 --- a/client/src/scene/ActorGroup.ts +++ b/client/src/scene/ActorGroup.ts @@ -20,7 +20,7 @@ export class ActorGroup extends Actor { width: options.width, height: options.height, cameraApplies: options.cameraApplies, - z: options.z, + z: options.z }); this.actors = []; diff --git a/client/src/scene/Camera.ts b/client/src/scene/Camera.ts index afd23418..e8e7dbef 100644 --- a/client/src/scene/Camera.ts +++ b/client/src/scene/Camera.ts @@ -31,7 +31,7 @@ export class Camera { const newCamera = new Camera({ wasd_controls: camera.hasWASDControls(), mouse_controls: camera.hasMouseControls(), - arrow_controls: camera.hasArrowControls(), + arrow_controls: camera.hasArrowControls() }); newCamera.setPosition(camera.getX(), camera.getY()); @@ -55,7 +55,7 @@ export class Camera { this.lastMouseY = 0; this.locked = false; - const scene = Game.getCurrentScene(); + const scene = Game.getInstance().getCurrentScene(); scene.on("keydown", (options) => { if (this.keysHeld.includes(options.key) || this.locked) { return; @@ -95,18 +95,16 @@ export class Camera { } if (options.key == "=") { - scene.getCamera().zoom(Game.getWidth() / 2, Game.getHeight() / 2, 1.2); + scene.getCamera().zoom(Game.getInstance().getWidth() / 2, Game.getInstance().getHeight() / 2, 1.2); } if (options.key == "-") { - scene.getCamera().zoom(Game.getWidth() / 2, Game.getHeight() / 2, 0.8); + scene.getCamera().zoom(Game.getInstance().getWidth() / 2, Game.getInstance().getHeight() / 2, 0.8); } }); scene.on("keyup", (options) => { if (this.wasdControls) { - this.keysHeld = this.keysHeld.filter( - (element) => element !== options.key - ); // Remove key from held lits + this.keysHeld = this.keysHeld.filter((element) => element !== options.key); // Remove key from held lits if (options.key == "a" || options.key == "A") { scene.getCamera().addVel(-5, 0); @@ -124,9 +122,7 @@ export class Camera { } if (this.arrowControls) { - this.keysHeld = this.keysHeld.filter( - (element) => element !== options.key - ); // Remove key from held lits + this.keysHeld = this.keysHeld.filter((element) => element !== options.key); // Remove key from held lits if (options.key == "ArrowLeft") { scene.getCamera().addVel(-5, 0); @@ -157,12 +153,7 @@ export class Camera { scene.on("mousemove", (options) => { if (this.mouseHeld) { - scene - .getCamera() - .setPosition( - options.x - this.lastMouseX, - options.y - this.lastMouseY - ); + scene.getCamera().setPosition(options.x - this.lastMouseX, options.y - this.lastMouseY); } }); @@ -213,8 +204,8 @@ export class Camera { } public zoomToLocation(x: number, y: number, zoomAmount: number) { - this.setPosition(-x + Game.getWidth() / 2, -y + Game.getHeight() / 2); - this.zoom(Game.getWidth() / 2, Game.getHeight() / 2, zoomAmount, false); + this.setPosition(-x + Game.getInstance().getWidth() / 2, -y + Game.getInstance().getHeight() / 2); + this.zoom(Game.getInstance().getWidth() / 2, Game.getInstance().getHeight() / 2, zoomAmount, false); } public addVel(x: number, y: number) { diff --git a/client/src/scene/Line.ts b/client/src/scene/Line.ts index 8390f62f..4db646e4 100644 --- a/client/src/scene/Line.ts +++ b/client/src/scene/Line.ts @@ -35,10 +35,7 @@ export class Line implements SceneObject { this.transparency = options.transparency ?? 1; this.originalPositions = []; - this.originalPositions.push( - new Vector(this.x1, this.y1), - new Vector(this.x2, this.y2) - ); + this.originalPositions.push(new Vector(this.x1, this.y1), new Vector(this.x2, this.y2)); } public increaseDistance(amount: number) { @@ -57,12 +54,7 @@ export class Line implements SceneObject { this.y2 = this.y1 + unitVectorY * newDistance; } - public setPosition(options: { - x1: number; - y1: number; - x2: number; - y2: number; - }) { + public setPosition(options: { x1: number; y1: number; x2: number; y2: number }) { this.x1 = options.x1; this.y1 = options.y1; this.x2 = options.x2; @@ -102,7 +94,7 @@ export class Line implements SceneObject { } public draw(canvasContext: CanvasRenderingContext2D) { - Game.drawLine(this, canvasContext); + Game.getInstance().drawLine(this, canvasContext); } public getColor(): string { diff --git a/client/src/scene/Scene.ts b/client/src/scene/Scene.ts index b700a165..5b95b986 100644 --- a/client/src/scene/Scene.ts +++ b/client/src/scene/Scene.ts @@ -34,29 +34,27 @@ export abstract class Scene { public addLine(line: Line) { this.sceneObjects.push(line); this.sortSceneObjects(); - Game.addLine(line); + Game.getInstance().addLine(line); } public removeLine(line: Line) { this.sceneObjects = this.sceneObjects.filter((element) => element !== line); this.sortSceneObjects(); - Game.removeLine(line); + Game.getInstance().removeLine(line); } public addActor(actor: Actor) { this.sceneObjects.push(actor); this.sortSceneObjects(); - Game.addActor(actor); + Game.getInstance().addActor(actor); } public removeActor(actor: Actor) { if (!actor) return; - this.sceneObjects = this.sceneObjects.filter( - (element) => element !== actor - ); + this.sceneObjects = this.sceneObjects.filter((element) => element !== actor); this.sortSceneObjects(); - Game.removeActor(actor); + Game.getInstance().removeActor(actor); } public gameLoop() { @@ -65,7 +63,7 @@ export abstract class Scene { } this.sceneObjects.forEach((object: SceneObject) => { - object.draw(Game.getCanvasContext()); + object.draw(Game.getInstance().getCanvasContext()); }); } @@ -134,13 +132,10 @@ export abstract class Scene { public restoreCamera() { this.camera = Camera.fromCamera(this.oldCamera); // Shift the camera position to account for our new window size (We do this for alignment) - const wDiff = Game.getWidth() - Game.getOldWidth(); - const hDiff = Game.getHeight() - Game.getOldHeight(); + const wDiff = Game.getInstance().getWidth() - Game.getInstance().getOldWidth(); + const hDiff = Game.getInstance().getHeight() - Game.getInstance().getOldHeight(); - this.camera.setPosition( - this.camera.getX() + wDiff / 2, - this.camera.getY() + hDiff / 2 - ); + this.camera.setPosition(this.camera.getX() + wDiff / 2, this.camera.getY() + hDiff / 2); } public sortSceneObjects() { diff --git a/client/src/scene/SceneBackground.ts b/client/src/scene/SceneBackground.ts index a4f4b11d..4aa421c2 100644 --- a/client/src/scene/SceneBackground.ts +++ b/client/src/scene/SceneBackground.ts @@ -6,8 +6,8 @@ import { SpriteRegion } from "../Assets"; export class SceneBackground { public static generateOcean() { let tileActors: Actor[] = []; - for (let y = -1; y < (Game.getHeight() + 24) / 24; y++) { - for (let x = -1; x < (Game.getWidth() + 32) / 32; x++) { + for (let y = -1; y < (Game.getInstance().getHeight() + 24) / 24; y++) { + for (let x = -1; x < (Game.getInstance().getWidth() + 32) / 32; x++) { let yPos = y * 24; let xPos = x * 32; if (y % 2 != 0) { @@ -15,12 +15,12 @@ export class SceneBackground { } tileActors.push( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.OCEAN, x: xPos, y: yPos, width: 32, - height: 32, + height: 32 }) ); } @@ -29,13 +29,13 @@ export class SceneBackground { return Actor.mergeActors({ actors: tileActors, spriteRegion: true, - spriteSize: 32, + spriteSize: 32 }); } public static generateRandomGrassland(): Actor { let tileActors: Actor[] = []; - for (let y = -1; y < (Game.getHeight() + 24) / 24; y++) { - for (let x = -1; x < (Game.getWidth() + 32) / 32; x++) { + for (let y = -1; y < (Game.getInstance().getHeight() + 24) / 24; y++) { + for (let x = -1; x < (Game.getInstance().getWidth() + 32) / 32; x++) { let yPos = y * 24; let xPos = x * 32; if (y % 2 != 0) { @@ -43,15 +43,12 @@ export class SceneBackground { } tileActors.push( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), - spriteRegion: - Math.random() < 0.1 - ? SpriteRegion.GRASS_HILL - : SpriteRegion.GRASS, + image: Game.getInstance().getImage(GameImage.SPRITESHEET), + spriteRegion: Math.random() < 0.1 ? SpriteRegion.GRASS_HILL : SpriteRegion.GRASS, x: xPos, y: yPos, width: 32, - height: 32, + height: 32 }) ); } @@ -59,8 +56,8 @@ export class SceneBackground { // Sparse background with a random unit //const spriteRegionNum = Math.floor(Math.random() * 9); // Random sprite region b/w 0-2 - for (let y = -1; y < (Game.getHeight() + 24) / 24; y++) { - for (let x = -1; x < (Game.getWidth() + 32) / 32; x++) { + for (let y = -1; y < (Game.getInstance().getHeight() + 24) / 24; y++) { + for (let x = -1; x < (Game.getInstance().getWidth() + 32) / 32; x++) { let yPos = y * 24; let xPos = x * 32; if (y % 2 != 0) { @@ -70,13 +67,12 @@ export class SceneBackground { tileActors.push( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), - spriteRegion: - Object.values(SpriteRegion)[Math.floor(Math.random() * 9)], + image: Game.getInstance().getImage(GameImage.SPRITESHEET), + spriteRegion: Object.values(SpriteRegion)[Math.floor(Math.random() * 9)], x: xPos, y: yPos, width: 32, - height: 32, + height: 32 }) ); } @@ -85,7 +81,7 @@ export class SceneBackground { return Actor.mergeActors({ actors: tileActors, spriteRegion: true, - spriteSize: 32, + spriteSize: 32 }); } } diff --git a/client/src/scene/type/InGameScene.ts b/client/src/scene/type/InGameScene.ts index d028b551..d5475625 100644 --- a/client/src/scene/type/InGameScene.ts +++ b/client/src/scene/type/InGameScene.ts @@ -32,7 +32,7 @@ export class InGameScene extends Scene { const camera = new Camera({ wasd_controls: false, mouse_controls: true, - arrow_controls: true, + arrow_controls: true //initial_position: [1, 1], }); this.setCamera(camera); @@ -62,7 +62,7 @@ export class InGameScene extends Scene { this.players.push(new ExternalPlayer(playerJSON)); } } - }, + } }); GameMap.init(); @@ -74,12 +74,13 @@ export class InGameScene extends Scene { fontColor: "white", x: 0, y: 0, - z: 5, + z: 5 }); + this.tileInformationLabel.conformSize().then(() => { this.tileInformationLabel.setPosition( 2, - Game.getHeight() - this.tileInformationLabel.getHeight() - 6 + Game.getInstance().getHeight() - this.tileInformationLabel.getHeight() - 6 ); this.addActor(this.tileInformationLabel); }); @@ -88,11 +89,9 @@ export class InGameScene extends Scene { this.addActor(this.statusBar); this.nextTurnButton = new Button({ - text: this.clientPlayer.hasRequestedNextTurn() - ? "Waiting..." - : "Next Turn", - x: Game.getWidth() / 2 - 150 / 2, - y: Game.getHeight() - 44, + text: this.clientPlayer.hasRequestedNextTurn() ? "Waiting..." : "Next Turn", + x: Game.getInstance().getWidth() / 2 - 150 / 2, + y: Game.getInstance().getHeight() - 44, z: 6, width: 150, height: 42, @@ -103,32 +102,32 @@ export class InGameScene extends Scene { this.nextTurnButton.setText("Next Turn"); WebsocketClient.sendMessage({ event: "nextTurnRequest", - value: false, + value: false }); this.clientPlayer.setRequestedNextTurn(false); } else { WebsocketClient.sendMessage({ event: "nextTurnRequest", - value: true, + value: true }); this.nextTurnButton.setText("Waiting..."); this.clientPlayer.setRequestedNextTurn(true); } - }, + } }); this.addActor(this.nextTurnButton); this.closeCityDisplayButton = new Button({ text: "Return to Map", - x: Game.getWidth() / 2 - 275 / 2, - y: Game.getHeight() - 88, + x: Game.getInstance().getWidth() / 2 - 275 / 2, + y: Game.getInstance().getHeight() - 88, z: 5, width: 275, height: 52, fontColor: "white", onClicked: () => { this.toggleCityUI(); - }, + } }); this.on("tileHovered", (options) => { @@ -186,7 +185,7 @@ export class InGameScene extends Scene { callback: (data) => { this.nextTurnButton.setText("Next Turn"); this.clientPlayer.setRequestedNextTurn(false); - }, + } }); }); } @@ -203,7 +202,7 @@ export class InGameScene extends Scene { const x = tile.getCenterPosition()[0]; const y = tile.getCenterPosition()[1]; - Game.getCurrentScene().getCamera().zoomToLocation(x, y, zoomAmount); + Game.getInstance().getCurrentScene().getCamera().zoomToLocation(x, y, zoomAmount); } public toggleCityUI(city?: City) { @@ -262,11 +261,11 @@ export class InGameScene extends Scene { this.controlsLocked = true; this.escMenu = new ActorGroup({ - x: Game.getWidth() / 2 - 275 / 2, - y: Game.getHeight() / 2 - 275 / 2, + x: Game.getInstance().getWidth() / 2 - 275 / 2, + y: Game.getInstance().getHeight() / 2 - 275 / 2, width: 275, height: 275, - cameraApplies: false, + cameraApplies: false }); this.escMenu.addActor( @@ -275,7 +274,7 @@ export class InGameScene extends Scene { y: this.escMenu.getY(), width: this.escMenu.getWidth(), height: this.escMenu.getHeight(), - image: Game.getImage(GameImage.POPUP_BOX), + image: Game.getInstance().getImage(GameImage.POPUP_BOX) }) ); @@ -290,7 +289,7 @@ export class InGameScene extends Scene { onClicked: () => { this.removeActor(this.escMenu); this.escMenu = undefined; - }, + } }) ); @@ -304,7 +303,7 @@ export class InGameScene extends Scene { fontColor: "white", onClicked: () => { console.log("Toggle settings menu"); - }, + } }) ); @@ -316,7 +315,7 @@ export class InGameScene extends Scene { width: 242, height: 62, fontColor: "white", - onClicked: () => {}, + onClicked: () => {} }) ); @@ -330,9 +329,9 @@ export class InGameScene extends Scene { fontColor: "white", onClicked: () => { WebsocketClient.disconnect(); - Game.setScene("main_menu"); + Game.getInstance().setScene("main_menu"); this.firstLoad = true; - }, + } }) ); diff --git a/client/src/scene/type/JoinGameScene.ts b/client/src/scene/type/JoinGameScene.ts index 0933a960..5280ea70 100644 --- a/client/src/scene/type/JoinGameScene.ts +++ b/client/src/scene/type/JoinGameScene.ts @@ -36,20 +36,20 @@ export class JoinGameScene extends Scene { //this.addActor(serverList); const backgroundActor = new Actor({ - image: Game.getImage(GameImage.POPUP_BOX), - x: Game.getWidth() / 2 - 600 / 2, - y: Game.getHeight() / 2 - 500 / 2, + image: Game.getInstance().getImage(GameImage.POPUP_BOX), + x: Game.getInstance().getWidth() / 2 - 600 / 2, + y: Game.getInstance().getHeight() / 2 - 500 / 2, width: 600, - height: 500, + height: 500 }); this.addActor(backgroundActor); this.serverTextBox = new TextBox({ - x: Game.getWidth() / 2 - 400 / 2, - y: Game.getHeight() / 2 - 100, + x: Game.getInstance().getWidth() / 2 - 400 / 2, + y: Game.getInstance().getHeight() / 2 - 100, width: 400, - height: 50, + height: 50 }); this.serverTextBox.setSelected(true); @@ -60,11 +60,11 @@ export class JoinGameScene extends Scene { const infoLabel = new Label({ text: "Enter server code: (e.g. ED2FG)", font: "24px serif", - fontColor: "white", + fontColor: "white" }); infoLabel.conformSize().then(() => { infoLabel.setPosition( - Game.getWidth() / 2 - infoLabel.getWidth() / 2, + Game.getInstance().getWidth() / 2 - infoLabel.getWidth() / 2, this.serverTextBox.getY() - 30 ); this.addActor(infoLabel); @@ -73,8 +73,8 @@ export class JoinGameScene extends Scene { this.addActor( new Button({ text: "Join", - x: Game.getWidth() / 2 - 242 / 2, - y: Game.getHeight() / 2 - 25, + x: Game.getInstance().getWidth() / 2 - 242 / 2, + y: Game.getInstance().getHeight() / 2 - 25, width: 242, height: 62, fontColor: "white", @@ -82,39 +82,39 @@ export class JoinGameScene extends Scene { infoLabel.setText("Connecting...", true); infoLabel.conformSize().then(() => { infoLabel.setPosition( - Game.getWidth() / 2 - infoLabel.getWidth() / 2, + Game.getInstance().getWidth() / 2 - infoLabel.getWidth() / 2, this.serverTextBox.getY() - 30 ); }); WebsocketClient.init(this.serverTextBox.getText()); - }, + } }) ); this.addActor( new Button({ text: "Server List", - x: Game.getWidth() / 2 - 242 / 2 - 150, - y: Game.getHeight() / 2 + 150, + x: Game.getInstance().getWidth() / 2 - 242 / 2 - 150, + y: Game.getInstance().getHeight() / 2 + 150, width: 242, height: 62, fontColor: "white", - onClicked: () => {}, + onClicked: () => {} }) ); this.addActor( new Button({ text: "Back", - x: Game.getWidth() / 2 - 242 / 2 + 150, - y: Game.getHeight() / 2 + 150, + x: Game.getInstance().getWidth() / 2 - 242 / 2 + 150, + y: Game.getInstance().getHeight() / 2 + 150, width: 242, height: 62, fontColor: "white", onClicked: () => { - Game.setScene("main_menu"); - }, + Game.getInstance().setScene("main_menu"); + } }) ); @@ -125,11 +125,11 @@ export class JoinGameScene extends Scene { infoLabel.setText("Connection Failed.", true); infoLabel.conformSize().then(() => { infoLabel.setPosition( - Game.getWidth() / 2 - infoLabel.getWidth() / 2, + Game.getInstance().getWidth() / 2 - infoLabel.getWidth() / 2, this.serverTextBox.getY() - 30 ); }); - }, + } }); NetworkEvents.on({ @@ -141,12 +141,12 @@ export class JoinGameScene extends Scene { infoLabel.setText("Connection Failed: Game in progress."); infoLabel.conformSize().then(() => { infoLabel.setPosition( - Game.getWidth() / 2 - infoLabel.getWidth() / 2, + Game.getInstance().getWidth() / 2 - infoLabel.getWidth() / 2, this.serverTextBox.getY() - 30 ); }); } - }, + } }); } diff --git a/client/src/scene/type/LoadingScene.ts b/client/src/scene/type/LoadingScene.ts index f778696c..fe28e633 100644 --- a/client/src/scene/type/LoadingScene.ts +++ b/client/src/scene/type/LoadingScene.ts @@ -14,13 +14,13 @@ export class LoadingScene extends Scene { fontColor: "white", shadowColor: "black", lineWidth: 4, - shadowBlur: 20, + shadowBlur: 20 }); loadingLabel.conformSize().then(() => { loadingLabel.setPosition( - Game.getWidth() / 2 - loadingLabel.getWidth() / 2, - Game.getHeight() / 2 - loadingLabel.getHeight() / 2 + Game.getInstance().getWidth() / 2 - loadingLabel.getWidth() / 2, + Game.getInstance().getHeight() / 2 - loadingLabel.getHeight() / 2 ); }); diff --git a/client/src/scene/type/LobbyScene.ts b/client/src/scene/type/LobbyScene.ts index 525fd776..9420d154 100644 --- a/client/src/scene/type/LobbyScene.ts +++ b/client/src/scene/type/LobbyScene.ts @@ -16,13 +16,13 @@ export class LobbyScene extends Scene { this.addActor(SceneBackground.generateRandomGrassland()); const playerList = new ListBox({ - x: Game.getWidth() / 2 - 600 / 2, + x: Game.getInstance().getWidth() / 2 - 600 / 2, y: 35, width: 600, - height: Game.getHeight() - 275, + height: Game.getInstance().getHeight() - 275, rowHeight: 50, textFont: "20px serif", - fontColor: "white", + fontColor: "white" }); this.addActor(playerList); @@ -30,7 +30,7 @@ export class LobbyScene extends Scene { this.addActor( new Button({ text: "Choose Civilization", - x: Game.getWidth() / 2 - 242 / 2, + x: Game.getInstance().getWidth() / 2 - 242 / 2, y: playerList.getY() + playerList.getHeight() + 10, width: 242, height: 62, @@ -45,7 +45,7 @@ export class LobbyScene extends Scene { if (!this.selectCivGroup || !this.hasActor(this.selectCivGroup)) { this.selectCivGroup = new SelectCivilizationGroup( playerList.getX() + playerList.getWidth() / 2 - 432 / 2, - Game.getHeight() / 2 - 440 / 2, + Game.getInstance().getHeight() / 2 - 440 / 2, 432, 440 ); @@ -57,14 +57,14 @@ export class LobbyScene extends Scene { disableHoverWhen: () => { return this.hasActor(this.selectCivGroup); - }, + } }) ); this.addActor( new Button({ text: "Ready Up", - x: Game.getWidth() / 2 - 242 / 2, + x: Game.getInstance().getWidth() / 2 - 242 / 2, y: playerList.getY() + playerList.getHeight() + 75, width: 242, height: 62, @@ -79,14 +79,14 @@ export class LobbyScene extends Scene { disableHoverWhen: () => { return this.hasActor(this.selectCivGroup); - }, + } }) ); this.addActor( new Button({ text: "Back", - x: Game.getWidth() / 2 - 242 / 2, + x: Game.getInstance().getWidth() / 2 - 242 / 2, y: playerList.getY() + playerList.getHeight() + 140, width: 242, height: 62, @@ -96,13 +96,13 @@ export class LobbyScene extends Scene { return; } - Game.setScene("join_game"); + Game.getInstance().setScene("join_game"); //TODO: Disconnect player }, disableHoverWhen: () => { return this.hasActor(this.selectCivGroup); - }, + } }) ); @@ -111,17 +111,17 @@ export class LobbyScene extends Scene { NetworkEvents.on({ eventName: "playerJoin", parentObject: this, - callback: this.updatePlayerList, + callback: this.updatePlayerList }); NetworkEvents.on({ eventName: "playerQuit", parentObject: this, - callback: this.updatePlayerList, + callback: this.updatePlayerList }); NetworkEvents.on({ eventName: "playerLeave", parentObject: this, - callback: this.updatePlayerList, + callback: this.updatePlayerList }); NetworkEvents.on({ @@ -140,17 +140,17 @@ export class LobbyScene extends Scene { } const currentRow = playerList.addRow({ - text: playerName, + text: playerName }); currentRow.addActor( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: civIcon, x: currentRow.getX() + 8, y: currentRow.getY() - 32 / 2 + currentRow.getHeight() / 2, width: 32, - height: 32, + height: 32 }) ); @@ -158,12 +158,12 @@ export class LobbyScene extends Scene { // TODO: Indicate this row is the users player currentRow.addActor( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.STAR, x: currentRow.getX() + currentRow.getWidth() - 32 - 8, y: currentRow.getY() - 32 / 2 + currentRow.getHeight() / 2, width: 32, - height: 32, + height: 32 }) ); } @@ -171,13 +171,11 @@ export class LobbyScene extends Scene { currentRow.conformLabelSize().then(() => { currentRow.setLabelPosition( currentRow.getX() + 48, - currentRow.getY() + - currentRow.getHeight() / 2 - - currentRow.getLabel().getHeight() / 2 + currentRow.getY() + currentRow.getHeight() / 2 - currentRow.getLabel().getHeight() / 2 ); }); } - }, + } }); NetworkEvents.on({ @@ -194,22 +192,17 @@ export class LobbyScene extends Scene { continue; } - rowActor.setSpriteRegion( - SpriteRegion[data["civData"]["icon_name"]] - ); + rowActor.setSpriteRegion(SpriteRegion[data["civData"]["icon_name"]]); } } - }, + } }); } public onDestroyed(newScene: Scene) { const exitReceipt = super.onDestroyed(newScene); // Disconnect from the server if we go back, unless were going into the loading scene or reloading this scene. - if ( - newScene.getName() !== "loading_scene" && - newScene.getName() !== "lobby" - ) { + if (newScene.getName() !== "loading_scene" && newScene.getName() !== "lobby") { WebsocketClient.disconnect(); } diff --git a/client/src/scene/type/MainMenuScene.ts b/client/src/scene/type/MainMenuScene.ts index 0776c822..a2e4c115 100644 --- a/client/src/scene/type/MainMenuScene.ts +++ b/client/src/scene/type/MainMenuScene.ts @@ -15,13 +15,10 @@ export class MainMenuScene extends Scene { fontColor: "white", shadowColor: "black", lineWidth: 4, - shadowBlur: 20, + shadowBlur: 20 }); titleLabel.conformSize().then(() => { - titleLabel.setPosition( - Game.getWidth() / 2 - titleLabel.getWidth() / 2, - 135 - ); + titleLabel.setPosition(Game.getInstance().getWidth() / 2 - titleLabel.getWidth() / 2, 135); }); this.addActor(titleLabel); @@ -39,56 +36,56 @@ export class MainMenuScene extends Scene { this.addActor( new Button({ text: "Singleplayer", - x: Game.getWidth() / 2 - 242 / 2 - 250 / 2, - y: Game.getHeight() / 3 + 68, + x: Game.getInstance().getWidth() / 2 - 242 / 2 - 250 / 2, + y: Game.getInstance().getHeight() / 3 + 68, width: 242, height: 62, fontColor: "white", onClicked: () => { console.log("singleplayer scene"); - }, + } }) ); this.addActor( new Button({ text: "Host Game", - x: Game.getWidth() / 2 - 242 / 2 + 250 / 2, - y: Game.getHeight() / 3 + 68, + x: Game.getInstance().getWidth() / 2 - 242 / 2 + 250 / 2, + y: Game.getInstance().getHeight() / 3 + 68, width: 242, height: 62, fontColor: "white", onClicked: () => { console.log("singleplayer scene"); - }, + } }) ); this.addActor( new Button({ text: "Join Game", - x: Game.getWidth() / 2 - 242 / 2 + 250 / 2, - y: Game.getHeight() / 3 + 136, + x: Game.getInstance().getWidth() / 2 - 242 / 2 + 250 / 2, + y: Game.getInstance().getHeight() / 3 + 136, width: 242, height: 62, fontColor: "white", onClicked: () => { - Game.setScene("join_game"); - }, + Game.getInstance().setScene("join_game"); + } }) ); this.addActor( new Button({ text: "Options", - x: Game.getWidth() / 2 - 242 / 2 - 250 / 2, - y: Game.getHeight() / 3 + 136, + x: Game.getInstance().getWidth() / 2 - 242 / 2 - 250 / 2, + y: Game.getInstance().getHeight() / 3 + 136, width: 242, height: 62, fontColor: "white", onClicked: () => { console.log("options scene"); - }, + } }) ); } diff --git a/client/src/ui/Button.ts b/client/src/ui/Button.ts index a2128407..edaaf78d 100644 --- a/client/src/ui/Button.ts +++ b/client/src/ui/Button.ts @@ -49,7 +49,7 @@ export class Button extends ActorGroup { z: options.z, width: options.width, height: options.height, - cameraApplies: false, + cameraApplies: false }); this.icon = options.icon; @@ -61,18 +61,17 @@ export class Button extends ActorGroup { this.font = options.font ?? "24px serif"; this.fontColor = options.fontColor ?? "black"; this.buttonImage = options.buttonImage || GameImage.BUTTON; - this.buttonHoveredImage = - options.buttonHoveredImage || GameImage.BUTTON_HOVERED; + this.buttonHoveredImage = options.buttonHoveredImage || GameImage.BUTTON_HOVERED; this.iconOnly = options.iconOnly || false; this.disableHoverWhen = options.disableHoverWhen; if (!this.iconOnly) { this.buttonActor = new Actor({ - image: Game.getImage(this.buttonImage), + image: Game.getInstance().getImage(this.buttonImage), x: this.x, y: this.y, width: this.width, - height: this.height, + height: this.height }); this.addActor(this.buttonActor); } @@ -82,12 +81,12 @@ export class Button extends ActorGroup { const iconHeight = options.iconHeight || this.height; this.addActor( new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: this.icon, x: this.x + this.width / 2 - iconWidth / 2, y: this.y + this.height / 2 - iconHeight / 2, width: iconWidth, - height: iconHeight, + height: iconHeight }) ); } @@ -98,7 +97,7 @@ export class Button extends ActorGroup { return; } - Game.setCursor("pointer"); + Game.getInstance().setCursor("pointer"); } }); @@ -111,7 +110,7 @@ export class Button extends ActorGroup { this.buttonActor.setImage(this.buttonHoveredImage); } - Game.setCursor("pointer"); + Game.getInstance().setCursor("pointer"); this.mouseEnterCallbackFunction(); }); @@ -120,7 +119,7 @@ export class Button extends ActorGroup { this.buttonActor.setImage(this.buttonImage); } - Game.setCursor("default"); + Game.getInstance().setCursor("default"); this.mouseExitCallbackFunction(); }); @@ -136,22 +135,24 @@ export class Button extends ActorGroup { super.draw(canvasContext); //FIXME: Don't draw until we know textWidth & height. if (this.textWidth == -1 && this.textHeight == -1) { - Game.measureText(this.text, this.font).then(([textWidth, textHeight]) => { - this.textWidth = textWidth; - this.textHeight = textHeight; - }); + Game.getInstance() + .measureText(this.text, this.font) + .then(([textWidth, textHeight]) => { + this.textWidth = textWidth; + this.textHeight = textHeight; + }); return; // Don't render text before we know the height & width of the text } //TODO: Allow user to change where the text is drawn... if (this.text) { - Game.drawText( + Game.getInstance().drawText( { text: this.text, x: this.x + this.width / 2 - this.textWidth / 2, y: this.y + this.height / 2 - this.textHeight / 2, color: this.fontColor, - font: this.font, + font: this.font }, canvasContext ); @@ -165,7 +166,7 @@ export class Button extends ActorGroup { public onDestroyed(): void { super.onDestroyed(); if (this.mouseInside) { - Game.setCursor("default"); + Game.getInstance().setCursor("default"); } } diff --git a/client/src/ui/CityDisplayInfo.ts b/client/src/ui/CityDisplayInfo.ts index 1a3ca64e..7df86b1e 100644 --- a/client/src/ui/CityDisplayInfo.ts +++ b/client/src/ui/CityDisplayInfo.ts @@ -19,9 +19,9 @@ export class CityDisplayInfo extends ActorGroup { x: 0, y: 0, z: 6, - width: Game.getWidth(), - height: Game.getHeight(), - cameraApplies: false, + width: Game.getInstance().getWidth(), + height: Game.getInstance().getHeight(), + cameraApplies: false }); this.city = city; @@ -34,12 +34,12 @@ export class CityDisplayInfo extends ActorGroup { private initializeBuildingsWindow() { const listbox = new ListBox({ - x: Game.getWidth() - 275, + x: Game.getInstance().getWidth() - 275, y: 21, width: 275, - height: Game.getHeight() - 21, + height: Game.getInstance().getHeight() - 21, textFont: "20px serif", - fontColor: "white", + fontColor: "white" }); listbox.addCategory("Citizen Management"); @@ -51,7 +51,7 @@ export class CityDisplayInfo extends ActorGroup { width: 64, height: 64, getOtherRadioButtons: this.getCitizenMgmtRadioButtons.bind(this), - selected: true, + selected: true }); this.citizenMgmtRadioButtons.push(radioButton); @@ -61,7 +61,7 @@ export class CityDisplayInfo extends ActorGroup { textX: listbox.getNextRowPosition().x + 48, centerTextY: true, rowHeight: 50, - actorIcons: [radioButton], + actorIcons: [radioButton] }); const focuses = [ @@ -69,7 +69,7 @@ export class CityDisplayInfo extends ActorGroup { { name: "Production Focus", icon: SpriteRegion.PRODUCTION_ICON }, { name: "Gold Focus", icon: SpriteRegion.GOLD_ICON }, { name: "Science Focus", icon: SpriteRegion.SCIENCE_ICON }, - { name: "Culture Focus", icon: SpriteRegion.CULTURE_ICON }, + { name: "Culture Focus", icon: SpriteRegion.CULTURE_ICON } ]; for (const focus of focuses) { @@ -79,7 +79,7 @@ export class CityDisplayInfo extends ActorGroup { z: this.z, width: 64, height: 64, - getOtherRadioButtons: this.getCitizenMgmtRadioButtons.bind(this), + getOtherRadioButtons: this.getCitizenMgmtRadioButtons.bind(this) }); this.citizenMgmtRadioButtons.push(radioButton); @@ -92,16 +92,16 @@ export class CityDisplayInfo extends ActorGroup { actorIcons: [ radioButton, new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: focus.icon, x: listbox.getNextRowPosition().x + 38, y: listbox.getNextRowPosition().y + 50 / 2 - 32 / 2, z: this.z, width: 32, height: 32, - cameraApplies: false, - }), - ], + cameraApplies: false + }) + ] }); } @@ -126,18 +126,18 @@ export class CityDisplayInfo extends ActorGroup { const height = 300; this.addActor( new Actor({ - image: Game.getImage(GameImage.POPUP_BOX), + image: Game.getInstance().getImage(GameImage.POPUP_BOX), x: x, y: y, // (Height of status-bar) width: width, - height: height, + height: height }) ); const nameLabel = new Label({ text: this.city.getName(), font: "20px serif", - fontColor: "white", + fontColor: "white" }); nameLabel.conformSize().then(() => { nameLabel.setPosition(0 + 250 / 2 - nameLabel.getWidth() / 2, 30); @@ -145,12 +145,12 @@ export class CityDisplayInfo extends ActorGroup { }); const populationIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.POPULATION_ICON, x: 6, y: 52, width: 32, - height: 32, + height: 32 }); this.addActor(populationIcon); @@ -160,32 +160,29 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "white", x: populationIcon.getX() + populationIcon.getWidth(), - y: populationIcon.getY() + 8, + y: populationIcon.getY() + 8 }) ); const populationLabel = new Label({ text: this.city.getStat("population").toString(), font: "20px serif", - fontColor: "white", + fontColor: "white" }); populationLabel.conformSize().then(() => { - populationLabel.setPosition( - width - populationLabel.getWidth() - 10, - populationIcon.getY() + 8 - ); + populationLabel.setPosition(width - populationLabel.getWidth() - 10, populationIcon.getY() + 8); this.addActor(populationLabel); }); this.statLabels.set("population", populationLabel); const moraleIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.MORALE_ICON, x: 6, y: populationIcon.getY() + 32, width: 32, - height: 32, + height: 32 }); this.addActor(moraleIcon); @@ -195,32 +192,29 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "orange", x: moraleIcon.getX() + moraleIcon.getWidth(), - y: moraleIcon.getY() + 8, + y: moraleIcon.getY() + 8 }) ); const moraleLabel = new Label({ text: this.city.getStat("morale").toString(), font: "20px serif", - fontColor: "white", + fontColor: "white" }); moraleLabel.conformSize().then(() => { - moraleLabel.setPosition( - width - moraleLabel.getWidth() - 10, - moraleIcon.getY() + 8 - ); + moraleLabel.setPosition(width - moraleLabel.getWidth() - 10, moraleIcon.getY() + 8); this.addActor(moraleLabel); }); this.statLabels.set("morale", moraleLabel); const foodIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.FOOD_ICON, x: 6, y: moraleIcon.getY() + 32, width: 32, - height: 32, + height: 32 }); this.addActor(foodIcon); @@ -230,32 +224,29 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "lime", x: foodIcon.getX() + foodIcon.getWidth(), - y: foodIcon.getY() + 8, + y: foodIcon.getY() + 8 }) ); const foodLabel = new Label({ text: Strings.convertToStatUnit(this.city.getStat("food")), font: "20px serif", - fontColor: "white", + fontColor: "white" }); foodLabel.conformSize().then(() => { - foodLabel.setPosition( - width - foodLabel.getWidth() - 10, - foodIcon.getY() + 8 - ); + foodLabel.setPosition(width - foodLabel.getWidth() - 10, foodIcon.getY() + 8); this.addActor(foodLabel); }); this.statLabels.set("food", foodLabel); const productionIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.PRODUCTION_ICON, x: 6, y: foodIcon.getY() + 32, width: 32, - height: 32, + height: 32 }); this.addActor(productionIcon); @@ -265,32 +256,29 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "rgb(220,162,29)", x: productionIcon.getX() + productionIcon.getWidth(), - y: productionIcon.getY() + 8, + y: productionIcon.getY() + 8 }) ); const productionLabel = new Label({ text: Strings.convertToStatUnit(this.city.getStat("production")), font: "20px serif", - fontColor: "white", + fontColor: "white" }); productionLabel.conformSize().then(() => { - productionLabel.setPosition( - width - productionLabel.getWidth() - 10, - productionIcon.getY() + 8 - ); + productionLabel.setPosition(width - productionLabel.getWidth() - 10, productionIcon.getY() + 8); this.addActor(productionLabel); }); this.statLabels.set("production", productionLabel); const goldIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.GOLD_ICON, x: 6, y: productionIcon.getY() + 32, width: 32, - height: 32, + height: 32 }); this.addActor(goldIcon); @@ -300,32 +288,29 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "gold", x: goldIcon.getX() + goldIcon.getWidth(), - y: goldIcon.getY() + 8, + y: goldIcon.getY() + 8 }) ); const goldLabel = new Label({ text: Strings.convertToStatUnit(this.city.getStat("gold")), font: "20px serif", - fontColor: "white", + fontColor: "white" }); goldLabel.conformSize().then(() => { - goldLabel.setPosition( - width - goldLabel.getWidth() - 10, - goldIcon.getY() + 8 - ); + goldLabel.setPosition(width - goldLabel.getWidth() - 10, goldIcon.getY() + 8); this.addActor(goldLabel); }); this.statLabels.set("gold", goldLabel); const scienceIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.SCIENCE_ICON, x: 6, y: goldIcon.getY() + 32, width: 32, - height: 32, + height: 32 }); this.addActor(scienceIcon); @@ -335,32 +320,29 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "aqua", x: scienceIcon.getX() + scienceIcon.getWidth(), - y: scienceIcon.getY() + 8, + y: scienceIcon.getY() + 8 }) ); const scienceLabel = new Label({ text: Strings.convertToStatUnit(this.city.getStat("science")), font: "20px serif", - fontColor: "white", + fontColor: "white" }); scienceLabel.conformSize().then(() => { - scienceLabel.setPosition( - width - scienceLabel.getWidth() - 10, - scienceIcon.getY() + 8 - ); + scienceLabel.setPosition(width - scienceLabel.getWidth() - 10, scienceIcon.getY() + 8); this.addActor(scienceLabel); }); this.statLabels.set("science", scienceLabel); const cultureIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.CULTURE_ICON, x: 6, y: scienceIcon.getY() + 32, width: 32, - height: 32, + height: 32 }); this.addActor(cultureIcon); @@ -370,20 +352,17 @@ export class CityDisplayInfo extends ActorGroup { font: "20px serif", fontColor: "rgb(207, 159, 255)", x: cultureIcon.getX() + cultureIcon.getWidth(), - y: cultureIcon.getY() + 8, + y: cultureIcon.getY() + 8 }) ); const cultureLabel = new Label({ text: Strings.convertToStatUnit(this.city.getStat("culture")), font: "20px serif", - fontColor: "white", + fontColor: "white" }); cultureLabel.conformSize().then(() => { - cultureLabel.setPosition( - width - cultureLabel.getWidth() - 10, - cultureIcon.getY() + 8 - ); + cultureLabel.setPosition(width - cultureLabel.getWidth() - 10, cultureIcon.getY() + 8); this.addActor(cultureLabel); }); diff --git a/client/src/ui/Label.ts b/client/src/ui/Label.ts index 92c8c204..54071f75 100644 --- a/client/src/ui/Label.ts +++ b/client/src/ui/Label.ts @@ -38,7 +38,7 @@ export class Label extends Actor { cameraApplies: options.cameraApplies || false, width: 0, height: 0, - transparency: options.transparency, + transparency: options.transparency }); this.text = options.text; @@ -64,16 +64,16 @@ export class Label extends Actor { // Change cursor to pointer when mouse is over label this.on("mousemove", () => { if (this.mouseInside) { - Game.setCursor("pointer"); + Game.getInstance().setCursor("pointer"); } }); this.on("mouse_enter", () => { - Game.setCursor("pointer"); + Game.getInstance().setCursor("pointer"); }); this.on("mouse_exit", () => { - Game.setCursor("default"); + Game.getInstance().setCursor("default"); }); } } @@ -89,7 +89,7 @@ export class Label extends Actor { text = this.oldText; } - Game.drawText( + Game.getInstance().drawText( { text: text, x: this.x, @@ -102,7 +102,7 @@ export class Label extends Actor { lineWidth: this.lineWidth, applyCamera: this.cameraApplies, transparency: this.transparency, - maxWidth: this.maxWidth, + maxWidth: this.maxWidth }, canvasContext ); @@ -113,17 +113,17 @@ export class Label extends Actor { */ public async conformSize() { if (this.maxWidth) { - const [wrappedText, wrappedHeight, unwrappedWordHeight] = - await Game.getWrappedText(this.text, this.font, this.maxWidth); + const [wrappedText, wrappedHeight, unwrappedWordHeight] = await Game.getInstance().getWrappedText( + this.text, + this.font, + this.maxWidth + ); this.wrappedText = wrappedText; this.width = this.maxWidth; this.height = wrappedHeight; this.unwrappedWordHeight = unwrappedWordHeight; } else { - const [textWidth, textHeight] = await Game.measureText( - this.text, - this.font - ); + const [textWidth, textHeight] = await Game.getInstance().measureText(this.text, this.font); this.width = textWidth; this.height = textHeight; } diff --git a/client/src/ui/Listbox.ts b/client/src/ui/Listbox.ts index b120f061..63a45f08 100644 --- a/client/src/ui/Listbox.ts +++ b/client/src/ui/Listbox.ts @@ -29,7 +29,7 @@ class Row extends ActorGroup { z: options.z, width: options.width, height: options.height, - cameraApplies: false, + cameraApplies: false }); this.addActor( @@ -38,7 +38,7 @@ class Row extends ActorGroup { y: this.y, width: this.width, height: this.height, - color: options.color, + color: options.color }) ); @@ -47,7 +47,7 @@ class Row extends ActorGroup { fontColor: options.fontColor, font: options.font, x: options.textX ?? this.x, - y: options.textY ?? this.y, + y: options.textY ?? this.y }); this.label = label; @@ -113,7 +113,7 @@ export class ListBox extends ActorGroup { y: this.y, width: this.width, height: this.height, - color: "black", + color: "black" }) ); } @@ -130,17 +130,13 @@ export class ListBox extends ActorGroup { color: this.rows.length % 2 == 0 ? "#9e9e9e" : " #bbbbbb", font: this.textFont, fontColor: this.fontColor, - text: name, + text: name }); row.conformLabelSize().then(() => { row.setLabelPosition( - row.getLabel().getX() + - row.getWidth() / 2 - - row.getLabel().getWidth() / 2, - row.getLabel().getY() + - row.getHeight() / 2 - - row.getLabel().getHeight() / 2 + row.getLabel().getX() + row.getWidth() / 2 - row.getLabel().getWidth() / 2, + row.getLabel().getY() + row.getHeight() / 2 - row.getLabel().getHeight() / 2 ); }); @@ -165,12 +161,11 @@ export class ListBox extends ActorGroup { text: options.text, width: this.width, height: options.rowHeight ?? this.rowHeight, - color: - options.color ?? this.rows.length % 2 == 0 ? "#9e9e9e" : " #bbbbbb", + color: options.color ?? this.rows.length % 2 == 0 ? "#9e9e9e" : " #bbbbbb", font: this.textFont, fontColor: this.fontColor, textX: options.textX, - textY: options.textY, + textY: options.textY }); for (const actionIcon of options.actorIcons ?? []) { @@ -182,9 +177,7 @@ export class ListBox extends ActorGroup { row.conformLabelSize().then(() => { row.setLabelPosition( row.getLabel().getX(), - row.getLabel().getY() + - row.getHeight() / 2 - - row.getLabel().getHeight() / 2 + row.getLabel().getY() + row.getHeight() / 2 - row.getLabel().getHeight() / 2 ); }); } diff --git a/client/src/ui/RadioButton.ts b/client/src/ui/RadioButton.ts index d740f0fe..f5a75ad0 100644 --- a/client/src/ui/RadioButton.ts +++ b/client/src/ui/RadioButton.ts @@ -18,14 +18,14 @@ export class RadioButton extends Actor { constructor(options: RadioButtonOptions) { super({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.RADIO_BUTTON_UNSELECTED, x: options.x, y: options.y, z: options.z, width: options.width, height: options.height, - cameraApplies: false, + cameraApplies: false }); this.selected = options.selected ?? false; @@ -37,16 +37,16 @@ export class RadioButton extends Actor { this.on("mousemove", () => { if (this.mouseInside) { - Game.setCursor("pointer"); + Game.getInstance().setCursor("pointer"); } }); this.on("mouse_enter", () => { - Game.setCursor("pointer"); + Game.getInstance().setCursor("pointer"); }); this.on("mouse_exit", () => { - Game.setCursor("default"); + Game.getInstance().setCursor("default"); }); this.on("clicked", () => { diff --git a/client/src/ui/SelectCivilizationGroup.ts b/client/src/ui/SelectCivilizationGroup.ts index 4d99b26e..a970831e 100644 --- a/client/src/ui/SelectCivilizationGroup.ts +++ b/client/src/ui/SelectCivilizationGroup.ts @@ -16,7 +16,7 @@ export class SelectCivilizationGroup extends ActorGroup { x: x, y: y, width: width, - height: height, + height: height }); this.selectCivActors = []; @@ -24,11 +24,11 @@ export class SelectCivilizationGroup extends ActorGroup { this.addActor( new Actor({ - image: Game.getImage(GameImage.POPUP_BOX), + image: Game.getInstance().getImage(GameImage.POPUP_BOX), x: this.x, y: this.y, width: this.width, - height: this.height, + height: this.height }) ); @@ -63,19 +63,19 @@ export class SelectCivilizationGroup extends ActorGroup { onClicked: () => { WebsocketClient.sendMessage({ event: "civInfo", - name: civJSON["name"], + name: civJSON["name"] }); }, onMouseEnter: () => { console.log("Mouse enter"); - }, + } }); this.selectCivActors.push(selectCivButton); this.addActor(selectCivButton); xOffsset++; } - }, + } }); NetworkEvents.on({ @@ -83,15 +83,15 @@ export class SelectCivilizationGroup extends ActorGroup { parentObject: this, callback: (data) => { this.displayCivInformation(data); - }, + } }); NetworkEvents.on({ eventName: "selectCiv", parentObject: this, callback: () => { - Game.getCurrentScene().removeActor(this); - }, + Game.getInstance().getCurrentScene().removeActor(this); + } }); } @@ -106,7 +106,7 @@ export class SelectCivilizationGroup extends ActorGroup { this.titleLabel = new Label({ text: "Select a Civilization", font: "20px serif", - fontColor: "white", + fontColor: "white" }); this.addActor(this.titleLabel); } else { @@ -114,10 +114,7 @@ export class SelectCivilizationGroup extends ActorGroup { } this.titleLabel.conformSize().then(() => { - this.titleLabel.setPosition( - this.x + this.width / 2 - this.titleLabel.getWidth() / 2, - this.y + 12 - ); + this.titleLabel.setPosition(this.x + this.width / 2 - this.titleLabel.getWidth() / 2, this.y + 12); }); const closeButton = new Button({ @@ -128,8 +125,8 @@ export class SelectCivilizationGroup extends ActorGroup { height: 50, fontColor: "white", onClicked: () => { - Game.getCurrentScene().removeActor(this); - }, + Game.getInstance().getCurrentScene().removeActor(this); + } }); this.selectCivActors.push(closeButton); @@ -142,10 +139,7 @@ export class SelectCivilizationGroup extends ActorGroup { // Rename title label: this.titleLabel.setText(data["name"]); this.titleLabel.conformSize().then(() => { - this.titleLabel.setPosition( - this.x + this.width / 2 - this.titleLabel.getWidth() / 2, - this.y + 12 - ); + this.titleLabel.setPosition(this.x + this.width / 2 - this.titleLabel.getWidth() / 2, this.y + 12); }); // Remove select civ actors: @@ -155,12 +149,12 @@ export class SelectCivilizationGroup extends ActorGroup { // Display civ information: const civIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion[data["icon_name"]], x: this.x + this.width / 2 - 32 / 2, y: this.y + 40, width: 32, - height: 32, + height: 32 }); this.addActor(civIcon); this.civInformationActors.push(civIcon); @@ -173,7 +167,7 @@ export class SelectCivilizationGroup extends ActorGroup { font: "20px serif", fontColor: "white", x: this.x + 12, - y: this.y + 80, + y: this.y + 80 }); await startBiasLabel.conformSize(); @@ -188,7 +182,7 @@ export class SelectCivilizationGroup extends ActorGroup { fontColor: "white", x: this.x + 12, y: startBiasLabel.getY() + startBiasLabel.getHeight() + 30, - maxWidth: this.width - 12, + maxWidth: this.width - 12 }); await uniqueUnitDescLabel.conformSize(); @@ -197,8 +191,7 @@ export class SelectCivilizationGroup extends ActorGroup { this.addActor(uniqueUnitDescLabel); for (const uniqueUnitDesc of data["unique_unit_descs"]) { - const lastLabel = - this.civInformationActors[this.civInformationActors.length - 1]; + const lastLabel = this.civInformationActors[this.civInformationActors.length - 1]; const unitLabel = new Label({ text: "* " + uniqueUnitDesc, @@ -206,7 +199,7 @@ export class SelectCivilizationGroup extends ActorGroup { fontColor: "white", x: this.x + 12, y: lastLabel.getY() + lastLabel.getHeight() + 5, - maxWidth: this.width - 12, + maxWidth: this.width - 12 }); await unitLabel.conformSize(); @@ -216,8 +209,7 @@ export class SelectCivilizationGroup extends ActorGroup { } if ("unique_building_descs" in data) { - const lastLabel = - this.civInformationActors[this.civInformationActors.length - 1]; + const lastLabel = this.civInformationActors[this.civInformationActors.length - 1]; const uniqueBuildingsDescLabel = new Label({ text: "Unique Buildings:", @@ -225,7 +217,7 @@ export class SelectCivilizationGroup extends ActorGroup { fontColor: "white", x: this.x + 12, y: lastLabel.getY() + lastLabel.getHeight() + 30, - maxWidth: this.width - 12, + maxWidth: this.width - 12 }); await uniqueBuildingsDescLabel.conformSize(); @@ -234,8 +226,7 @@ export class SelectCivilizationGroup extends ActorGroup { this.addActor(uniqueBuildingsDescLabel); for (const buildingDesc of data["unique_building_descs"] as []) { - const lastLabel = - this.civInformationActors[this.civInformationActors.length - 1]; + const lastLabel = this.civInformationActors[this.civInformationActors.length - 1]; const abilityLabel = new Label({ text: "* " + buildingDesc, @@ -243,7 +234,7 @@ export class SelectCivilizationGroup extends ActorGroup { fontColor: "white", x: this.x + 12, y: lastLabel.getY() + lastLabel.getHeight() + 5, - maxWidth: this.width - 12, + maxWidth: this.width - 12 }); await abilityLabel.conformSize(); @@ -253,8 +244,7 @@ export class SelectCivilizationGroup extends ActorGroup { } } - const lastLabel = - this.civInformationActors[this.civInformationActors.length - 1]; + const lastLabel = this.civInformationActors[this.civInformationActors.length - 1]; const uniqueAbilityDescLabel = new Label({ text: "Special Abilities:", @@ -262,7 +252,7 @@ export class SelectCivilizationGroup extends ActorGroup { fontColor: "white", x: this.x + 12, y: lastLabel.getY() + lastLabel.getHeight() + 30, - maxWidth: this.width - 12, + maxWidth: this.width - 12 }); await uniqueAbilityDescLabel.conformSize(); @@ -271,8 +261,7 @@ export class SelectCivilizationGroup extends ActorGroup { this.addActor(uniqueAbilityDescLabel); for (const abilityDesc of data["ability_descs"]) { - const lastLabel = - this.civInformationActors[this.civInformationActors.length - 1]; + const lastLabel = this.civInformationActors[this.civInformationActors.length - 1]; const abilityLabel = new Label({ text: "* " + abilityDesc, @@ -280,7 +269,7 @@ export class SelectCivilizationGroup extends ActorGroup { fontColor: "white", x: this.x + 12, y: lastLabel.getY() + lastLabel.getHeight() + 5, - maxWidth: this.width - 12, + maxWidth: this.width - 12 }); await abilityLabel.conformSize(); @@ -302,7 +291,7 @@ export class SelectCivilizationGroup extends ActorGroup { // Fire event for lobby to handle this. Or network event..? //Game.getCurrentScene().removeActor(this); WebsocketClient.sendMessage({ event: "selectCiv", name: data["name"] }); - }, + } }); this.civInformationActors.push(selectButton); @@ -319,7 +308,7 @@ export class SelectCivilizationGroup extends ActorGroup { onClicked: () => { // Clear current civ information actors, restore select civ buttons: this.listAvailableCivs(); - }, + } }); this.civInformationActors.push(backButton); diff --git a/client/src/ui/StatusBar.ts b/client/src/ui/StatusBar.ts index 0a95befe..763dca8a 100644 --- a/client/src/ui/StatusBar.ts +++ b/client/src/ui/StatusBar.ts @@ -36,9 +36,9 @@ export class StatusBar extends ActorGroup { x: 0, y: 0, z: 5, - width: Game.getWidth(), + width: Game.getInstance().getWidth(), height: 21, - cameraApplies: false, + cameraApplies: false }); this.generateActors(); @@ -49,7 +49,7 @@ export class StatusBar extends ActorGroup { parentObject: this, callback: (data) => { this.updateCurrentTurnLabel(data); - }, + } }); NetworkEvents.on({ @@ -57,7 +57,7 @@ export class StatusBar extends ActorGroup { parentObject: this, callback: (data) => { this.updateCurrentTurnLabel(data); - }, + } }); } @@ -69,22 +69,19 @@ export class StatusBar extends ActorGroup { } else { this.currentTurnLabel.setText(text); this.currentTurnLabel.conformSize().then(() => { - this.currentTurnLabel.setPosition( - Game.getWidth() - this.currentTurnLabel.getWidth() - 1, - 3 - ); + this.currentTurnLabel.setPosition(Game.getInstance().getWidth() - this.currentTurnLabel.getWidth() - 1, 3); }); } } private async generateActors() { this.statusBarActor = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.UI_STATUSBAR, x: this.x, y: this.y, width: this.width, - height: this.height, + height: this.height }); this.addActor(this.statusBarActor); @@ -92,19 +89,19 @@ export class StatusBar extends ActorGroup { this.scienceDescLabel = new Label({ text: "Science:", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.scienceDescLabel.conformSize(); this.scienceDescLabel.setPosition(this.x + 1, 3); this.addActor(this.scienceDescLabel); this.scienceIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.SCIENCE_ICON, x: this.scienceDescLabel.getX() + this.scienceDescLabel.getWidth(), y: -6, width: 32, - height: 32, + height: 32 }); this.addActor(this.scienceIcon); @@ -112,35 +109,29 @@ export class StatusBar extends ActorGroup { this.scienceLabel = new Label({ text: "+0", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.scienceLabel.conformSize(); - this.scienceLabel.setPosition( - this.scienceIcon.getX() + this.scienceIcon.getWidth() - 6, - 3 - ); + this.scienceLabel.setPosition(this.scienceIcon.getX() + this.scienceIcon.getWidth() - 6, 3); this.addActor(this.scienceLabel); // Culture information this.cultureDescLabel = new Label({ text: "Culture:", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.cultureDescLabel.conformSize(); - this.cultureDescLabel.setPosition( - this.scienceLabel.getX() + this.scienceLabel.getWidth() + 10, - 3 - ); + this.cultureDescLabel.setPosition(this.scienceLabel.getX() + this.scienceLabel.getWidth() + 10, 3); this.addActor(this.cultureDescLabel); this.cultureIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.CULTURE_ICON, x: this.cultureDescLabel.getX() + this.cultureDescLabel.getWidth(), y: -6, width: 32, - height: 32, + height: 32 }); this.addActor(this.cultureIcon); @@ -148,35 +139,29 @@ export class StatusBar extends ActorGroup { this.cultureLabel = new Label({ text: "+0", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.cultureLabel.conformSize(); - this.cultureLabel.setPosition( - this.cultureIcon.getX() + this.cultureIcon.getWidth() - 6, - 3 - ); + this.cultureLabel.setPosition(this.cultureIcon.getX() + this.cultureIcon.getWidth() - 6, 3); this.addActor(this.cultureLabel); //Gold information this.goldDescLabel = new Label({ text: "Gold:", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.goldDescLabel.conformSize(); - this.goldDescLabel.setPosition( - this.cultureLabel.getX() + this.cultureLabel.getWidth() + 10, - 3 - ); + this.goldDescLabel.setPosition(this.cultureLabel.getX() + this.cultureLabel.getWidth() + 10, 3); this.addActor(this.goldDescLabel); this.goldIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.GOLD_ICON, x: this.goldDescLabel.getX() + this.goldDescLabel.getWidth(), y: -6, width: 32, - height: 32, + height: 32 }); this.addActor(this.goldIcon); @@ -184,13 +169,10 @@ export class StatusBar extends ActorGroup { this.goldLabel = new Label({ text: "+0", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.goldLabel.conformSize(); - this.goldLabel.setPosition( - this.goldIcon.getX() + this.goldIcon.getWidth() - 6, - 3 - ); + this.goldLabel.setPosition(this.goldIcon.getX() + this.goldIcon.getWidth() - 6, 3); this.addActor(this.goldLabel); //Faith information @@ -198,22 +180,19 @@ export class StatusBar extends ActorGroup { this.faithDescLabel = new Label({ text: "Faith:", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.faithDescLabel.conformSize(); - this.faithDescLabel.setPosition( - this.goldLabel.getX() + this.goldLabel.getWidth() + 10, - 3 - ); + this.faithDescLabel.setPosition(this.goldLabel.getX() + this.goldLabel.getWidth() + 10, 3); this.addActor(this.faithDescLabel); this.faithIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.FAITH_ICON, x: this.faithDescLabel.getX() + this.faithDescLabel.getWidth(), y: -6, width: 32, - height: 32, + height: 32 }); this.addActor(this.faithIcon); @@ -221,35 +200,29 @@ export class StatusBar extends ActorGroup { this.faithLabel = new Label({ text: "+0", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.faithLabel.conformSize(); - this.faithLabel.setPosition( - this.faithIcon.getX() + this.faithIcon.getWidth() - 6, - 3 - ); + this.faithLabel.setPosition(this.faithIcon.getX() + this.faithIcon.getWidth() - 6, 3); this.addActor(this.faithLabel); //Trade information this.tradeDescLabel = new Label({ text: "Trade:", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.tradeDescLabel.conformSize(); - this.tradeDescLabel.setPosition( - this.faithLabel.getX() + this.faithLabel.getWidth() + 10, - 3 - ); + this.tradeDescLabel.setPosition(this.faithLabel.getX() + this.faithLabel.getWidth() + 10, 3); this.addActor(this.tradeDescLabel); this.tradeIcon = new Actor({ - image: Game.getImage(GameImage.SPRITESHEET), + image: Game.getInstance().getImage(GameImage.SPRITESHEET), spriteRegion: SpriteRegion.TRADE_ICON, x: this.tradeDescLabel.getX() + this.tradeDescLabel.getWidth() + 10, y: 2, width: 16, - height: 16, + height: 16 }); this.addActor(this.tradeIcon); @@ -257,26 +230,20 @@ export class StatusBar extends ActorGroup { this.tradeLabel = new Label({ text: "0/0", font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.tradeLabel.conformSize(); - this.tradeLabel.setPosition( - this.tradeIcon.getX() + this.tradeIcon.getWidth() + 4, - 3 - ); + this.tradeLabel.setPosition(this.tradeIcon.getX() + this.tradeIcon.getWidth() + 4, 3); this.addActor(this.tradeLabel); // Current turn information this.currentTurnLabel = new Label({ text: this.currentTurnText, font: "16px serif", - fontColor: "white", + fontColor: "white" }); await this.currentTurnLabel.conformSize(); - this.currentTurnLabel.setPosition( - Game.getWidth() - this.currentTurnLabel.getWidth() - 1, - 3 - ); + this.currentTurnLabel.setPosition(Game.getInstance().getWidth() - this.currentTurnLabel.getWidth() - 1, 3); this.addActor(this.currentTurnLabel); } } diff --git a/client/src/ui/Textbox.ts b/client/src/ui/Textbox.ts index ff87b96e..cad82f13 100644 --- a/client/src/ui/Textbox.ts +++ b/client/src/ui/Textbox.ts @@ -23,7 +23,7 @@ export class TextBox extends Actor { x: options.x, y: options.y, width: options.width, - height: options.height, + height: options.height }); this.selected = false; @@ -105,40 +105,42 @@ export class TextBox extends Actor { public draw(canvasContext: CanvasRenderingContext2D) { if (this.textHeight == -1) { - Game.measureText("M", this.font).then(([width, height]) => { - this.textHeight = height; - }); + Game.getInstance() + .measureText("M", this.font) + .then(([width, height]) => { + this.textHeight = height; + }); } - Game.drawRect({ + Game.getInstance().drawRect({ x: this.x, y: this.y, width: this.width, height: this.height, color: "#FFFFFF", fill: true, - canvasContext: canvasContext, + canvasContext: canvasContext }); if (this.shouldBlink) { - Game.drawRect({ + Game.getInstance().drawRect({ x: this.blinkerX, y: this.y + 4, width: 2, height: this.height - 8, color: "black", fill: true, - canvasContext: canvasContext, + canvasContext: canvasContext }); } - Game.drawText( + Game.getInstance().drawText( { text: this.text, font: this.font, color: "black", x: this.x, - y: this.y + this.height / 2 - this.textHeight / 2, + y: this.y + this.height / 2 - this.textHeight / 2 }, canvasContext ); @@ -165,9 +167,11 @@ export class TextBox extends Actor { public setText(text: string) { this.text = text; - Game.measureText(this.text, this.font).then(([width, height]) => { - //this.textHeight = height; - this.blinkerX = this.x + 2 + width; - }); + Game.getInstance() + .measureText(this.text, this.font) + .then(([width, height]) => { + //this.textHeight = height; + this.blinkerX = this.x + 2 + width; + }); } } diff --git a/client/src/ui/UnitDisplayInfo.ts b/client/src/ui/UnitDisplayInfo.ts index f1d3afc9..ad71ddb9 100644 --- a/client/src/ui/UnitDisplayInfo.ts +++ b/client/src/ui/UnitDisplayInfo.ts @@ -15,12 +15,12 @@ export class UnitDisplayInfo extends ActorGroup { constructor(unit: Unit) { super({ - x: Game.getWidth() - 250, - y: Game.getHeight() - 150, + x: Game.getInstance().getWidth() - 250, + y: Game.getInstance().getHeight() - 150, width: 250, height: 150, cameraApplies: false, - z: 5, + z: 5 }); this.unit = unit; @@ -28,11 +28,11 @@ export class UnitDisplayInfo extends ActorGroup { this.addActor( new Actor({ - image: Game.getImage(GameImage.POPUP_BOX), + image: Game.getInstance().getImage(GameImage.POPUP_BOX), x: this.x, y: this.y, width: this.width, - height: this.height, + height: this.height }) ); @@ -41,14 +41,11 @@ export class UnitDisplayInfo extends ActorGroup { x: this.x, y: this.y, font: "18px serif", - fontColor: "white", + fontColor: "white" }); nameLabel.conformSize().then(() => { - nameLabel.setPosition( - this.x + this.width / 2 - nameLabel.getWidth() / 2, - this.y + 10 - ); + nameLabel.setPosition(this.x + this.width / 2 - nameLabel.getWidth() / 2, this.y + 10); this.addActor(nameLabel); }); @@ -57,7 +54,7 @@ export class UnitDisplayInfo extends ActorGroup { x: this.x, y: this.y, font: "18px serif", - fontColor: "white", + fontColor: "white" }); this.updateMovementLabel({ updateText: false }); @@ -70,7 +67,7 @@ export class UnitDisplayInfo extends ActorGroup { parentObject: this, callback: (data) => { this.refreshDisplayInfo(); - }, + } }); NetworkEvents.on({ @@ -81,7 +78,7 @@ export class UnitDisplayInfo extends ActorGroup { return; } this.refreshDisplayInfo(); - }, + } }); } @@ -93,9 +90,7 @@ export class UnitDisplayInfo extends ActorGroup { private updateMovementLabel(options: { updateText: boolean }) { if (options.updateText) { - this.movementLabel.setText( - `Movement: ${this.unit.getAvailableMovement()}/${this.unit.getDefaultMoveDistance()}` - ); + this.movementLabel.setText(`Movement: ${this.unit.getAvailableMovement()}/${this.unit.getDefaultMoveDistance()}`); } this.movementLabel.conformSize().then(() => { @@ -132,7 +127,7 @@ export class UnitDisplayInfo extends ActorGroup { unitX: this.unit.getTile().getGridX(), unitY: this.unit.getTile().getGridY(), id: this.unit.getID(), - actionName: action.getName(), + actionName: action.getName() }); }, onMouseEnter: () => { @@ -141,7 +136,7 @@ export class UnitDisplayInfo extends ActorGroup { }, onMouseExit: () => { this.updateMovementLabel({ updateText: true }); - }, + } }); this.addActor(button); diff --git a/client/src/util/Numbers.ts b/client/src/util/Numbers.ts index 8a766ac8..2244fac4 100644 --- a/client/src/util/Numbers.ts +++ b/client/src/util/Numbers.ts @@ -3,11 +3,7 @@ export class Numbers { return Math.min(Math.max(num, min), max); } - public static addAndWrapAround( - num: number, - addend: number, - max: number - ): number { + public static addAndWrapAround(num: number, addend: number, max: number): number { // add the numbers let sum = num + addend; diff --git a/client/src/util/Vector.ts b/client/src/util/Vector.ts index 7fcf89ae..c2f3478f 100644 --- a/client/src/util/Vector.ts +++ b/client/src/util/Vector.ts @@ -29,10 +29,7 @@ export class Vector { } public static getCenterOfPolygon(vectors: Vector[]): Vector { - const centerPoint = vectors.reduce( - (acc, curr) => new Vector(acc.x + curr.x, acc.y + curr.y), - new Vector(0, 0) - ); + const centerPoint = vectors.reduce((acc, curr) => new Vector(acc.x + curr.x, acc.y + curr.y), new Vector(0, 0)); centerPoint.x /= vectors.length; centerPoint.y /= vectors.length; @@ -48,9 +45,7 @@ export class Vector { let centerPoint = new Vector(centerX, centerY); const shiftedVectors = vectors.map((vector) => { - const distanceFromCenter = vector.distance( - new Vector(centerPoint.x, centerPoint.y) - ); + const distanceFromCenter = vector.distance(new Vector(centerPoint.x, centerPoint.y)); const shiftAmount = 1 - shiftDistance / distanceFromCenter; const shiftedVector = vector .clone() @@ -73,11 +68,7 @@ export class Vector { return angleInDegrees; } - public static isInsidePolygon( - vectors: Vector[], - mouseVector: Vector, - mouseExtremeVector: Vector - ) { + public static isInsidePolygon(vectors: Vector[], mouseVector: Vector, mouseExtremeVector: Vector) { // Count intersections of the above line // with sides of polygon let count = 0; @@ -88,14 +79,7 @@ export class Vector { // Check if the line segment from 'p' to // 'extreme' intersects with the line // segment from 'polygon[i]' to 'polygon[next]' - if ( - this.doIntersect( - vectors[i], - vectors[next], - mouseVector, - mouseExtremeVector - ) - ) { + if (this.doIntersect(vectors[i], vectors[next], mouseVector, mouseExtremeVector)) { // If the point 'p' is colinear with line // segment 'i-next', then check if it lies // on segment. If it lies, return true, otherwise false diff --git a/package.json b/package.json index b157649a..9da6c677 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "scripts": { "start": "concurrently \"npm start --prefix server\" \"npm run dev --prefix client\"", "install-all": "npm install && concurrently \"npm install --prefix ./server\" \"npm install --prefix ./client\"", - "generate-docs": "concurrently \"cd ./server && npx typedoc --name openciv/server\" \"cd ./client && npx typedoc --name openciv/client\"" + "generate-docs": "concurrently \"cd ./server && npx typedoc --name openciv/server\" \"cd ./client && npx typedoc --name openciv/client\"", + "format": "npx prettier --write \"**/*.ts\"" }, "dependencies": { "concurrently": "^7.6.0" diff --git a/server/src/Events.ts b/server/src/Events.ts index 12830f86..31377a5e 100644 --- a/server/src/Events.ts +++ b/server/src/Events.ts @@ -5,11 +5,7 @@ export class CallbackData { public callbackFunction: Function; public globalEvent: boolean; // Not associated with the current scene. - constructor( - parentObject: object, - callbackFunctions: Function, - globalEvent: boolean - ) { + constructor(parentObject: object, callbackFunctions: Function, globalEvent: boolean) { this.parentObject = parentObject; this.callbackFunction = callbackFunctions; this.globalEvent = globalEvent; @@ -28,16 +24,10 @@ export class ServerEvents { private constructor() {} - public static call( - eventName: string, - data: Record, - websocket?: WebSocket - ) { + public static call(eventName: string, data: Record, websocket?: WebSocket) { if (this.storedEvents.has(eventName)) { //Call the stored callback function - const callbackDataList = this.storedEvents.get( - eventName - ) as CallbackData[]; + const callbackDataList = this.storedEvents.get(eventName) as CallbackData[]; for (let callbackData of callbackDataList) { callbackData.callbackFunction(data, websocket); } @@ -75,9 +65,7 @@ export class ServerEvents { public static removeCallbacksByParentObject(parentObj: object): void { this.storedEvents.forEach((callbackDataList, eventName) => { - const filteredDataList = callbackDataList.filter( - (callbackData) => callbackData.parentObject !== parentObj - ); + const filteredDataList = callbackDataList.filter((callbackData) => callbackData.parentObject !== parentObj); if (filteredDataList.length === 0) { this.storedEvents.delete(eventName); @@ -117,9 +105,7 @@ export class ServerEvents { //Get the list of stored callback functions or an empty list let callbackDataList: CallbackData[] = storedEvents.get(eventName) ?? []; // Append the to functions - callbackDataList.push( - new CallbackData(parentObject, callback, globalEvent) - ); + callbackDataList.push(new CallbackData(parentObject, callback, globalEvent)); storedEvents.set(eventName, callbackDataList); } } diff --git a/server/src/Game.ts b/server/src/Game.ts index ea6ba42b..db20a03e 100644 --- a/server/src/Game.ts +++ b/server/src/Game.ts @@ -7,15 +7,13 @@ import { ServerEvents } from "./Events"; * Game class is responsible for managing the state of the game, and players. */ export class Game { - private constructor() {} - private static currentState: State; - private static states: Map; - private static players: Map; + private static gameInstance: Game; - /** - * Initializes the game by setting up server event listeners for various events. - */ - public static init() { + private currentState: State; + private states: Map; + private players: Map; + + private constructor() { this.states = new Map(); // Set up the listener for the "setState" event. Changes the game-state. @@ -25,7 +23,7 @@ export class Game { callback: (data: JSON) => { this.setState(data["state"]); }, - globalEvent: true, + globalEvent: true }); // Set up the listener for the "connectedPlayers" event. Return all connected players in-game. @@ -34,18 +32,17 @@ export class Game { parentObject: this, callback: (data: JSON, websocket) => { // Get all player names and the name of the requesting player. - const requestingPlayerName = - this.getPlayerFromWebsocket(websocket)?.getName(); + const requestingPlayerName = this.getPlayerFromWebsocket(websocket)?.getName(); // Send the names to the requesting player. websocket.send( JSON.stringify({ event: "connectedPlayers", players: this.getPlayerJSONS(), - requestingName: requestingPlayerName, + requestingName: requestingPlayerName }) ); }, - globalEvent: true, + globalEvent: true }); // Set up the listener for the "playerQuit" event. @@ -55,19 +52,30 @@ export class Game { callback: (data: JSON) => { // If only one player is remaining, set the state to "lobby". if (this.players.size <= 1) { - Game.setState("lobby"); + this.setState("lobby"); } }, - globalEvent: true, + globalEvent: true }); } + public static getInstance() { + return this.gameInstance; + } + + /** + * Initializes the game by setting up server event listeners for various events. + */ + public static init() { + this.gameInstance = new Game(); + } + /** * Adds a state to the states map. * @param stateName - The name of the state. * @param state - The state object to add. */ - public static addState(stateName: string, state: State) { + public addState(stateName: string, state: State) { this.states.set(stateName, state); } @@ -75,7 +83,7 @@ export class Game { * Sets the current state of the game. * @param stateName - The name of the state to set. */ - public static setState(stateName: string) { + public setState(stateName: string) { const newState = this.states.get(stateName) as State; if (this.currentState != null) { @@ -90,7 +98,7 @@ export class Game { * Returns the map containing all the players in the game. * Creates a new map if it doesn't exist. */ - public static getPlayers() { + public getPlayers() { if (!this.players) { this.players = new Map(); } @@ -103,7 +111,7 @@ export class Game { * @param websocket - The websocket to check. * @returns - The player object associated with the websocket or undefined if not found. */ - public static getPlayerFromWebsocket(websocket: WebSocket) { + public getPlayerFromWebsocket(websocket: WebSocket) { for (const player of this.players.values()) { if (player.getWebsocket() === websocket) { return player; @@ -113,11 +121,11 @@ export class Game { return undefined; } - public static getCurrentStateAs(): T { + public getCurrentStateAs(): T { return this.currentState as T; } - private static getPlayerJSONS() { + private getPlayerJSONS() { const playerJSONS = []; for (const player of this.players.values()) { diff --git a/server/src/Player.ts b/server/src/Player.ts index cdf1f736..62fbfc8f 100644 --- a/server/src/Player.ts +++ b/server/src/Player.ts @@ -37,10 +37,10 @@ export class Player { this.wsConnection.on("close", (data) => { console.log(name + " quit"); ServerEvents.call("playerQuit", {}, this.wsConnection); - Game.getPlayers().delete(this.name); + Game.getInstance().getPlayers().delete(this.name); // Send playerQuit data to other connected players - for (const player of Array.from(Game.getPlayers().values())) { + for (const player of Array.from(Game.getInstance().getPlayers().values())) { if (player === this) { continue; } @@ -58,7 +58,7 @@ export class Player { this.loadedIn = true; this.loadedInCallback.call(undefined); }, - globalEvent: true, + globalEvent: true }); ServerEvents.on({ @@ -69,7 +69,7 @@ export class Player { this.resizeWindowCallback.call(undefined); }, - globalEvent: true, + globalEvent: true }); } @@ -80,7 +80,7 @@ export class Player { * @param zoomAmount The zoom amount to apply. */ public static allZoomOnto(x: number, y: number, zoomAmount: number) { - for (let player of Game.getPlayers().values()) { + for (let player of Game.getInstance().getPlayers().values()) { player.zoomToLocation(x, y, zoomAmount); } } @@ -120,7 +120,7 @@ export class Player { event: "zoomToLocation", x: x, y: y, - zoomAmount: zoomAmount, + zoomAmount: zoomAmount }); } @@ -156,7 +156,7 @@ export class Player { return { name: this.name, civData: this.civilizationData, - requestedNextTurn: this.requestedNextTurn, + requestedNextTurn: this.requestedNextTurn }; } diff --git a/server/src/Server.ts b/server/src/Server.ts index 34003d68..6f805d82 100644 --- a/server/src/Server.ts +++ b/server/src/Server.ts @@ -5,7 +5,7 @@ import { InGameState } from "./state/type/InGameState"; import { LobbyState } from "./state/type/LobbyState"; export class Server { - private static instance: Server = new Server(); + private static serverInstance: Server; private port: number = 2000; private wss: WebSocketServer; @@ -15,7 +15,11 @@ export class Server { * @returns Server singleton instance */ public static getInstance(): Server { - return this.instance; + if (this.serverInstance == undefined) { + this.serverInstance = new Server(); + } + + return this.serverInstance; } /** @@ -55,9 +59,9 @@ export class Server { * Set the game state to "lobby". */ Game.init(); - Game.addState("lobby", new LobbyState()); - Game.addState("in_game", new InGameState()); - Game.setState("lobby"); + Game.getInstance().addState("lobby", new LobbyState()); + Game.getInstance().addState("in_game", new InGameState()); + Game.getInstance().setState("lobby"); } /** diff --git a/server/src/city/City.ts b/server/src/city/City.ts index 7020a612..80da6991 100644 --- a/server/src/city/City.ts +++ b/server/src/city/City.ts @@ -48,13 +48,13 @@ export class City { eventName: "requestCityStats", parentObject: this, callback: (data, websocket) => { - const player = Game.getPlayerFromWebsocket(websocket); + const player = Game.getInstance().getPlayerFromWebsocket(websocket); if (this.name != data["cityName"] || this.player != player) { return; } this.sendStatUpdate(player); - }, + } }); } @@ -73,7 +73,7 @@ export class City { const tile = GameMap.getInstance().getTileWithHighestYeild({ stats: [tileFocus], tiles: this.territory, - ignoreTiles: this.workedTiles, + ignoreTiles: this.workedTiles }); this.workedTiles.push(tile); @@ -86,8 +86,7 @@ export class City { public addBuilding(name: string) { // Get the building data from YML - const buildingData = - Game.getCurrentStateAs().getBuildingDataByName(name); + const buildingData = Game.getInstance().getCurrentStateAs().getBuildingDataByName(name); // Apply any effects to the building if any (faith, culture, bonuses, etc.)): //... @@ -99,7 +98,7 @@ export class City { this.player.sendNetworkEvent({ event: "addBuilding", cityName: this.name, - building: buildingData, + building: buildingData }); this.updateWorkedTiles({ sendStatUpdate: true }); @@ -117,7 +116,7 @@ export class City { player.sendNetworkEvent({ event: "updateCityStats", cityName: this.name, - cityStats: cityStats, + cityStats: cityStats }); } @@ -126,7 +125,7 @@ export class City { if (options.asArray) { const cityStats = [ { - population: this.population, + population: this.population }, { science: 0 }, { gold: 0 }, @@ -135,7 +134,7 @@ export class City { { culture: 0 }, { food: -(this.population * 2) }, { morale: 0 }, //TODO: Implement morale - { foodSurplus: this.foodSurplus }, + { foodSurplus: this.foodSurplus } ]; // Add all buildings to existing stat-line dictionary @@ -165,7 +164,7 @@ export class City { culture: 0, food: -(this.population * 2), morale: 0, //TODO: Implement morale - foodSurplus: this.foodSurplus, + foodSurplus: this.foodSurplus }; // Feed citizens @@ -213,7 +212,7 @@ export class City { public getJSON() { const territoryCoords = this.territory.map((tile) => ({ tileX: tile.getX(), - tileY: tile.getY(), + tileY: tile.getY() })); return { @@ -221,7 +220,7 @@ export class City { player: this.player.getName(), tileX: this.tile.getX(), tileY: this.tile.getY(), - territory: territoryCoords, + territory: territoryCoords }; } } diff --git a/server/src/map/GameMap.ts b/server/src/map/GameMap.ts index deb1e4d3..3db35708 100644 --- a/server/src/map/GameMap.ts +++ b/server/src/map/GameMap.ts @@ -3,7 +3,7 @@ import { Tile } from "./Tile"; import random from "random"; import { MapResources } from "./MapResources"; import { TileIndexer } from "./TileIndexer"; -import { Unit } from "../Unit"; +import { Unit } from "../unit/Unit"; import PriorityQueue from "ts-priority-queue"; enum MapSize { @@ -12,7 +12,7 @@ enum MapSize { SMALL = "68x44", STANDARD = "80x52", LARGE = "104x64", - HUGE = "128x80", + HUGE = "128x80" } export class GameMap { @@ -24,7 +24,7 @@ export class GameMap { [1, 0], [1, 1], [0, 1], - [-1, 0], + [-1, 0] ]; private static evenEdgeAxis = [ [-1, -1], @@ -32,7 +32,7 @@ export class GameMap { [1, 0], [0, 1], [-1, 1], - [-1, 0], + [-1, 0] ]; private tiles: Tile[][]; @@ -104,8 +104,7 @@ export class GameMap { // == Generate grass circles == const LAND_MASS_PARAM = 6; - const landMassSize = - ((this.mapWidth * this.mapHeight) / 12.5) * (LAND_MASS_PARAM + 2); + const landMassSize = ((this.mapWidth * this.mapHeight) / 12.5) * (LAND_MASS_PARAM + 2); const maxPathLength = 140; const maxLandmassIterations = 10000; let landmassIterations = 0; @@ -123,7 +122,7 @@ export class GameMap { setTileType: "grass", followTileTypes: ["ocean"], setTileChance: 0.5, - overrideWater: true, + overrideWater: true }); if (landmassIterations >= maxLandmassIterations) break; @@ -169,11 +168,7 @@ export class GameMap { while (low < high) { var mid = (low + high) >>> 1; // Same as: (low + high) / 2 - if ( - tallestTiles[mid].getGenerationHeight() > - currentTile.getGenerationHeight() - ) - low = mid + 1; + if (tallestTiles[mid].getGenerationHeight() > currentTile.getGenerationHeight()) low = mid + 1; else high = mid; } const insertionIndex = low; @@ -187,15 +182,13 @@ export class GameMap { //Assign top 10% of tiles to have a 50% of becoming a hill tile const totalHills = tallestTiles.length * 0.1; for (let i = 0; i < totalHills; i++) { - if (Math.random() < 0.5) - tallestTiles[i].replaceTileType("grass", "grass_hill"); + if (Math.random() < 0.5) tallestTiles[i].replaceTileType("grass", "grass_hill"); } // TODO: Spawn hills in patches? // For all other grass tiles, make it a 13% of becoming a hill tile. for (let i = 0; i < tallestTiles.length; i++) { - if (Math.random() < 0.13) - tallestTiles[i].replaceTileType("grass", "grass_hill"); + if (Math.random() < 0.13) tallestTiles[i].replaceTileType("grass", "grass_hill"); } //Assign the top 5% of tiles to be mountains @@ -216,10 +209,7 @@ export class GameMap { if (yPercent <= 0.1 || yPercent >= 0.9) { tile.setGenerationTemp(random.int(0, 31)); //TODO: Higher temp on y-values closer to midpoint. - } else if ( - (yPercent > 0.1 && yPercent < 0.3) || - (yPercent > 0.7 && yPercent < 0.9) - ) { + } else if ((yPercent > 0.1 && yPercent < 0.3) || (yPercent > 0.7 && yPercent < 0.9)) { tile.setGenerationTemp(random.int(32, 60)); } else { tile.setGenerationTemp(random.int(60, 100)); @@ -239,10 +229,7 @@ export class GameMap { if (yPercent <= 0.1 || yPercent >= 0.9) { this.setTileBiome({ tile: currentTile, tileType: "snow" }); - } else if ( - (yPercent > 0.1 && yPercent < 0.15) || - (yPercent > 0.85 && yPercent < 0.9) - ) { + } else if ((yPercent > 0.1 && yPercent < 0.15) || (yPercent > 0.85 && yPercent < 0.9)) { if (Math.random() > 0.25) { for (const adjTile of currentTile.getAdjacentTiles()) { if (!adjTile) continue; @@ -265,7 +252,7 @@ export class GameMap { for (let i = 0; i < numberOfPlainsBiomes; i++) { const originTile = this.getRandomTileWith({ tileTypes: ["grass"], - tempRange: [60, 80], + tempRange: [60, 80] }); if (!originTile) continue; this.generateTilePath({ @@ -274,7 +261,7 @@ export class GameMap { setTileType: "plains", followTileTypes: ["grass"], setTileChance: 0.95, - overrideWater: false, + overrideWater: false }); } console.log("Done generating plains biomes!"); @@ -285,7 +272,7 @@ export class GameMap { for (let i = 0; i < numberOfDesertBiomes; i++) { const originTile = this.getRandomTileWith({ tileTypes: ["grass"], - tempRange: [95, 100], + tempRange: [95, 100] }); if (!originTile) continue; // Now we have random origin, create path @@ -295,7 +282,7 @@ export class GameMap { setTileType: "desert", followTileTypes: ["grass", "grass_hill"], setTileChance: 0.95, - overrideWater: false, + overrideWater: false }); } console.log("Done generating desert biomes!"); @@ -306,7 +293,7 @@ export class GameMap { for (let i = 0; i < numberOfJungleBiomes; i++) { const originTile = this.getRandomTileWith({ tileTypes: ["grass"], - tempRange: [60, 75], + tempRange: [60, 75] }); if (!originTile) continue; // Now we have random origin, create path @@ -318,7 +305,7 @@ export class GameMap { setTileChance: 0.5, overrideWater: false, setFollowTileTypeOnly: true, - clearExistingTileTypes: false, + clearExistingTileTypes: false }); } console.log("Done generating jungle tiles!"); @@ -330,7 +317,7 @@ export class GameMap { for (let i = 0; i < numberOfForestBiomes; i++) { const originTile = this.getRandomTileWith({ tileTypes: ["grass"], - tempRange: [32, 90], + tempRange: [32, 90] }); if (!originTile) continue; // Now we have random origin, create path @@ -338,18 +325,11 @@ export class GameMap { tile: originTile, pathLength: 5, setTileType: "forest", - followTileTypes: [ - "grass", - "grass_hill", - "plains", - "plains_hill", - "tundra", - "tundra_hill", - ], + followTileTypes: ["grass", "grass_hill", "plains", "plains_hill", "tundra", "tundra_hill"], setTileChance: 0.1, overrideWater: false, setFollowTileTypeOnly: true, - clearExistingTileTypes: false, + clearExistingTileTypes: false }); } console.log("Done generating forest tiles!"); @@ -371,10 +351,7 @@ export class GameMap { if (!adjTile) { freshwater = false; } else if (adjTile.containsTileType("ocean")) { - if ( - !traversedTiles.includes(adjTile) && - !traverseQueue.includes(adjTile) - ) { + if (!traversedTiles.includes(adjTile) && !traverseQueue.includes(adjTile)) { traverseQueue.push(adjTile); } } @@ -427,14 +404,14 @@ export class GameMap { mapResourceType = "luxury"; } const mapResource = MapResources.getRandomMapResource({ - mapResourceType: mapResourceType, + mapResourceType: mapResourceType }); const originTile = this.getRandomTileWith({ tileTypes: mapResource.getSpawnTiles(), onAdditionalTileTypes: mapResource.spawnOnAdditionalTileTypes(), avoidResourceTiles: true, - tempRange: [mapResource.getMinTemp(), mapResource.getMaxTemp()], + tempRange: [mapResource.getMinTemp(), mapResource.getMaxTemp()] }); if (!originTile) { @@ -452,14 +429,12 @@ export class GameMap { setTileChance: mapResource.getSetChance(), minTilesSet: mapResource.getMinTilesSet(), maxTilesSet: mapResource.getMaxTilesSet(), - overrideWater: mapResource.getSpawnTiles().includes("ocean") - ? true - : false, + overrideWater: mapResource.getSpawnTiles().includes("ocean") ? true : false, setFollowTileTypeOnly: true, clearExistingTileTypes: false, insertIndex: 1, // Puts the resource behind trees, jungle onAdditionalTileTypes: mapResource.onAdditionalTileTypes, - avoidResourceTiles: true, + avoidResourceTiles: true }); } console.log("Done generating resources!"); @@ -469,23 +444,12 @@ export class GameMap { console.log("Generating rivers..."); //const riverAmount = 25; //FIXME: The higher number the higher chance of infinite loop. const riverAmount = this.mapArea * 0.015; - rivenGenLoop: for ( - let riverIndex = 0; - riverIndex < riverAmount; - riverIndex++ - ) { + rivenGenLoop: for (let riverIndex = 0; riverIndex < riverAmount; riverIndex++) { //console.log("riverGenLoop"); let originTile: Tile = undefined; findRiverOriginLoop: while (!originTile) { originTile = this.getRandomTileWith({ - tileTypes: [ - "grass_hill", - "plains_hill", - "desert_hill", - "tundra_hill", - "snow_hill", - "mountain", - ], + tileTypes: ["grass_hill", "plains_hill", "desert_hill", "tundra_hill", "snow_hill", "mountain"] }); // If we couldn't find a random tile, just give up. @@ -494,10 +458,7 @@ export class GameMap { for (const adjTile of originTile.getAdjacentTiles()) { if (!adjTile) continue; - if ( - adjTile.containsTileType("river_candidate") || - adjTile.isWater() - ) { + if (adjTile.containsTileType("river_candidate") || adjTile.isWater()) { originTile = undefined; continue findRiverOriginLoop; } @@ -519,11 +480,7 @@ export class GameMap { let riverLength = 1; riverPathLoop: while (true) { - const nextTileCandidates: Tile[] = this.getNextPotentialRiverTiles( - currentTile, - lastTraversedTile, - originTile - ); + const nextTileCandidates: Tile[] = this.getNextPotentialRiverTiles(currentTile, lastTraversedTile, originTile); lastTraversedTile = currentTile; @@ -533,8 +490,7 @@ export class GameMap { } // Traverse to the next tile from nextTileCandidates[] - currentTile = - nextTileCandidates[random.int(0, nextTileCandidates.length - 1)]; + currentTile = nextTileCandidates[random.int(0, nextTileCandidates.length - 1)]; if (!currentTile) { riverIndex--; @@ -577,8 +533,7 @@ export class GameMap { let prevTile: Tile = undefined; let nextTile: Tile = undefined; - if (i < currentRiverTiles.length - 1) - nextTile = currentRiverTiles[i + 1]; // Include the next tile we are traversing + if (i < currentRiverTiles.length - 1) nextTile = currentRiverTiles[i + 1]; // Include the next tile we are traversing if (i > 0) prevTile = currentRiverTiles[i - 1]; // Ensure we are including the previous tile such that we can connect to it through our method. @@ -596,7 +551,7 @@ export class GameMap { tile.applyRiverSide({ originTile: i == 0, previousTile: prevTile, - nextTile: nextTile, + nextTile: nextTile }); appliedRiverSides++; } @@ -607,8 +562,7 @@ export class GameMap { let tooManyRiverSides = false; for (let i = 0; i < currentRiverTiles.length; i++) { const tile = currentRiverTiles[i]; - if (tile.getRiverSideIndexes({ value: true }).length > 3) - tooManyRiverSides = true; + if (tile.getRiverSideIndexes({ value: true }).length > 3) tooManyRiverSides = true; } if (tooManyRiverSides || appliedRiverSides < 3) { @@ -655,11 +609,7 @@ export class GameMap { console.log("Done generating floodplains!"); } - public getNextPotentialRiverTiles( - currentTile: Tile, - lastTraversedTile: Tile, - originTile: Tile - ) { + public getNextPotentialRiverTiles(currentTile: Tile, lastTraversedTile: Tile, originTile: Tile) { const nextTileCandidates = []; adjCandidateTilesLoop: for (const adjacentCandidateTile of currentTile.getAdjacentTiles()) { let deleteCandidate = false; @@ -678,10 +628,7 @@ export class GameMap { // Check if the distance of the candidate is closer to the origin than the lastTraversedTile, if so remove it if (lastTraversedTile) { - if ( - originTile.getDistanceFrom(adjacentCandidateTile) <= - originTile.getDistanceFrom(lastTraversedTile) - ) { + if (originTile.getDistanceFrom(adjacentCandidateTile) <= originTile.getDistanceFrom(lastTraversedTile)) { continue adjCandidateTilesLoop; } } @@ -714,7 +661,7 @@ export class GameMap { public getDimensionValues(mapSize: MapSize) { const values = [ parseInt(mapSize.substring(0, mapSize.indexOf("x"))), - parseInt(mapSize.substring(mapSize.indexOf("x") + 1)), + parseInt(mapSize.substring(mapSize.indexOf("x") + 1)) ]; return values; } @@ -723,13 +670,13 @@ export class GameMap { player.sendNetworkEvent({ event: "mapSize", width: this.mapWidth, - height: this.mapHeight, + height: this.mapHeight }); //Send tile stats to player player.sendNetworkEvent({ event: "tileStats", - tiles: Tile.getAllTileStats(), + tiles: Tile.getAllTileStats() }); for (let x = 0; x < this.mapWidth; x += 4) { @@ -756,7 +703,7 @@ export class GameMap { chunkX: x, chunkY: y, tiles: chunkTiles, - lastChunk: lastChunk, + lastChunk: lastChunk }); } } @@ -789,20 +736,12 @@ export class GameMap { let edgeX = x + edgeAxis[i][0]; let edgeY = y + edgeAxis[i][1]; - if ( - edgeX == -1 || - edgeY == -1 || - edgeX > this.mapWidth - 1 || - edgeY > this.mapHeight - 1 - ) { + if (edgeX == -1 || edgeY == -1 || edgeX > this.mapWidth - 1 || edgeY > this.mapHeight - 1) { this.tiles[x][y].setAdjacentTile(i, null); continue; } - this.tiles[x][y].setAdjacentTile( - i, - this.tiles[x + edgeAxis[i][0]][y + edgeAxis[i][1]] - ); + this.tiles[x][y].setAdjacentTile(i, this.tiles[x + edgeAxis[i][0]][y + edgeAxis[i][1]]); } } } @@ -815,12 +754,7 @@ export class GameMap { } } - private setTileBiome(options: { - tile: Tile; - tileType: string; - clearTileTypes?: boolean; - insertIndex?: number; - }) { + private setTileBiome(options: { tile: Tile; tileType: string; clearTileTypes?: boolean; insertIndex?: number }) { const clearTileTypes = options.clearTileTypes ?? true; // By default this is true. let newTileType = undefined; @@ -878,7 +812,7 @@ export class GameMap { onAdditionalTileTypes = false, avoidResourceTiles = false, minTilesSet = 0, - maxTilesSet = 99999, + maxTilesSet = 99999 } = options; let tile = options.tile; let tilesSet = 0; @@ -904,11 +838,7 @@ export class GameMap { if (tile.containsTileType("ocean") && !options.overrideWater) continue; // Skip if we don't spread to the tile types we follow - if ( - !tile.containsTileTypes(options.followTileTypes) && - setFollowTileTypeOnly - ) - continue; + if (!tile.containsTileTypes(options.followTileTypes) && setFollowTileTypeOnly) continue; // Skip if we end up in a tile w/ tileTypes > 1 and we want to avoid them if (!onAdditionalTileTypes && tile.getTileTypes().length > 1) continue; @@ -921,7 +851,7 @@ export class GameMap { tile: tile, tileType: options.setTileType, clearTileTypes: options.clearExistingTileTypes, - insertIndex: options.insertIndex, + insertIndex: options.insertIndex }); tilesSet++; @@ -942,8 +872,7 @@ export class GameMap { } // Get the nextPathTile randomly, which has to be an adjacent follow tile - nextPathTile = - adjacentFollowTiles[random.int(0, adjacentFollowTiles.length)]; + nextPathTile = adjacentFollowTiles[random.int(0, adjacentFollowTiles.length)]; // If we can't get get a tile adjacent to follow tile, the path ends. if (!nextPathTile) break; @@ -954,16 +883,13 @@ export class GameMap { // Ensure the minimum amount of tiles have been set. if (tilesSet < minTilesSet) { for (let i = tilesSet; i < minTilesSet; i++) { - const rndTile = - skippedValidGenerationTiles[ - random.int(0, skippedValidGenerationTiles.length - 1) - ]; + const rndTile = skippedValidGenerationTiles[random.int(0, skippedValidGenerationTiles.length - 1)]; this.setTileBiome({ tile: rndTile, tileType: options.setTileType, clearTileTypes: options.clearExistingTileTypes, - insertIndex: options.insertIndex, + insertIndex: options.insertIndex }); tilesSet++; } @@ -992,11 +918,7 @@ export class GameMap { let originTile = undefined; let iterations = 0; - const { - tempRange = [0, 100], - onAdditionalTileTypes = false, - avoidResourceTiles = false, - } = options; + const { tempRange = [0, 100], onAdditionalTileTypes = false, avoidResourceTiles = false } = options; const minTemp = tempRange[0]; const maxTemp = tempRange[1]; const maxIterations = 100; @@ -1005,42 +927,26 @@ export class GameMap { iterations++; if (iterations >= maxIterations) { - console.log( - "Reached max iterations for random tile: " + options.tileTypes - ); + console.log("Reached max iterations for random tile: " + options.tileTypes); break; } - const randomTile = - this.tiles[random.int(0, this.mapWidth - 1)][ - random.int(0, this.mapHeight - 1) - ]; + const randomTile = this.tiles[random.int(0, this.mapWidth - 1)][random.int(0, this.mapHeight - 1)]; // Ensure we are avoiding any tile types we don't want - if ( - options.avoidTileTypes && - randomTile.containsTileTypes(options.avoidTileTypes) - ) - continue; + if (options.avoidTileTypes && randomTile.containsTileTypes(options.avoidTileTypes)) continue; // Ensure at least one tile type is in this randomTile. - if (options.tileTypes && !randomTile.containsTileTypes(options.tileTypes)) - continue; + if (options.tileTypes && !randomTile.containsTileTypes(options.tileTypes)) continue; // Ensure we are within the provided temperature range - if ( - randomTile.getGenerationTemp() < minTemp || - randomTile.getGenerationTemp() > maxTemp - ) - continue; + if (randomTile.getGenerationTemp() < minTemp || randomTile.getGenerationTemp() > maxTemp) continue; // If we don't want additional tileTypes, check for that - if (!onAdditionalTileTypes && randomTile.getTileTypes().length > 1) - continue; + if (!onAdditionalTileTypes && randomTile.getTileTypes().length > 1) continue; // If we don't want to spawn on existing resource, natural wonder tiles, check for that - if (avoidResourceTiles && MapResources.isResourceTile(randomTile)) - continue; + if (avoidResourceTiles && MapResources.isResourceTile(randomTile)) continue; originTile = randomTile; } @@ -1143,7 +1049,7 @@ export class GameMap { return 0; // fscoreA and fscoreB are equal } }, - initialValues: [startTile], + initialValues: [startTile] }); //cameFrom.fill(undefined, 0, totalNodes); @@ -1158,22 +1064,16 @@ export class GameMap { for (let neighborTile of currentTile.getAdjacentTiles()) { if (!neighborTile) continue; - let d = (current: Tile, neighbor: Tile) => - unit.getTileWeight(current, neighbor); + let d = (current: Tile, neighbor: Tile) => unit.getTileWeight(current, neighbor); - let tentativeGScore = - gScore[currentTile.getX()][currentTile.getY()] + - d(currentTile, neighborTile); + let tentativeGScore = gScore[currentTile.getX()][currentTile.getY()] + d(currentTile, neighborTile); //console.log(neighborTile.getNodeIndex()); //console.log(gScore[neighborTile.getNodeIndex()]); - if ( - tentativeGScore < gScore[neighborTile.getX()][neighborTile.getY()] - ) { + if (tentativeGScore < gScore[neighborTile.getX()][neighborTile.getY()]) { cameFrom[neighborTile.getX()][neighborTile.getY()] = currentTile; gScore[neighborTile.getX()][neighborTile.getY()] = tentativeGScore; - fScore[neighborTile.getX()][neighborTile.getY()] = - tentativeGScore + h(neighborTile); + fScore[neighborTile.getX()][neighborTile.getY()] = tentativeGScore + h(neighborTile); //if (!QueueUtils.valuePresent(openSet, neighborTile)) { openSet.queue(neighborTile); @@ -1185,11 +1085,7 @@ export class GameMap { return []; } - public getTileWithHighestYeild(options: { - stats: string[]; - tiles: Tile[]; - ignoreTiles: Tile[]; - }) { + public getTileWithHighestYeild(options: { stats: string[]; tiles: Tile[]; ignoreTiles: Tile[] }) { let highestTile: Tile = undefined; let highestValue = 0; diff --git a/server/src/map/MapResources.ts b/server/src/map/MapResources.ts index dad5831a..673bdefa 100644 --- a/server/src/map/MapResources.ts +++ b/server/src/map/MapResources.ts @@ -22,8 +22,7 @@ export class MapResource { this.setChance = resourceData.set_chance; this.minTemp = resourceData.min_temp; this.maxTemp = resourceData.max_temp; - this.onAdditionalTileTypes = - resourceData.spawn_on_additional_tile_types ?? false; + this.onAdditionalTileTypes = resourceData.spawn_on_additional_tile_types ?? false; } public getName(): string { @@ -73,31 +72,22 @@ export class MapResources { this.resourcesData = YAML.parse(file); } - public static getRandomMapResource(options: { - mapResourceType: string; - }): MapResource { + public static getRandomMapResource(options: { mapResourceType: string }): MapResource { if (!this.resourcesData) this.loadConfigurationFile(); let resourceData = undefined; switch (options.mapResourceType) { case "bonus": - resourceData = - this.resourcesData.bonus_resources[ - random.int(0, this.resourcesData.bonus_resources.length - 1) - ]; + resourceData = this.resourcesData.bonus_resources[random.int(0, this.resourcesData.bonus_resources.length - 1)]; break; case "strategic": resourceData = - this.resourcesData.strategic_resources[ - random.int(0, this.resourcesData.strategic_resources.length - 1) - ]; + this.resourcesData.strategic_resources[random.int(0, this.resourcesData.strategic_resources.length - 1)]; break; case "luxury": resourceData = - this.resourcesData.luxury_resources[ - random.int(0, this.resourcesData.luxury_resources.length - 1) - ]; + this.resourcesData.luxury_resources[random.int(0, this.resourcesData.luxury_resources.length - 1)]; break; } @@ -114,10 +104,8 @@ export class MapResources { const resourceTileTypes = [ ...this.resourcesData.bonus_resources.map((resource) => resource.name), - ...this.resourcesData.strategic_resources.map( - (resource) => resource.name - ), - ...this.resourcesData.luxury_resources.map((resource) => resource.name), + ...this.resourcesData.strategic_resources.map((resource) => resource.name), + ...this.resourcesData.luxury_resources.map((resource) => resource.name) ]; return tile.containsTileTypes(resourceTileTypes); } diff --git a/server/src/map/Tile.ts b/server/src/map/Tile.ts index f85ddcbe..146154cc 100644 --- a/server/src/map/Tile.ts +++ b/server/src/map/Tile.ts @@ -1,7 +1,7 @@ import random from "random"; import { GameMap } from "./GameMap"; import { TileIndexer } from "./TileIndexer"; -import { Unit } from "../Unit"; +import { Unit } from "../unit/Unit"; import { City } from "../city/City"; import fs from "fs"; import YAML from "yaml"; @@ -42,9 +42,7 @@ export class Tile { public static getAllTileStats() { if (!Tile.allTileStats) { // Load available civilizations from config file - const tileYAMLData = YAML.parse( - fs.readFileSync("./config/tiles.yml", "utf-8") - ); + const tileYAMLData = YAML.parse(fs.readFileSync("./config/tiles.yml", "utf-8")); //Convert civsData from YAML to JSON: Tile.allTileStats = JSON.parse(JSON.stringify(tileYAMLData.tiles)); } @@ -73,11 +71,7 @@ export class Tile { return this.riverSides; } - public setRiverSide( - side: number, - value: boolean, - cacheEntry = true - ): Map { + public setRiverSide(side: number, value: boolean, cacheEntry = true): Map { const tilesEffected = new Map(); this.riverSides[side] = value; @@ -99,10 +93,7 @@ export class Tile { const oppositeTileSide = oppositeSides[side]; // The side that matches this tile's river-side // Set the opposite river-side too, since it's also on that adjacent tile. - if ( - oppositeTile && - oppositeTile.getRiverSides()[oppositeTileSide] !== value - ) { + if (oppositeTile && oppositeTile.getRiverSides()[oppositeTileSide] !== value) { oppositeTile.getRiverSides()[oppositeTileSide] = value; tilesEffected.set(oppositeTile, oppositeTileSide); } @@ -120,7 +111,7 @@ export class Tile { x: this.x, y: this.y, movementCost: this.getMovementCost(), - city: this.city ? this.city.getJSON() : null, + city: this.city ? this.city.getJSON() : null }; } @@ -186,9 +177,7 @@ export class Tile { } public replaceTileType(oldTileType: string, newTileType: string) { - this.tileTypes = this.tileTypes.map((type) => - type === oldTileType ? newTileType : type - ); + this.tileTypes = this.tileTypes.map((type) => (type === oldTileType ? newTileType : type)); TileIndexer.removeTileType(oldTileType, this); TileIndexer.addTileType(newTileType, this); @@ -204,11 +193,7 @@ export class Tile { return this.tileTypes.includes(tileType); } - public applyRiverSide(options: { - previousTile?: Tile; - nextTile?: Tile; - originTile?: boolean; - }) { + public applyRiverSide(options: { previousTile?: Tile; nextTile?: Tile; originTile?: boolean }) { //console.log("Applying river side for: [" + this.x + "," + this.y + "]"); /** * Rules: @@ -251,8 +236,7 @@ export class Tile { for (const validRiverConnection of validRiverConnections) { const tilesSet = new Map(); - const adjTileOfRiverConnection = - this.getAdjacentTiles()[validRiverConnection]; + const adjTileOfRiverConnection = this.getAdjacentTiles()[validRiverConnection]; if (!adjTileOfRiverConnection) continue; @@ -271,10 +255,7 @@ export class Tile { currentRiverSide = validRiverConnection; - const smallestRiverPathToNextTile = this.flowRiverToNextTile( - currentRiverSide, - nextTile - ); + const smallestRiverPathToNextTile = this.flowRiverToNextTile(currentRiverSide, nextTile); if (!smallestRiverPathToNextTile) { GameMap.getInstance().restoreCachedRiverSides(); @@ -302,10 +283,7 @@ export class Tile { // TODO: Iterate through potentialRiverPaths & choose the smallest path let smallestRiverConnectionIndex = 0; let smallestRiverSidesSet = Infinity; - for (const [ - validRiverConnection, - tilesSet, - ] of potentialRiverPaths.entries()) { + for (const [validRiverConnection, tilesSet] of potentialRiverPaths.entries()) { let totalRiverSidesSet = 0; for (const riverSideSet of tilesSet.values()) { @@ -318,9 +296,7 @@ export class Tile { } } - for (const [tile, riverSides] of potentialRiverPaths - .get(smallestRiverConnectionIndex) - .entries()) { + for (const [tile, riverSides] of potentialRiverPaths.get(smallestRiverConnectionIndex).entries()) { for (const riverSide of riverSides) { if (!tile.getAdjacentTiles()[riverSide].isWater()) { tile.setRiverSide(riverSide, true); //MAYBE BUG here @@ -332,10 +308,7 @@ export class Tile { // If this tile already connects to the previous tile (with the river), then just flow to the next tile. if (connectedToPreviousTile) { - const smallestRiverPathToNextTile = this.flowRiverToNextTile( - currentRiverSide, - nextTile - ); + const smallestRiverPathToNextTile = this.flowRiverToNextTile(currentRiverSide, nextTile); if (!smallestRiverPathToNextTile) return; @@ -347,10 +320,7 @@ export class Tile { } } - private flowRiverToNextTile( - startingRiverSide: number, - nextTile: Tile - ): number[] { + private flowRiverToNextTile(startingRiverSide: number, nextTile: Tile): number[] { // Do this rotating left or right, pick smallest amount of tile-sides set. const orientations = new Map(); @@ -359,17 +329,14 @@ export class Tile { let prevRiverSide = startingRiverSide; GameMap.getInstance().cacheSetRiverSides(); - while ( - nextTile && - !this.riverConnectsToTile(startingRiverSide, nextTile) - ) { + while (nextTile && !this.riverConnectsToTile(startingRiverSide, nextTile)) { //console.log( // "No connection to next tile as: [" + this.x + "," + this.y + "]" //); const potentialRiverConnections = this.getConnectedRiverSides({ emptySidesOnly: true, - ofRiverSide: startingRiverSide, + ofRiverSide: startingRiverSide }); const validRiverConnections = []; @@ -393,10 +360,7 @@ export class Tile { return []; } - const side = - orientation === "left" - ? Math.min(...validRiverConnections) - : Math.max(...validRiverConnections); + const side = orientation === "left" ? Math.min(...validRiverConnections) : Math.max(...validRiverConnections); // Choose either the smallest connection index or largest. Count how many potential connections we make, choose the smallest of the two. //console.log("Setting connected side: " + side + " - " + orientation); @@ -448,9 +412,7 @@ export class Tile { // Our issue is we don't know which riverside from the specified tile is connecting INTO us (this). //this.getAllConnectedRiverSides(undefined).get(tile) for (const riverSide of connectingRiverSides) { - validConnections = validConnections.concat( - tile.getAllConnectedRiverSides(riverSide).get(this) - ); + validConnections = validConnections.concat(tile.getAllConnectedRiverSides(riverSide).get(this)); } return validConnections; } @@ -472,9 +434,7 @@ export class Tile { if (!this.getAllConnectedRiverSides(riverSide).get(tile)) return false; // Ensure at least one river-side in our comparing tile is inside our valid connection list. - for (const validConnectionSide of this.getAllConnectedRiverSides( - riverSide - ).get(tile)) { + for (const validConnectionSide of this.getAllConnectedRiverSides(riverSide).get(tile)) { if (riverSidesOfTile.includes(validConnectionSide)) return true; } } @@ -543,7 +503,7 @@ export class Tile { this, this.getConnectedRiverSides({ ofRiverSide: riverSide, - emptySidesOnly: false, + emptySidesOnly: false }) ); return allConnRiverSides; @@ -555,10 +515,7 @@ export class Tile { */ //FIXME: This doesn't work sometimes? - public getConnectedRiverSides(options: { - ofRiverSide?: number; - emptySidesOnly: boolean; - }): number[] { + public getConnectedRiverSides(options: { ofRiverSide?: number; emptySidesOnly: boolean }): number[] { if (!this.hasRiver()) { //console.log( // "Warning: Tried to get connected river-sides of tile w/ no river" @@ -571,7 +528,7 @@ export class Tile { [1, 2, 3], [2, 3, 4], [3, 4, 5], - [4, 5, 0], + [4, 5, 0] ]; const adjacentSides: number[] = []; @@ -640,7 +597,7 @@ export class Tile { [1, 2, 3], [2, 3, 4], [3, 4, 5], - [4, 5, 0], + [4, 5, 0] ]; const adjIndexes = sides[riverSide]; @@ -675,9 +632,7 @@ export class Tile { } if (unusedSides.length < 1) { - console.log( - "Warning: Tried to apply random river side to all occupied sides..." - ); + console.log("Warning: Tried to apply random river side to all occupied sides..."); return; } @@ -766,10 +721,7 @@ export class Tile { //TODO: Function works but naming is confusing, we don't use grid variables in server. public static gridDistance(tile1: Tile, tile2: Tile) { - return Math.sqrt( - Math.pow(tile2.getX() - tile1.getX(), 2) + - Math.pow(tile2.getY() - tile1.getY(), 2) - ); + return Math.sqrt(Math.pow(tile2.getX() - tile1.getX(), 2) + Math.pow(tile2.getY() - tile1.getY(), 2)); } public static getWeight(tile1: Tile, tile2: Tile): number { @@ -788,7 +740,7 @@ export class Tile { { faith: 0 }, { culture: 0 }, { food: 0 }, - { morale: 0 }, + { morale: 0 } ]; for (const tileType of this.tileTypes) { const tileTypeStats = Tile.getAllTileStats()[tileType]; diff --git a/server/src/state/type/InGameState.ts b/server/src/state/type/InGameState.ts index a41b81fc..01131e96 100644 --- a/server/src/state/type/InGameState.ts +++ b/server/src/state/type/InGameState.ts @@ -2,12 +2,13 @@ import { Game } from "../../Game"; import { ServerEvents } from "../../Events"; import { State } from "../State"; import { GameMap } from "../../map/GameMap"; -import { Unit } from "../../Unit"; +import { Unit } from "../../unit/Unit"; import { City } from "../../city/City"; import { Job, gracefulShutdown, scheduleJob } from "node-schedule"; import fs from "fs"; import YAML from "yaml"; +import { UnitActions } from "../../unit/UnitActions"; export class InGameState extends State { private turnTimeJob: Job; @@ -22,16 +23,16 @@ export class InGameState extends State { this.turnTime = 0; // Load available buildings from config file - const buildingsYMLData = YAML.parse( - fs.readFileSync("./config/buildings.yml", "utf-8") - ); + const buildingsYMLData = YAML.parse(fs.readFileSync("./config/buildings.yml", "utf-8")); //Convert civsData from YAML to JSON: this.cityBuildings = JSON.parse(JSON.stringify(buildingsYMLData.buildings)); // Set loading screen for players - Game.getPlayers().forEach((player) => { - player.sendNetworkEvent({ event: "setScene", scene: "loading_scene" }); - }); + Game.getInstance() + .getPlayers() + .forEach((player) => { + player.sendNetworkEvent({ event: "setScene", scene: "loading_scene" }); + }); GameMap.init(); @@ -46,112 +47,87 @@ export class InGameState extends State { JSON.stringify({ event: "messageBox", messageName: "gameInProgress", - message: "Connection Error: Game in progress.", + message: "Connection Error: Game in progress." }) ); websocket.close(); - }, + } }); ServerEvents.on({ eventName: "requestMap", parentObject: this, callback: (data, websocket) => { - const player = Game.getPlayerFromWebsocket(websocket); + const player = Game.getInstance().getPlayerFromWebsocket(websocket); GameMap.getInstance().sendMapChunksToPlayer(player); - }, + } }); - Game.getPlayers().forEach((player) => { - const badTileTypes = [ - "ocean", - "shallow_ocean", - "freshwater", - "mountain", - "snow", - "snow_hill", - "tundra", - "tundra_hill", - ]; - - const spawnTile = GameMap.getInstance().getRandomTileWith({ - avoidTileTypes: badTileTypes, - }); + Game.getInstance() + .getPlayers() + .forEach((player) => { + const badTileTypes = [ + "ocean", + "shallow_ocean", + "freshwater", + "mountain", + "snow", + "snow_hill", + "tundra", + "tundra_hill" + ]; + + const spawnTile = GameMap.getInstance().getRandomTileWith({ + avoidTileTypes: badTileTypes + }); - //FIXME: Make Unit have a createSettler() method? - spawnTile.addUnit( - new Unit({ - name: "settler", - player: player, - tile: spawnTile, - actions: [ - { - name: "settle", - icon: "SETTLE_ICON", - requirements: ["awayFromCity", "movement"], - desc: "Settle City", - onAction: (unit: Unit) => { - console.log("ACTION: Act on settle city."); - - const tile = unit.getTile(); - unit.delete(); - - const city = new City({ player: player, tile: tile }); - tile.setCity(city); - player.getCities().push(city); - - Game.getPlayers().forEach((gamePlayer) => { - gamePlayer.sendNetworkEvent({ - event: "newCity", - ...city.getJSON(), - }); - }); - - // Add palace to city if it's the first city - if (player.getCities().length < 2) { - city.addBuilding("palace"); - } - }, - }, - ], - }) - ); - - //TODO: Re-choose spawn location if warrior can't spawn - for (const adjTile of spawnTile.getAdjacentTiles()) { - if (!adjTile || adjTile.containsTileTypes(badTileTypes)) continue; - - adjTile.addUnit( + //FIXME: Make Unit have a createSettler() method? + spawnTile.addUnit( new Unit({ - name: "warrior", + name: "settler", player: player, - tile: adjTile, - attackType: "melee", - actions: [], + tile: spawnTile, + actions: [UnitActions.settleCity()] }) ); - break; - } - player.onLoadedIn(() => { - player.zoomToLocation(spawnTile.getX(), spawnTile.getY(), 7); + //TODO: Re-choose spawn location if warrior can't spawn + for (const adjTile of spawnTile.getAdjacentTiles()) { + if (!adjTile || adjTile.containsTileTypes(badTileTypes)) continue; + + adjTile.addUnit( + new Unit({ + name: "warrior", + player: player, + tile: adjTile, + attackType: "melee", + actions: [] + }) + ); + break; + } - let allLoaded = true; - // Trigger allPlayersLoaded event - Game.getPlayers().forEach((player) => { - if (!player.isLoadedIn()) { - allLoaded = false; + player.onLoadedIn(() => { + player.zoomToLocation(spawnTile.getX(), spawnTile.getY(), 7); + + let allLoaded = true; + // Trigger allPlayersLoaded event + Game.getInstance() + .getPlayers() + .forEach((player) => { + if (!player.isLoadedIn()) { + allLoaded = false; + } + }); + + if (allLoaded) { + ServerEvents.call("allPlayersLoaded", {}); } }); - if (allLoaded) { - ServerEvents.call("allPlayersLoaded", {}); - } + player.sendNetworkEvent({ event: "setScene", scene: "in_game" }); }); - player.sendNetworkEvent({ event: "setScene", scene: "in_game" }); - }); - ServerEvents.on({ eventName: "allPlayersLoaded", parentObject: this, @@ -159,36 +135,35 @@ export class InGameState extends State { // Increment the turn this.incrementTurn(); this.beginTurnTimer(); - }, + } }); ServerEvents.on({ eventName: "nextTurnRequest", parentObject: this, callback: (data, websocket) => { - const player = Game.getPlayerFromWebsocket(websocket); + const player = Game.getInstance().getPlayerFromWebsocket(websocket); player.setRequestedNextTurn(data["value"]); - const allRequested = Array.from(Game.getPlayers().values()).every( - (player) => player.hasRequestedNextTurn() + const allRequested = Array.from(Game.getInstance().getPlayers().values()).every((player) => + player.hasRequestedNextTurn() ); if (allRequested) { this.incrementTurn(); - Game.getPlayers().forEach((player) => { - player.setRequestedNextTurn(false); - }); + Game.getInstance() + .getPlayers() + .forEach((player) => { + player.setRequestedNextTurn(false); + }); } - }, + } }); } public getBuildingDataByName(name: string) { for (const building of this.cityBuildings) { - if ( - (building.name as string).toLocaleLowerCase() === - name.toLocaleLowerCase() - ) { + if ((building.name as string).toLocaleLowerCase() === name.toLocaleLowerCase()) { return building; } } @@ -200,13 +175,15 @@ export class InGameState extends State { private beginTurnTimer() { this.turnTimeJob = scheduleJob("* * * * * *", () => { // Send turn time increment to player - Game.getPlayers().forEach((player) => { - player.sendNetworkEvent({ - event: "turnTimeDecrement", - turn: this.currentTurn, - turnTime: this.turnTime, + Game.getInstance() + .getPlayers() + .forEach((player) => { + player.sendNetworkEvent({ + event: "turnTimeDecrement", + turn: this.currentTurn, + turnTime: this.turnTime + }); }); - }); //FIXME: WAIT for all players timers to be 0! if (this.turnTime <= 0) { @@ -222,13 +199,15 @@ export class InGameState extends State { this.currentTurn++; this.turnTime = this.totalTurnTime; - Game.getPlayers().forEach((player) => { - player.sendNetworkEvent({ - event: "newTurn", - turn: this.currentTurn, - turnTime: this.turnTime, + Game.getInstance() + .getPlayers() + .forEach((player) => { + player.sendNetworkEvent({ + event: "newTurn", + turn: this.currentTurn, + turnTime: this.turnTime + }); }); - }); ServerEvents.call("nextTurn", { turn: this.currentTurn }); } diff --git a/server/src/state/type/LobbyState.ts b/server/src/state/type/LobbyState.ts index 109d91a1..a9c51fe9 100644 --- a/server/src/state/type/LobbyState.ts +++ b/server/src/state/type/LobbyState.ts @@ -16,9 +16,7 @@ export class LobbyState extends State { playerIndex = 1; // Load available civilizations from config file - const civYAMLData = YAML.parse( - fs.readFileSync("./config/civilizations.yml", "utf-8") - ); + const civYAMLData = YAML.parse(fs.readFileSync("./config/civilizations.yml", "utf-8")); //Convert civsData from YAML to JSON: this.playableCivs = JSON.parse(JSON.stringify(civYAMLData.civilizations)); @@ -33,25 +31,25 @@ export class LobbyState extends State { console.log(playerName + " has joined the lobby"); const newPlayer = new Player(playerName, websocket); - Game.getPlayers().set(playerName, newPlayer); + Game.getInstance().getPlayers().set(playerName, newPlayer); // Send playerJoin data to other connected players - for (const player of Array.from(Game.getPlayers().values())) { + for (const player of Array.from(Game.getInstance().getPlayers().values())) { player.sendNetworkEvent({ event: "playerJoin", - playerName: playerName, + playerName: playerName }); } newPlayer.sendNetworkEvent({ event: "setScene", scene: "lobby" }); - }, + } }); ServerEvents.on({ eventName: "availableCivs", parentObject: this, callback: (_, websocket) => { - const player = Game.getPlayerFromWebsocket(websocket); + const player = Game.getInstance().getPlayerFromWebsocket(websocket); const playableCivs = []; //Extract name and icon_name from playableCivs: @@ -61,16 +59,16 @@ export class LobbyState extends State { player.sendNetworkEvent({ event: "availableCivs", - civs: playableCivs, + civs: playableCivs }); - }, + } }); ServerEvents.on({ eventName: "civInfo", parentObject: this, callback: (data, websocket) => { - const player = Game.getPlayerFromWebsocket(websocket); + const player = Game.getInstance().getPlayerFromWebsocket(websocket); // Get civ from this.playerCivs JSON list: const civilization = this.getCivByName(data["name"]); @@ -83,31 +81,33 @@ export class LobbyState extends State { start_bias_desc: civilization.start_bias_desc, unique_unit_descs: civilization.unique_unit_descs, unique_building_descs: civilization.unique_building_descs, - ability_descs: civilization.ability_descs, + ability_descs: civilization.ability_descs }); } - }, + } }); ServerEvents.on({ eventName: "selectCiv", parentObject: this, callback: (data, websocket) => { - const player = Game.getPlayerFromWebsocket(websocket); + const player = Game.getInstance().getPlayerFromWebsocket(websocket); //TODO: Check if this civ is already selected. const civilization = this.getCivByName(data["name"]); player.setCivilizationData(civilization); - Game.getPlayers().forEach((gamePlayer) => { - gamePlayer.sendNetworkEvent({ - event: "selectCiv", - name: civilization.name, - playerName: player.getName(), - civData: civilization, + Game.getInstance() + .getPlayers() + .forEach((gamePlayer) => { + gamePlayer.sendNetworkEvent({ + event: "selectCiv", + name: civilization.name, + playerName: player.getName(), + civData: civilization + }); }); - }); - }, + } }); } @@ -124,22 +124,26 @@ export class LobbyState extends State { public onDestroyed() { //Assign players w/o a civ a non-assigned random civilization: - Game.getPlayers().forEach((player) => { - if (!player.getCivilizationData()) { - player.setCivilizationData(this.getRandomNonAssignedCiv()); - } - }); + Game.getInstance() + .getPlayers() + .forEach((player) => { + if (!player.getCivilizationData()) { + player.setCivilizationData(this.getRandomNonAssignedCiv()); + } + }); return super.onDestroyed(); } private getRandomNonAssignedCiv(): Record { const assignedCivs = []; - Game.getPlayers().forEach((player) => { - if (player.getCivilizationData()) { - assignedCivs.push(player.getCivilizationData()); - } - }); + Game.getInstance() + .getPlayers() + .forEach((player) => { + if (player.getCivilizationData()) { + assignedCivs.push(player.getCivilizationData()); + } + }); const nonAssignedCivs = this.playableCivs.filter((civ) => { return !assignedCivs.includes(civ); }); diff --git a/server/src/Unit.ts b/server/src/unit/Unit.ts similarity index 77% rename from server/src/Unit.ts rename to server/src/unit/Unit.ts index b6d0bdd7..3ee539e9 100644 --- a/server/src/Unit.ts +++ b/server/src/unit/Unit.ts @@ -1,8 +1,16 @@ -import { ServerEvents } from "./Events"; -import { Game } from "./Game"; -import { Player } from "./Player"; -import { GameMap } from "./map/GameMap"; -import { Tile } from "./map/Tile"; +import { ServerEvents } from "../Events"; +import { Game } from "../Game"; +import { Player } from "../Player"; +import { GameMap } from "../map/GameMap"; +import { Tile } from "../map/Tile"; + +export interface UnitAction { + name: string; + icon: string; + requirements: string[]; + desc: string; + onAction: (unit: Unit) => void; +} export interface UnitOptions { name: string; @@ -10,13 +18,7 @@ export interface UnitOptions { player: Player; attackType?: string; defaultMoveDistance?: number; - actions: { - name: string; - icon: string; - requirements: string[]; - desc: string; - onAction: (unit: Unit) => void; - }[]; + actions: UnitAction[]; } export class Unit { @@ -55,23 +57,16 @@ export class Unit { eventName: "moveUnit", parentObject: this, callback: (data, websocket) => { - const targetTile = - GameMap.getInstance().getTiles()[data["targetX"]][data["targetY"]]; - const player = Game.getPlayerFromWebsocket(websocket); + const targetTile = GameMap.getInstance().getTiles()[data["targetX"]][data["targetY"]]; + const player = Game.getInstance().getPlayerFromWebsocket(websocket); - if ( - this.id !== data["id"] || - this.tile === targetTile || - this.player != player - ) - return; + if (this.id !== data["id"] || this.tile === targetTile || this.player != player) return; // Move the furthest we can possibly go, and queue the rest of tiles for next turn. //FIXME: Allow this function to use our existing queuedMovementTiles, // This should stop the path from being redrawn every turn. - const [arrivedTile, remainingTiles, remainingMovement] = - this.getMovementTowardsTargetTile(targetTile); + const [arrivedTile, remainingTiles, remainingMovement] = this.getMovementTowardsTargetTile(targetTile); if (!arrivedTile) return; @@ -79,17 +74,16 @@ export class Unit { previousTile: this.tile, targetTile: arrivedTile, remainingTiles: remainingTiles, - remainingMovement: remainingMovement, + remainingMovement: remainingMovement }); - }, + } }); ServerEvents.on({ eventName: "unitAction", parentObject: this, callback: (data, websocket) => { - const unitTile = - GameMap.getInstance().getTiles()[data["unitX"]][data["unitY"]]; + const unitTile = GameMap.getInstance().getTiles()[data["unitX"]][data["unitY"]]; if (this.tile !== unitTile) return; @@ -97,7 +91,7 @@ export class Unit { if (action) { action.onAction(this); } - }, + } }); ServerEvents.on({ @@ -109,7 +103,7 @@ export class Unit { if (this.queuedMovementTiles.length > 0) { this.moveWithMovementQueue(); } - }, + } }); } @@ -137,7 +131,7 @@ export class Unit { unitX: previousTile.getX(), unitY: previousTile.getY(), targetX: targetTile.getX(), - targetY: targetTile.getY(), + targetY: targetTile.getY() }; // Store a list of queued tiles if we have remaining tiles @@ -150,17 +144,21 @@ export class Unit { } // Send back packet, telling client server updated the unit location - Game.getPlayers().forEach((player) => { - player.sendNetworkEvent(dataPacket); - }); + Game.getInstance() + .getPlayers() + .forEach((player) => { + player.sendNetworkEvent(dataPacket); + }); } private moveWithMovementQueue() { const targetTile = this.getTargetQueuedTile(); const existingPath = [this.tile, ...this.queuedMovementTiles]; - const [arrivedTile, remainingTiles, remainingMovement] = - this.getMovementTowardsTargetTile(targetTile, existingPath); + const [arrivedTile, remainingTiles, remainingMovement] = this.getMovementTowardsTargetTile( + targetTile, + existingPath + ); if (!arrivedTile) return; @@ -168,14 +166,11 @@ export class Unit { previousTile: this.tile, targetTile: arrivedTile, remainingTiles, - remainingMovement: remainingMovement, + remainingMovement: remainingMovement }); } - private getMovementTowardsTargetTile( - tile: Tile, - existingPath?: Tile[] - ): [Tile, Tile[], number] { + private getMovementTowardsTargetTile(tile: Tile, existingPath?: Tile[]): [Tile, Tile[], number] { const shortestPath = existingPath ?? GameMap.getInstance().constructShortestPath( @@ -194,8 +189,7 @@ export class Unit { // Traverse tile by tile, removing our movement incrementally. for (let i = 0; i < shortestPath.length; i++) { const currentTile = shortestPath[i]; - const nextTile = - i + 1 >= shortestPath.length ? undefined : shortestPath[i + 1]; + const nextTile = i + 1 >= shortestPath.length ? undefined : shortestPath[i + 1]; if (!nextTile) continue; @@ -212,9 +206,7 @@ export class Unit { traversedTiles.push(nextTile); } - const remainingTiles: Tile[] = shortestPath.filter( - (tile) => !traversedTiles.includes(tile) - ); + const remainingTiles: Tile[] = shortestPath.filter((tile) => !traversedTiles.includes(tile)); return [traversedTiles.pop(), remainingTiles, remainingMovement]; } @@ -223,14 +215,16 @@ export class Unit { this.tile.removeUnit(this); ServerEvents.removeCallbacksByParentObject(this); - Game.getPlayers().forEach((player) => { - player.sendNetworkEvent({ - event: "removeUnit", - id: this.id, - unitX: this.tile.getX(), - unitY: this.tile.getY(), + Game.getInstance() + .getPlayers() + .forEach((player) => { + player.sendNetworkEvent({ + event: "removeUnit", + id: this.id, + unitX: this.tile.getX(), + unitY: this.tile.getY() + }); }); - }); } public getPlayer() { @@ -244,7 +238,7 @@ export class Unit { public asJSON() { const queuedTilesJSON = this.queuedMovementTiles.map((tile) => ({ x: tile.getX(), - y: tile.getY(), + y: tile.getY() })); return { @@ -257,7 +251,7 @@ export class Unit { actions: this.getUnitActionsJSON(), queuedTiles: queuedTilesJSON, remainingMovement: this.availableMovement, - defaultMoveDistance: this.defaultMoveDistance, + defaultMoveDistance: this.defaultMoveDistance }; } @@ -272,15 +266,14 @@ export class Unit { } public getUnitActionsJSON() { - const actions: { name: string; requirements: string[]; desc: string }[] = - []; + const actions: { name: string; requirements: string[]; desc: string }[] = []; actions.push( ...this.actions.map(({ name, icon, requirements, desc }) => ({ name, icon, requirements, - desc, + desc })) ); return actions; diff --git a/server/src/unit/UnitActions.ts b/server/src/unit/UnitActions.ts new file mode 100644 index 00000000..672af045 --- /dev/null +++ b/server/src/unit/UnitActions.ts @@ -0,0 +1,41 @@ +import { Game } from "../Game"; +import { City } from "../city/City"; +import { Unit, UnitAction } from "./Unit"; + +export class UnitActions { + public static settleCity(): UnitAction { + return { + name: "settle", + icon: "SETTLE_ICON", + requirements: ["awayFromCity", "movement"], + desc: "Settle City", + onAction: (unit: Unit) => { + console.log("ACTION: Act on settle city."); + + const tile = unit.getTile(); + const player = unit.getPlayer(); + unit.delete(); + + const city = new City({ player: player, tile: tile }); + tile.setCity(city); + player.getCities().push(city); + + Game.getInstance() + .getPlayers() + .forEach((gamePlayer) => { + gamePlayer.sendNetworkEvent({ + event: "newCity", + ...city.getJSON() + }); + }); + + // Add palace to city if it's the first city + if (player.getCities().length < 2) { + city.addBuilding("palace"); + } + } + }; + } + + public createReligion() {} +}