From f64b4855e15526bb53cb11a3934deb4b7fa425f3 Mon Sep 17 00:00:00 2001 From: keshav2010 Date: Wed, 24 Jul 2024 05:52:45 +0530 Subject: [PATCH 1/2] fix: tile ownership changes --- .../commands/OnSpawnPointSelectCommand.ts | 3 +- gameserver/schema/PlayerState.ts | 1 - gameserver/schema/SessionState.ts | 6 +- gameserver/schema/SoldierState.ts | 23 ++--- gameserver/schema/TilemapState.ts | 88 ++++++++++++------- public/gameObjects/CaptureFlag.ts | 3 +- public/scenes/GameScene.ts | 5 +- 7 files changed, 76 insertions(+), 53 deletions(-) diff --git a/gameserver/commands/OnSpawnPointSelectCommand.ts b/gameserver/commands/OnSpawnPointSelectCommand.ts index 108c035..7dcb05e 100644 --- a/gameserver/commands/OnSpawnPointSelectCommand.ts +++ b/gameserver/commands/OnSpawnPointSelectCommand.ts @@ -42,7 +42,8 @@ export class OnSpawnPointSelectCommand extends Command< return; } const player = this.state.getPlayer(client.id); - player?.updatePosition(requestedPoint.x, requestedPoint.y); + if(!player) return; + player.updatePosition(requestedPoint.x, requestedPoint.y); this.state.tilemap.updateOwnershipMap(this.state.getPlayers()); } } diff --git a/gameserver/schema/PlayerState.ts b/gameserver/schema/PlayerState.ts index 8445037..453fe88 100644 --- a/gameserver/schema/PlayerState.ts +++ b/gameserver/schema/PlayerState.ts @@ -145,7 +145,6 @@ export class PlayerState extends Schema implements ISceneItem { sessionState.onCaptureFlagRemoved(flagId); this.resourceGrowthRateHz = 2 * (1 + 0.2 * this.captureFlags.length); - sessionState.tilemap.updateOwnershipMap(sessionState.getPlayers()); } removeBulkCaptureFlag( flagIds: string[], diff --git a/gameserver/schema/SessionState.ts b/gameserver/schema/SessionState.ts index c3697db..5df2ffe 100644 --- a/gameserver/schema/SessionState.ts +++ b/gameserver/schema/SessionState.ts @@ -34,11 +34,7 @@ export class SessionState extends Schema { return this.players.get(sessionId); } public getPlayers() { - let playersArr = []; - for (let player of this.players.entries()) { - playersArr.push(player[1]); - } - return playersArr; + return this.players; } onCaptureFlagAdded(flagId: string, parentId: string) { diff --git a/gameserver/schema/SoldierState.ts b/gameserver/schema/SoldierState.ts index 1962186..41bcda3 100644 --- a/gameserver/schema/SoldierState.ts +++ b/gameserver/schema/SoldierState.ts @@ -391,18 +391,21 @@ export class SoldierState extends Schema implements ISceneItem, IBoidAgent { flagQuatree.id ); if (!flagOwnerId) return; - const flag = sessionState - .getPlayer(flagOwnerId) - ?.captureFlags.toArray() + + const flagOwner = sessionState.getPlayer(flagOwnerId); + if (!flagOwner) return; + + const [flag] = sessionState + .getPlayer(flagOwnerId)! + .captureFlags.toArray() .filter((flag) => flag.id === flagQuatree.id); - if (flag && flag?.[0]) { - flag[0].setHealth(flag[0].health - 0.5 * delta); - if(flag[0].health === 0) - sessionState - .getPlayer(flagOwnerId) - ?.removeCaptureFlag(flag[0].id, sessionState, stateManager); - } + if (!flag) return; + + flag.setHealth(flag.health - 0.5 * delta); + if (flag.health > 0) return; + flagOwner.removeCaptureFlag(flag.id, sessionState, stateManager); + sessionState.tilemap.updateOwnershipMap(sessionState.getPlayers()); }); this.stateMachine.tick({ delta, stateManager, soldier: this }); diff --git a/gameserver/schema/TilemapState.ts b/gameserver/schema/TilemapState.ts index 6a84800..be1d38a 100644 --- a/gameserver/schema/TilemapState.ts +++ b/gameserver/schema/TilemapState.ts @@ -1,8 +1,7 @@ -import { Schema, type, ArraySchema } from "@colyseus/schema"; +import { Schema, type, MapSchema, ArraySchema } from "@colyseus/schema"; import { createNoise2D } from "simplex-noise"; import { PlayerState } from "./PlayerState"; import SAT from "sat"; - export enum ETileType { DIRT = "dirt", GRASS = "grass", @@ -50,62 +49,87 @@ export class TilemapState extends Schema { return new SAT.Vector(col, row); } - getTileTypeAt(index: number) { + getTileTypeAt(index: number) : ETileType { const tileId = this.tilemap1D.at(index); return TilesTypeById[tileId]; } - updateOwnershipMap(players: PlayerState[]) { + updateOwnershipMap(players: MapSchema) { for ( let tileIndex1D = 0; tileIndex1D < this.ownershipTilemap1D.length; tileIndex1D++ ) { const tileType = this.getTileTypeAt(tileIndex1D); - if (tileType === "water") continue; - - const currentOwner = this.ownershipTilemap1D.at(tileIndex1D); - const newOwner = this.selectTileOwner(tileIndex1D, players); + if (tileType === ETileType.WATER) continue; - if (newOwner !== "NONE" && currentOwner !== "NONE") { - continue; - } - if (newOwner === currentOwner) continue; - this.ownershipTilemap1D[tileIndex1D] = newOwner; + this.ownershipTilemap1D[tileIndex1D] = this.getTileOwner( + tileIndex1D, + players + ); } } - private selectTileOwner( - tileIndex: number, - players: PlayerState[] + private isTileWithinPlayerReach( + player: PlayerState | undefined, + tile1DIndex: number + ): boolean { + if (!player) return false; + const minDistance = TilemapState.TILE_INFLUENCE_DISTANCE; + let isValidOwner = false; + const castleAndCaptureFlagPos = player.captureFlags.map((flag) => + flag.pos.getVector() + ); + castleAndCaptureFlagPos.push(player.pos.getVector()); + + const tilePos = this.get2DIndex(tile1DIndex); + for (const pos of castleAndCaptureFlagPos) { + pos.x = Math.floor(pos.x / this.tilewidth); + pos.y = Math.floor(pos.y / this.tileheight); + const distanceFromTile = pos.sub(tilePos).len(); + if (distanceFromTile >= minDistance) continue; + isValidOwner = true; + break; + } + + return isValidOwner; + } + private getTileOwner( + tile1DIndex: number, + players: MapSchema ): string | "NONE" { - let ownerId = "NONE"; + const currentOwner = this.ownershipTilemap1D.at(tile1DIndex); + let ownerId = players.has(currentOwner) ? currentOwner : "NONE"; + let isTileWithinCurrentOwnerReach = this.isTileWithinPlayerReach( + players.get(ownerId), + tile1DIndex + ); + + // if tile currently has an active owner that satisfies the ownership creteria + if (isTileWithinCurrentOwnerReach) return ownerId; + + ownerId = 'NONE'; let minDistance = TilemapState.TILE_INFLUENCE_DISTANCE; - for (const player of players) { - const captureFlagPos = player.captureFlags.map((flag) => + let hasOwner: boolean = false; + for (const [_, player] of players) { + const castleAndCaptureFlagPos = player.captureFlags.map((flag) => flag.pos.getVector() ); - const territoryFlagPositions = [ - player.pos.getVector(), - ...captureFlagPos, - ]; + castleAndCaptureFlagPos.push(player.pos.getVector()); - territoryFlagPositions.forEach((pos) => { - // Convert to tile coordinates + const tilePos = this.get2DIndex(tile1DIndex); + for (const pos of castleAndCaptureFlagPos) { pos.x = Math.floor(pos.x / this.tilewidth); pos.y = Math.floor(pos.y / this.tileheight); - - const tilePos = this.get2DIndex(tileIndex); - const distanceFromTile = pos.sub(tilePos).len(); - if (distanceFromTile >= minDistance) return; - + if (distanceFromTile >= minDistance) continue; + hasOwner = true; minDistance = distanceFromTile; ownerId = player.id; - }); + } } - return ownerId; + return hasOwner ? ownerId : "NONE"; } async generateTilemap() { diff --git a/public/gameObjects/CaptureFlag.ts b/public/gameObjects/CaptureFlag.ts index a9157e3..4b73ded 100644 --- a/public/gameObjects/CaptureFlag.ts +++ b/public/gameObjects/CaptureFlag.ts @@ -91,7 +91,8 @@ export class CaptureFlag y: number, radius: number ) { - this.circleOfInfluence = scene.add.graphics(); + if(!this.circleOfInfluence) + this.circleOfInfluence = scene.add.graphics(); this.circleOfInfluence.lineStyle(3, 0xffffff); this.circleOfInfluence.strokeCircle(x, y, radius); } diff --git a/public/scenes/GameScene.ts b/public/scenes/GameScene.ts index ecedfb4..8bfef3f 100644 --- a/public/scenes/GameScene.ts +++ b/public/scenes/GameScene.ts @@ -459,8 +459,8 @@ export class GameScene extends BaseScene { // update tilemap for every tile update received. this.AddStateChangeListener( GameSessionState.tilemap.ownershipTilemap1D.onChange( - (owner, tileIndex) => { - this.updateTilemap(networkManager, owner, tileIndex); + (owner, tile1DIndex) => { + this.updateTilemap(networkManager, owner, tile1DIndex); } ) ); @@ -531,7 +531,6 @@ export class GameScene extends BaseScene { this.AddSceneEvent( GAMEEVENTS.DELETE_SELECTED_OBJECTS, () => { - console.log('requested to delete seelcted objects'); const selectedObjectsMap = this.data.get( DataKey.SELECTED_OBJECTS_MAP ) as Map; From 9bae1af4a7f1a37e3c5c8be81192df91f044661f Mon Sep 17 00:00:00 2001 From: keshav2010 Date: Wed, 24 Jul 2024 06:14:42 +0530 Subject: [PATCH 2/2] remove capture flag when player leaves --- gameserver/commands/OnLeaveCommand.ts | 1 - public/scenes/GameScene.ts | 6 +++--- public/scenes/PlayerStatisticHUD.ts | 6 ++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/gameserver/commands/OnLeaveCommand.ts b/gameserver/commands/OnLeaveCommand.ts index 0aed803..4dcd03b 100644 --- a/gameserver/commands/OnLeaveCommand.ts +++ b/gameserver/commands/OnLeaveCommand.ts @@ -7,6 +7,5 @@ export class OnLeaveCommand extends Command { execute({ client, message, gameManager }: CommandPayload) { const sessionId = client.sessionId; this.state.removePlayer(sessionId, gameManager!); - this.state.tilemap.updateOwnershipMap(this.state.getPlayers()); } } diff --git a/public/scenes/GameScene.ts b/public/scenes/GameScene.ts index 8bfef3f..107de7d 100644 --- a/public/scenes/GameScene.ts +++ b/public/scenes/GameScene.ts @@ -703,9 +703,9 @@ export class GameScene extends BaseScene { `obj_captureFlag_${player.id}_${newFlag.id}` ); if (!flag) return; - this.DestroyObjectById(`obj_captureFlag_${player.id}_${newFlag.id}`); + this.DestroyObjectById(`obj_captureFlag_${player.id}_${flag.id}`); this.DestroyStateChangeListener( - `statechange_captureFlag_${player.id}_${newFlag.id}` + `statechange_captureFlag_${player.id}_${flag.id}` ); }) ); @@ -714,10 +714,10 @@ export class GameScene extends BaseScene { this.AddStateChangeListener( state.players.onRemove((player) => { const kingdomId = `obj_playerCastle_${player.id}`; + this.DestroyObjectById(kingdomId); this.events.emit(PacketType.ByServer.PLAYER_LEFT, { playerState: player, }); - this.DestroyObjectById(kingdomId); }) ); diff --git a/public/scenes/PlayerStatisticHUD.ts b/public/scenes/PlayerStatisticHUD.ts index d2befc7..4bd231a 100644 --- a/public/scenes/PlayerStatisticHUD.ts +++ b/public/scenes/PlayerStatisticHUD.ts @@ -9,6 +9,7 @@ import { NetworkManager } from "../NetworkManager"; import { PlayerState } from "../../gameserver/schema/PlayerState"; import { Spearman } from "../soldiers/Spearman"; import CONSTANTS from "../constant"; +import { CaptureFlag } from "../gameObjects/CaptureFlag"; const textStyle: Phaser.Types.GameObjects.Text.TextStyle = { color: "#fff", @@ -198,6 +199,11 @@ export class PlayerStatisticHUD extends BaseScene { gameScene.onSoldierRemoved(soldier.id, playerObject.id); }); + const captureFlags = gameScene.GetObjectsWithKeyPrefix( + `obj_captureFlag_${playerObject.id}` + ); + captureFlags.forEach((flag) => flag.destroy(true)); + soldierCount.setText( `Total Soldiers: ${[...state.players.values()].reduce((acc, curr) => { acc = acc + curr.soldiers.size;