diff --git a/apps/server/src/domains/game/GameManager.ts b/apps/server/src/domains/game/GameManager.ts index c6f5a6f..c94a91b 100644 --- a/apps/server/src/domains/game/GameManager.ts +++ b/apps/server/src/domains/game/GameManager.ts @@ -13,14 +13,16 @@ export class GameManager { private sessions: Map; private playerToRoom: Map; + private roomToPlayers: Map>; private lifecycleService: GameSessionLifecycleService; private playerOperationService: GamePlayerOperationService; constructor() { this.sessions = new Map(); this.playerToRoom = new Map(); - this.lifecycleService = new GameSessionLifecycleService(this.sessions, this.playerToRoom); - this.playerOperationService = new GamePlayerOperationService(this.sessions, this.playerToRoom); + this.roomToPlayers = new Map(); + this.lifecycleService = new GameSessionLifecycleService(this.sessions, this.playerToRoom, this.roomToPlayers); + this.playerOperationService = new GamePlayerOperationService(this.sessions, this.playerToRoom, this.roomToPlayers); } // 外部(GameHandlerなど)から開始時刻を取得できるようにする diff --git a/apps/server/src/domains/game/application/services/GamePlayerOperationService.ts b/apps/server/src/domains/game/application/services/GamePlayerOperationService.ts index e6af25b..1a3514e 100644 --- a/apps/server/src/domains/game/application/services/GamePlayerOperationService.ts +++ b/apps/server/src/domains/game/application/services/GamePlayerOperationService.ts @@ -7,12 +7,14 @@ type SessionStore = Map; type PlayerRoomIndex = Map; +type RoomPlayersIndex = Map>; /** プレイヤー移動とセッション離脱処理を提供するサービス */ export class GamePlayerOperationService { constructor( private sessions: SessionStore, - private playerToRoom: PlayerRoomIndex + private playerToRoom: PlayerRoomIndex, + private roomToPlayers: RoomPlayersIndex ) {} public movePlayer(id: string, x: number, y: number): void { @@ -43,15 +45,22 @@ const session = this.sessions.get(roomId); if (!session) { this.playerToRoom.delete(id); + this.roomToPlayers.get(roomId)?.delete(id); + + if (this.roomToPlayers.get(roomId)?.size === 0) { + this.roomToPlayers.delete(roomId); + } return; } const removed = session.removePlayer(id); this.playerToRoom.delete(id); + this.roomToPlayers.get(roomId)?.delete(id); if (removed && session.isEmpty()) { session.dispose(); this.sessions.delete(roomId); + this.roomToPlayers.delete(roomId); logEvent("GameSessionService", { event: "REMOVE_PLAYER", result: "session_disposed_empty_room", diff --git a/apps/server/src/domains/game/application/services/GameSessionLifecycleService.ts b/apps/server/src/domains/game/application/services/GameSessionLifecycleService.ts index 0b22870..7e648fc 100644 --- a/apps/server/src/domains/game/application/services/GameSessionLifecycleService.ts +++ b/apps/server/src/domains/game/application/services/GameSessionLifecycleService.ts @@ -9,12 +9,14 @@ type SessionStore = Map; type PlayerRoomIndex = Map; +type RoomPlayersIndex = Map>; /** ゲームセッションのライフサイクル操作を提供するサービス */ export class GameSessionLifecycleService { constructor( private sessions: SessionStore, - private playerToRoom: PlayerRoomIndex + private playerToRoom: PlayerRoomIndex, + private roomToPlayers: RoomPlayersIndex ) {} public getRoomStartTime(roomId: string): number | undefined { @@ -42,10 +44,12 @@ const tickRate = config.GAME_CONFIG.PLAYER_POSITION_UPDATE_MS; const session = new GameRoomSession(roomId, playerIds); + const roomPlayerSet = new Set(playerIds); playerIds.forEach((playerId) => { this.playerToRoom.set(playerId, roomId); }); + this.roomToPlayers.set(roomId, roomPlayerSet); this.sessions.set(roomId, session); session.start(tickRate, onTick, () => { @@ -63,10 +67,14 @@ } private clearRoomPlayerIndex(roomId: string): void { - Array.from(this.playerToRoom.entries()).forEach(([playerId, mappedRoomId]) => { - if (mappedRoomId === roomId) { - this.playerToRoom.delete(playerId); - } + const roomPlayerSet = this.roomToPlayers.get(roomId); + if (!roomPlayerSet) { + return; + } + + roomPlayerSet.forEach((playerId) => { + this.playerToRoom.delete(playerId); }); + this.roomToPlayers.delete(roomId); } } \ No newline at end of file