diff --git a/apps/client/src/network/handlers/GameHandler.ts b/apps/client/src/network/handlers/GameHandler.ts index 77abe3d..2d5b226 100644 --- a/apps/client/src/network/handlers/GameHandler.ts +++ b/apps/client/src/network/handlers/GameHandler.ts @@ -4,14 +4,19 @@ type GameHandler = { onCurrentPlayers: (callback: (players: playerTypes.PlayerData[] | Record) => void) => void; + offCurrentPlayers: (callback: (players: playerTypes.PlayerData[] | Record) => void) => void; onNewPlayer: (callback: (player: playerTypes.PlayerData) => void) => void; + offNewPlayer: (callback: (player: playerTypes.PlayerData) => void) => void; onUpdatePlayer: (callback: (data: Partial & { id: string }) => void) => void; + offUpdatePlayer: (callback: (data: Partial & { id: string }) => void) => void; onRemovePlayer: (callback: (id: string) => void) => void; + offRemovePlayer: (callback: (id: string) => void) => void; onUpdateMapCells: (callback: (updates: gridMapTypes.CellUpdate[]) => void) => void; + offUpdateMapCells: (callback: (updates: gridMapTypes.CellUpdate[]) => void) => void; onGameStart: (callback: (data: { startTime: number }) => void) => void; + offGameStart: (callback: (data: { startTime: number }) => void) => void; sendMove: (x: number, y: number) => void; readyForGame: () => void; - removeAllListeners: () => void; }; export const createGameHandler = (socket: Socket): GameHandler => { @@ -19,34 +24,45 @@ onCurrentPlayers: (callback) => { socket.on(protocol.SocketEvents.CURRENT_PLAYERS, callback); }, + offCurrentPlayers: (callback) => { + socket.off(protocol.SocketEvents.CURRENT_PLAYERS, callback); + }, onNewPlayer: (callback) => { socket.on(protocol.SocketEvents.NEW_PLAYER, callback); }, + offNewPlayer: (callback) => { + socket.off(protocol.SocketEvents.NEW_PLAYER, callback); + }, onUpdatePlayer: (callback) => { socket.on(protocol.SocketEvents.UPDATE_PLAYER, callback); }, + offUpdatePlayer: (callback) => { + socket.off(protocol.SocketEvents.UPDATE_PLAYER, callback); + }, onRemovePlayer: (callback) => { socket.on(protocol.SocketEvents.REMOVE_PLAYER, callback); }, + offRemovePlayer: (callback) => { + socket.off(protocol.SocketEvents.REMOVE_PLAYER, callback); + }, onUpdateMapCells: (callback) => { socket.on(protocol.SocketEvents.UPDATE_MAP_CELLS, callback); }, + offUpdateMapCells: (callback) => { + socket.off(protocol.SocketEvents.UPDATE_MAP_CELLS, callback); + }, onGameStart: (callback) => { socket.on(protocol.SocketEvents.GAME_START, callback); }, + offGameStart: (callback) => { + socket.off(protocol.SocketEvents.GAME_START, callback); + }, sendMove: (x, y) => { const payload: playerTypes.MovePayload = { x, y }; socket.emit(protocol.SocketEvents.MOVE, payload); }, readyForGame: () => { socket.emit(protocol.SocketEvents.READY_FOR_GAME); - }, - removeAllListeners: () => { - socket.off(protocol.SocketEvents.CURRENT_PLAYERS); - socket.off(protocol.SocketEvents.NEW_PLAYER); - socket.off(protocol.SocketEvents.UPDATE_PLAYER); - socket.off(protocol.SocketEvents.REMOVE_PLAYER); - socket.off(protocol.SocketEvents.UPDATE_MAP_CELLS); } }; }; diff --git a/apps/client/src/scenes/game/application/GameNetworkSync.ts b/apps/client/src/scenes/game/application/GameNetworkSync.ts index 79d2d59..f401c1c 100644 --- a/apps/client/src/scenes/game/application/GameNetworkSync.ts +++ b/apps/client/src/scenes/game/application/GameNetworkSync.ts @@ -19,6 +19,50 @@ private myId: string; private gameMap: GameMapController; private onGameStart: (startTime: number) => void; + private isBound = false; + + private handleCurrentPlayers = (serverPlayers: playerTypes.PlayerData[] | Record) => { + const playersArray = (Array.isArray(serverPlayers) ? serverPlayers : Object.values(serverPlayers)) as playerTypes.PlayerData[]; + playersArray.forEach((p) => { + const playerController = p.id === this.myId ? new LocalPlayerController(p) : new RemotePlayerController(p); + this.worldContainer.addChild(playerController.getDisplayObject()); + this.players[p.id] = playerController; + }); + }; + + private handleNewPlayer = (p: playerTypes.PlayerData) => { + const playerController = new RemotePlayerController(p); + this.worldContainer.addChild(playerController.getDisplayObject()); + this.players[p.id] = playerController; + }; + + private handleGameStart = (data: { startTime: number }) => { + if (data && data.startTime) { + this.onGameStart(data.startTime); + console.log(`[GameManager] ゲーム開始時刻同期完了: ${data.startTime}`); + } + }; + + private handleUpdatePlayer = (data: Partial & { id: string }) => { + if (data.id === this.myId) return; + const target = this.players[data.id]; + if (target && target instanceof RemotePlayerController) { + target.applyRemoteUpdate({ x: data.x, y: data.y }); + } + }; + + private handleRemovePlayer = (id: string) => { + const target = this.players[id]; + if (target) { + this.worldContainer.removeChild(target.getDisplayObject()); + target.destroy(); + delete this.players[id]; + } + }; + + private handleUpdateMapCells = (updates: Parameters[0]) => { + this.gameMap.updateCells(updates); + }; constructor({ worldContainer, players, myId, gameMap, onGameStart }: GameNetworkSyncOptions) { this.worldContainer = worldContainer; @@ -29,51 +73,28 @@ } public bind() { - socketManager.game.onCurrentPlayers((serverPlayers: playerTypes.PlayerData[] | Record) => { - const playersArray = (Array.isArray(serverPlayers) ? serverPlayers : Object.values(serverPlayers)) as playerTypes.PlayerData[]; - playersArray.forEach((p) => { - const playerController = p.id === this.myId ? new LocalPlayerController(p) : new RemotePlayerController(p); - this.worldContainer.addChild(playerController.getDisplayObject()); - this.players[p.id] = playerController; - }); - }); + if (this.isBound) return; - socketManager.game.onNewPlayer((p: playerTypes.PlayerData) => { - const playerController = new RemotePlayerController(p); - this.worldContainer.addChild(playerController.getDisplayObject()); - this.players[p.id] = playerController; - }); + socketManager.game.onCurrentPlayers(this.handleCurrentPlayers); + socketManager.game.onNewPlayer(this.handleNewPlayer); + socketManager.game.onGameStart(this.handleGameStart); + socketManager.game.onUpdatePlayer(this.handleUpdatePlayer); + socketManager.game.onRemovePlayer(this.handleRemovePlayer); + socketManager.game.onUpdateMapCells(this.handleUpdateMapCells); - socketManager.game.onGameStart((data) => { - if (data && data.startTime) { - this.onGameStart(data.startTime); - console.log(`[GameManager] ゲーム開始時刻同期完了: ${data.startTime}`); - } - }); - - socketManager.game.onUpdatePlayer((data: Partial & { id: string }) => { - if (data.id === this.myId) return; - const target = this.players[data.id]; - if (target && target instanceof RemotePlayerController) { - target.applyRemoteUpdate({ x: data.x, y: data.y }); - } - }); - - socketManager.game.onRemovePlayer((id: string) => { - const target = this.players[id]; - if (target) { - this.worldContainer.removeChild(target.getDisplayObject()); - target.destroy(); - delete this.players[id]; - } - }); - - socketManager.game.onUpdateMapCells((updates) => { - this.gameMap.updateCells(updates); - }); + this.isBound = true; } public unbind() { - socketManager.game.removeAllListeners(); + if (!this.isBound) return; + + socketManager.game.offCurrentPlayers(this.handleCurrentPlayers); + socketManager.game.offNewPlayer(this.handleNewPlayer); + socketManager.game.offGameStart(this.handleGameStart); + socketManager.game.offUpdatePlayer(this.handleUpdatePlayer); + socketManager.game.offRemovePlayer(this.handleRemovePlayer); + socketManager.game.offUpdateMapCells(this.handleUpdateMapCells); + + this.isBound = false; } }