diff --git a/gameserver/commands/OnSoldierAttackCommand.ts b/gameserver/commands/OnSoldierAttackCommand.ts index 48f9161..37cad91 100644 --- a/gameserver/commands/OnSoldierAttackCommand.ts +++ b/gameserver/commands/OnSoldierAttackCommand.ts @@ -17,21 +17,25 @@ export class OnSoldierAttackCommand extends Command< targetPlayerId: string; targetUnitId: string; }>) { - const attacker = this.state.getPlayer(client.id); - const victim = this.state.getPlayer(message.targetPlayerId); - if (!attacker || !victim) { - return; - } - const targetSoldier = victim.getSoldier(message.targetUnitId); - if (!targetSoldier) { - return; - } + try { + const attacker = this.state.getPlayer(client.id); + const victim = this.state.getPlayer(message.targetPlayerId); + if (!attacker || !victim) { + return; + } + const targetSoldier = victim.getSoldier(message.targetUnitId); + if (!targetSoldier) { + return; + } - const attackerUnits = attacker - .getAllSoldiers() - .filter((soldier) => message.soldiers.includes(soldier.id)); - attackerUnits.forEach((unit: SoldierState) => { - unit.attackUnit(targetSoldier, gameManager!); - }); + const attackerUnits = attacker + .getAllSoldiers() + .filter((soldier) => message.soldiers.includes(soldier.id)); + attackerUnits.forEach((unit: SoldierState) => { + unit.attackUnit(targetSoldier, gameManager!); + }); + } catch (error) { + console.error(error); + } } } diff --git a/gameserver/commands/OnSoldierMoveCommand.ts b/gameserver/commands/OnSoldierMoveCommand.ts index 930f4bf..d7862c2 100644 --- a/gameserver/commands/OnSoldierMoveCommand.ts +++ b/gameserver/commands/OnSoldierMoveCommand.ts @@ -17,21 +17,26 @@ export class OnSoldierMoveCommand extends Command { expectedPositionX: number; expectedPositionY: number; }>) { - const sceneSize = gameManager?.scene.getDimension(); - if (!sceneSize) return; - - const soldierObjects = message.soldierIds - .map((id) => this.state.getPlayer(client.sessionId)?.getSoldier(id)) - .filter(Boolean) as SoldierState[]; - if (soldierObjects.length === 0) return; - const offset = 96; - const gridFormation = new GroupFormation( - soldierObjects, - offset, - new SAT.Box(new SAT.Vector(), sceneSize.x, sceneSize.y) - ); - gridFormation.calculatePositions( - new SAT.Vector(message.expectedPositionX, message.expectedPositionY) - ); + try { + const sceneSize = gameManager?.scene.getDimension(); + if (!sceneSize) { + throw new Error(`sceneSize not found`); + } + const soldierObjects = message.soldierIds + .map((id) => this.state.getPlayer(client.sessionId)?.getSoldier(id)) + .filter(Boolean) as SoldierState[]; + if (soldierObjects.length === 0) return; + const offset = 96; + const gridFormation = new GroupFormation( + soldierObjects, + offset, + new SAT.Box(new SAT.Vector(), sceneSize.x, sceneSize.y) + ); + gridFormation.calculatePositions( + new SAT.Vector(message.expectedPositionX, message.expectedPositionY) + ); + } catch (error) { + console.error(error); + } } } diff --git a/package-lock.json b/package-lock.json index 61fb5ea..462e706 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,7 +31,7 @@ "npx": "^10.2.2", "phaser": "^3.70.0", "phaser-ui-tools": "^2.0.0-beta", - "phaser3-rex-plugins": "^1.1.82", + "phaser3-rex-plugins": "^1.80.2", "quadtree-lib": "^1.0.9", "sat": "^0.9.0", "socket.io": "^4.4.1", @@ -4324,9 +4324,9 @@ } }, "node_modules/i18next-http-backend": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.4.3.tgz", - "integrity": "sha512-jo2M03O6n1/DNb51WSQ8PsQ0xEELzLZRdYUTbf17mLw3rVwnJF9hwNgMXvEFSxxb+N8dT+o0vtigA6s5mGWyPA==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.5.1.tgz", + "integrity": "sha512-+rNX1tghdVxdfjfPt0bI1sNg5ahGW9kA7OboG7b4t03Fp69NdDlRIze6yXhIbN8rbHxJ8IP4dzRm/okZ15lkQg==", "dependencies": { "cross-fetch": "4.0.0" } @@ -10569,13 +10569,13 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" }, "node_modules/phaser3-rex-plugins": { - "version": "1.60.10", - "resolved": "https://registry.npmjs.org/phaser3-rex-plugins/-/phaser3-rex-plugins-1.60.10.tgz", - "integrity": "sha512-BiwFPPGSIvPG1jMLCjMd3Im7UrjPmU9103BF//5q9ns/QVbLl54XwoHoR4FYx+iCQEYsUV53x9ABGVPlNETyDQ==", + "version": "1.80.2", + "resolved": "https://registry.npmjs.org/phaser3-rex-plugins/-/phaser3-rex-plugins-1.80.2.tgz", + "integrity": "sha512-ZPA4c47WQRU6rqLdlOFizGU+ljtP4C2blhcpbYSsNMqNRHD7o8vRBEzEhl8w6CMGvcy+eVoA6v10cyL4eIZARw==", "dependencies": { "eventemitter3": "^3.1.2", "i18next": "^22.5.1", - "i18next-http-backend": "^2.4.1", + "i18next-http-backend": "^2.5.0", "js-yaml": "^4.1.0", "mustache": "^4.2.0", "papaparse": "^5.4.1", diff --git a/package.json b/package.json index ecc9865..c21a7ab 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "npx": "^10.2.2", "phaser": "^3.70.0", "phaser-ui-tools": "^2.0.0-beta", - "phaser3-rex-plugins": "^1.1.82", + "phaser3-rex-plugins": "^1.80.2", "quadtree-lib": "^1.0.9", "sat": "^0.9.0", "socket.io": "^4.4.1", diff --git a/public/game.ts b/public/game.ts index ebb4889..26c08f2 100644 --- a/public/game.ts +++ b/public/game.ts @@ -7,6 +7,7 @@ import { PlayerStatisticHUD } from "./scenes/PlayerStatisticHUD"; import { SessionLobbyScene } from "./scenes/SessionLobbyScene"; import { SessionBrowserScene } from "./scenes/SessionBrowserScene"; import SpinnerPlugin from "phaser3-rex-plugins/templates/spinner/spinner-plugin.js"; + import Phaser from "phaser"; const config = { type: Phaser.WEBGL, diff --git a/public/scenes/BaseScene.ts b/public/scenes/BaseScene.ts index 8742b1b..2dc2741 100644 --- a/public/scenes/BaseScene.ts +++ b/public/scenes/BaseScene.ts @@ -4,17 +4,13 @@ import { NetworkManager } from "../NetworkManager"; import { ClientStateManager } from "../ClientStateManager"; import CONSTANT from "../constant"; import { nanoid } from "nanoid"; +interface Destroyable { + destroy: Function; +} +type ManagedTypes = Destroyable; export class BaseScene extends Phaser.Scene { - objectSet: Map< - string, - | Phaser.GameObjects.Graphics - | PlayerCastle - | Phaser.Cameras.Controls.SmoothedKeyControl - | Phaser.GameObjects.Text - | Phaser.GameObjects.DOMElement - | Phaser.GameObjects.Image - >; + objectSet: Map; registeredInputEvents: Set; registeredSceneEvents: Set; @@ -73,29 +69,13 @@ export class BaseScene extends Phaser.Scene { } } - AddObject< - T extends - | Phaser.GameObjects.Graphics - | PlayerCastle - | Phaser.Cameras.Controls.SmoothedKeyControl - | Phaser.GameObjects.Text - | Phaser.GameObjects.DOMElement - | Phaser.GameObjects.Image - >(newObject: T, key?: string): T { + AddObject(newObject: T, key?: string): T { let mKey = nanoid(); this.objectSet.set(key || mKey, newObject); return newObject; } - GetObject< - T extends - | Phaser.GameObjects.Graphics - | PlayerCastle - | Phaser.Cameras.Controls.SmoothedKeyControl - | Phaser.GameObjects.Text - | Phaser.GameObjects.DOMElement - | Phaser.GameObjects.Image - >(key: string) { + GetObject(key: string) { return this.objectSet.get(key) as T | undefined; } @@ -124,15 +104,7 @@ export class BaseScene extends Phaser.Scene { } // Recursively destroy an object, including any children if it's a group - DestroyObject< - T extends - | Phaser.GameObjects.Graphics - | PlayerCastle - | Phaser.GameObjects.Text - | Phaser.GameObjects.DOMElement - | Phaser.GameObjects.Image - | Phaser.Cameras.Controls.SmoothedKeyControl - >(obj: T) { + DestroyObject(obj: T) { if ((obj as any)?.type === "Group") obj.destroy(true); else obj.destroy(); } diff --git a/public/scenes/GameScene.ts b/public/scenes/GameScene.ts index 5a4aa24..8f8cd02 100644 --- a/public/scenes/GameScene.ts +++ b/public/scenes/GameScene.ts @@ -9,6 +9,8 @@ import SessionStateClientHelpers from "../helpers/SessionStateClientHelpers"; import { BaseSoldier } from "../soldiers/BaseSoldier"; import { Spearman } from "../soldiers/Spearman"; import { BaseScene } from "./BaseScene"; +import SpinnerPlugin from "phaser3-rex-plugins/templates/spinner/spinner-plugin.js"; + import $ from "jquery"; var selectorColor = 0xffff00; @@ -56,7 +58,7 @@ export class GameScene extends BaseScene { canvasWidth: number; canvasHeight: number; controls?: Phaser.Cameras.Controls.SmoothedKeyControl; - + rexSpinner: SpinnerPlugin.Spinner | undefined; constructor() { super(CONSTANT.SCENES.GAME); this.canvasWidth = 1962; @@ -88,10 +90,6 @@ export class GameScene extends BaseScene { [ownerPlayer.colorR, ownerPlayer.colorG, ownerPlayer.colorB], ownerPlayer.id ); - spearmen.setData("serverPosition", { - x: soldier.currentPositionX, - y: soldier.currentPositionY, - }); const playerSoldiersGameObject = this.data.get( "playerSoldiersGameObject" ) as Map; @@ -207,7 +205,6 @@ export class GameScene extends BaseScene { create() { networkManager = this.registry.get("networkManager") as NetworkManager; - const stylus = this.add.graphics(); stylus.setDepth(9999); diff --git a/public/scenes/MenuScene.ts b/public/scenes/MenuScene.ts index a1c554b..e513657 100644 --- a/public/scenes/MenuScene.ts +++ b/public/scenes/MenuScene.ts @@ -2,8 +2,12 @@ import CONSTANT from "../constant"; import { BaseScene } from "./BaseScene"; import { NetworkManager } from "../NetworkManager"; import { addBackgroundImage } from "../helpers/addBackgroundImage"; +import SpinnerPlugin from "phaser3-rex-plugins/templates/spinner/spinner-plugin.js"; + const URL = `${window.location.host}`; + export class MenuScene extends BaseScene { + rexSpinner: SpinnerPlugin | undefined; constructor() { super(CONSTANT.SCENES.MENU); console.log(URL); @@ -15,8 +19,24 @@ export class MenuScene extends BaseScene { this.scene.bringToTop(); this.load.html("playerForm", "../html/menu-form.html"); this.load.image("background", "../assets/background.png"); + this.load.scenePlugin({ + key: "rexSpinner", + url: SpinnerPlugin, + sceneKey: "rexSpinner", + }); } create() { + const spinner = this.rexSpinner!.add.spinner({ + width: 80, + height: 80, + duration: 500, + x: 80, + y: 80, + }); + spinner.setDepth(9999); + spinner.setVisible(false); + this.AddObject(spinner, "obj_spinner"); + let networkManager = this.registry.get("networkManager") as NetworkManager; addBackgroundImage(this, "background"); this.AddObject(this.add.text(100, 20, "War.IO"), "obj_introText"); @@ -35,11 +55,13 @@ export class MenuScene extends BaseScene { let playBtn = playerForm.getChildByName("btnJoin"); let createSessionBtn = playerForm.getChildByName("btnCreate"); const tutorialBtn = playerForm.getChildByName("btnTutorial"); - + let inputField = playerForm.getChildByName("nameInput"); inputField?.addEventListener("input", (event) => { - var inputName = playerForm.getChildByName("nameInput") as Element & { value: string }; + var inputName = ( + playerForm.getChildByName("nameInput") + ); if (!inputName) return; if (inputName.value !== "") { let name = inputName.value.trim().replace(" ", "-"); @@ -54,7 +76,7 @@ export class MenuScene extends BaseScene { event.stopPropagation(); this.scene.start(CONSTANT.SCENES.TUTORIAL); }); - + playerForm.addListener("click"); playerForm.on("click", function (event: any) { event.stopPropagation(); @@ -66,12 +88,17 @@ export class MenuScene extends BaseScene { }); createSessionBtn?.addEventListener("pointerdown", async (event) => { - event.stopPropagation(); - await this.onCreateSessionClick(); + try { + event.stopPropagation(); + + await this.onCreateSessionClick(); + } catch (error) { + console.log(error); + } }); this.AddSceneEvent("shutdown", (data: any) => { - console.log("shutdown ", data.config.key); + console.log(`[shutdown]: ${data.config.key}`); this.Destroy(); }); @@ -86,7 +113,9 @@ export class MenuScene extends BaseScene { const networkManager = this.registry.get( "networkManager" ) as NetworkManager; - var inputName = playerForm.getChildByName("nameInput") as Element & { value: string }; + var inputName = ( + playerForm.getChildByName("nameInput") + ); if (inputName?.nodeValue !== "") { let name = inputName?.value.trim().replace(" ", "-"); networkManager.setPlayerName(name || ""); @@ -109,7 +138,7 @@ export class MenuScene extends BaseScene { this.scene.start(CONSTANT.SCENES.MENU); }; //join session - await( + await ( this.registry.get("networkManager") as NetworkManager ).connectGameServer(`${URL}/${sessionId}`); } catch (err) { @@ -130,29 +159,23 @@ export class MenuScene extends BaseScene { "obj_playerForm" )?.getChildByName("nameInput") as Element & { value: string })!.value; const sessions = await networkManager.getAvailableSession(); - console.log('available sessions ', sessions); - } - catch(error) { - - } + console.log("available sessions ", sessions); + } catch (error) {} } async onCreateSessionClick() { try { - const networkManager = this.registry.get( - "networkManager" - ) as NetworkManager; + const networkManager = ( + this.registry.get("networkManager") + ); + const spinner = this.GetObject("obj_spinner"); + spinner.setVisible(true); if (!networkManager) { throw new Error("NetworkManager is not defined"); } - const playerName = (this.GetObject( "obj_playerForm" )?.getChildByName("nameInput") as Element & { value: string })!.value; - await networkManager?.hostAndJoinSession( - `${playerName}` - ); - - console.log("[client id] : ", networkManager?.getClientId()); + await networkManager?.hostAndJoinSession(`${playerName}`); this.scene.start(CONSTANT.SCENES.SESSIONLOBBY); } catch (error) { console.log(error); diff --git a/public/soldiers/BaseSoldier.ts b/public/soldiers/BaseSoldier.ts index b055574..65c0bb5 100644 --- a/public/soldiers/BaseSoldier.ts +++ b/public/soldiers/BaseSoldier.ts @@ -1,6 +1,7 @@ import CONSTANTS from "../constant"; import SessionStateClientHelpers from "../helpers/SessionStateClientHelpers"; import LoadingBar from "../LoadingBar"; +import SAT from 'sat'; import { NetworkManager } from "../NetworkManager"; const GAMEEVENTS = CONSTANTS.GAMEEVENTS; class BackgroundHighlight extends Phaser.GameObjects.Graphics { @@ -49,7 +50,7 @@ class BackgroundHighlight extends Phaser.GameObjects.Graphics { } } export class BaseSoldier extends Phaser.GameObjects.Sprite { - id: string; + readonly id: string; initialParam: any; color: number[]; expectedPositionX: number; @@ -58,6 +59,7 @@ export class BaseSoldier extends Phaser.GameObjects.Sprite { highlightBackground: BackgroundHighlight; DEBUGTEXT: Phaser.GameObjects.Text; playerId: string | null; + /** * @param {*} scene * @param {number} x @@ -81,7 +83,6 @@ export class BaseSoldier extends Phaser.GameObjects.Sprite { scene.add.existing(this); this.setInteractive(); this.id = id; - console.log("BASESOLDIER ", this.id); this.playerId = playerId; scene.events.on("update", this.update, this); @@ -123,7 +124,7 @@ export class BaseSoldier extends Phaser.GameObjects.Sprite { const networkManager = this?.scene?.registry?.get( "networkManager" ) as NetworkManager; - if(!networkManager) { + if (!networkManager) { console.log( `Could not find network-manager for soldier :${this.id}, most likely is deleted from scene (value of scene : ${this.scene})` ); @@ -131,15 +132,10 @@ export class BaseSoldier extends Phaser.GameObjects.Sprite { } const session = networkManager.getState(); - const clientId = networkManager.getClientId() - if(!session || !clientId) - return; - const playerState = SessionStateClientHelpers.getPlayer( - session, - clientId - ); - if(!playerState) - return; + const clientId = networkManager.getClientId(); + if (!session || !clientId) return; + const playerState = SessionStateClientHelpers.getPlayer(session, clientId); + if (!playerState) return; const soldierState = SessionStateClientHelpers.getSoldier( session,