diff --git a/apps/server/src/application/coordinators/disconnectCoordinator.ts b/apps/server/src/application/coordinators/disconnectCoordinator.ts index dcb2d76..8f0d0ce 100644 --- a/apps/server/src/application/coordinators/disconnectCoordinator.ts +++ b/apps/server/src/application/coordinators/disconnectCoordinator.ts @@ -3,11 +3,13 @@ * DISCONNECTイベントの調停を行い,ゲーム離脱処理とルーム離脱処理を順序実行する */ import { + type BombRoomStateCleanupPort, type DisconnectPlayerPort, type GameOutputPort, } from "@server/domains/game/application/ports/gameUseCasePorts"; import type { DisconnectRoomPort, + FindRoomByIdPort, FindRoomByPlayerPort, RoomOutputPort, } from "@server/domains/room/application/ports/roomUseCasePorts"; @@ -18,7 +20,8 @@ export type DisconnectCoordinatorParams = { socketId: string; gameManager: DisconnectPlayerPort; - roomManager: DisconnectRoomPort & FindRoomByPlayerPort; + roomManager: DisconnectRoomPort & FindRoomByPlayerPort & FindRoomByIdPort; + bombStateStore: BombRoomStateCleanupPort; gameOutput: Pick; roomOutput: Pick; }; @@ -28,6 +31,7 @@ socketId, gameManager, roomManager, + bombStateStore, gameOutput, roomOutput, }: DisconnectCoordinatorParams) => { @@ -45,4 +49,8 @@ socketId, output: roomOutput, }); + + if (roomId && !roomManager.getRoomById(roomId)) { + bombStateStore.clearBombRoomState(roomId, "room-deleted"); + } }; diff --git a/apps/server/src/application/coordinators/startGameCoordinator.ts b/apps/server/src/application/coordinators/startGameCoordinator.ts index 602e37b..c1f9bfa 100644 --- a/apps/server/src/application/coordinators/startGameCoordinator.ts +++ b/apps/server/src/application/coordinators/startGameCoordinator.ts @@ -3,6 +3,7 @@ * START_GAMEイベントの調停を行い,ルーム状態更新とゲーム開始処理を橋渡しする */ import { + type BombRoomStateCleanupPort, type GameOutputPort, type StartGamePort, type StartGameRoomPort, @@ -16,7 +17,7 @@ ownerId: string; gameManager: StartGamePort; roomManager: StartGameRoomPort; - onRoomGameEnded?: (roomId: string) => void; + bombStateStore: BombRoomStateCleanupPort; output: Pick< GameOutputPort, | "publishUpdatePlayersToRoom" @@ -32,7 +33,7 @@ ownerId, gameManager, roomManager, - onRoomGameEnded, + bombStateStore, output, }: StartGameCoordinatorParams) => { const room = roomManager.getRoomByOwnerId(ownerId); @@ -82,7 +83,7 @@ gameManager, onGameEnd: () => { roomManager.markRoomWaiting(updatedRoom.roomId); - onRoomGameEnded?.(updatedRoom.roomId); + bombStateStore.clearBombRoomState(updatedRoom.roomId, "game-ended"); }, output, }); diff --git a/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts b/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts index a91dce1..2fdae5b 100644 --- a/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts +++ b/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts @@ -87,6 +87,17 @@ issueServerBombId(roomId: string): string; } +/** 爆弾状態破棄理由を表す型 */ +export type BombRoomStateClearReason = "game-ended" | "room-deleted"; + +/** 爆弾状態破棄ユースケースが利用する入力ポート */ +export interface BombRoomStateCleanupPort { + clearBombRoomState(roomId: string, reason: BombRoomStateClearReason): void; +} + +/** 爆弾状態の参照更新と破棄を扱う統合入力ポート */ +export interface BombRoomStateStorePort extends BombPlacementStorePort, BombRoomStateCleanupPort {} + /** 爆弾設置ユースケースの入力値 */ export type PlaceBombInput = { socketId: string; diff --git a/apps/server/src/network/handlers/GameHandler.ts b/apps/server/src/network/handlers/GameHandler.ts index ac3b899..f317903 100644 --- a/apps/server/src/network/handlers/GameHandler.ts +++ b/apps/server/src/network/handlers/GameHandler.ts @@ -5,6 +5,3 @@ */ /** ゲームイベント受信ハンドラ登録関数を外部参照向けに再公開 */ export { registerGameHandlers } from "./game/registerGameHandlers"; - -/** ルーム終了時の爆弾状態掃除関数を外部参照向けに再公開 */ -export { clearBombRoomState } from "@server/domains/game/entities/bomb/BombRoomStateStore"; diff --git a/apps/server/src/network/handlers/game/createBombRoomStateStoreAdapter.ts b/apps/server/src/network/handlers/game/createBombRoomStateStoreAdapter.ts new file mode 100644 index 0000000..0d5215b --- /dev/null +++ b/apps/server/src/network/handlers/game/createBombRoomStateStoreAdapter.ts @@ -0,0 +1,19 @@ +/** + * createBombRoomStateStoreAdapter + * 爆弾状態ストア実装をネットワーク層向けの入力ポートへ変換する + */ +import type { BombRoomStateStorePort } from "@server/domains/game/application/ports/gameUseCasePorts"; +import { + clearBombRoomState, + issueServerBombId, + shouldBroadcastBombPlaced, +} from "@server/domains/game/entities/bomb/BombRoomStateStore"; + +/** 爆弾状態ストア入力ポートの実装を生成する */ +export const createBombRoomStateStoreAdapter = (): BombRoomStateStorePort => { + return { + clearBombRoomState, + issueServerBombId, + shouldBroadcastBombPlaced, + }; +}; diff --git a/apps/server/src/network/handlers/game/registerGameHandlers.ts b/apps/server/src/network/handlers/game/registerGameHandlers.ts index 577b8cb..37352c6 100644 --- a/apps/server/src/network/handlers/game/registerGameHandlers.ts +++ b/apps/server/src/network/handlers/game/registerGameHandlers.ts @@ -7,7 +7,7 @@ import { readyForGameCoordinator } from "@server/application/coordinators/readyForGameCoordinator"; import { startGameCoordinator } from "@server/application/coordinators/startGameCoordinator"; import type { - BombPlacementStorePort, + BombRoomStateStorePort, MovePlayerPort, PlaceBombRoomPort, ReadyForGamePort, @@ -22,7 +22,6 @@ import { isMovePayload, isPingPayload, isPlaceBombPayload } from "@server/network/validation/socketPayloadValidators"; import { createServerSocketOnBridge } from "@server/network/handlers/socketEventBridge"; import { createPayloadGuard } from "@server/network/handlers/payloadGuard"; -import { clearBombRoomState, issueServerBombId, shouldBroadcastBombPlaced } from "@server/domains/game/entities/bomb/BombRoomStateStore"; import { createGameOutputAdapter } from "./createGameOutputAdapter"; /** ゲーム受信イベントごとの入力検証関数を保持するテーブル */ @@ -37,7 +36,8 @@ io: Server, socket: Socket, gameManager: StartGamePort & ReadyForGamePort & MovePlayerPort, - roomManager: StartGameRoomPort & ReadyForGameRoomPort & PlaceBombRoomPort + roomManager: StartGameRoomPort & ReadyForGameRoomPort & PlaceBombRoomPort, + bombStateStore: BombRoomStateStorePort ) => { const common = createCommonHandlerContext(io, socket); const gameOutputAdapter = createGameOutputAdapter(common); @@ -55,7 +55,6 @@ protocol.SocketEvents.PLACE_BOMB, gamePayloadValidators[protocol.SocketEvents.PLACE_BOMB] ); - // 遅延計測用のPINGを検証しPONGを返す onEvent(protocol.SocketEvents.PING, (clientTime) => { if (!guardPingPayload(clientTime)) { @@ -74,9 +73,7 @@ ownerId: socket.id, gameManager, roomManager, - onRoomGameEnded: (roomId) => { - clearBombRoomState(roomId, "game-ended"); - }, + bombStateStore, output: gameOutputAdapter, }); }); @@ -110,14 +107,9 @@ return; } - const bombStore: BombPlacementStorePort = { - shouldBroadcastBombPlaced, - issueServerBombId, - }; - placeBombUseCase({ roomResolver: roomManager, - bombStore, + bombStore: bombStateStore, input: { socketId: socket.id, payload: data, diff --git a/apps/server/src/network/handlers/registerConnectionHandlers.ts b/apps/server/src/network/handlers/registerConnectionHandlers.ts index 555dc51..7c2466a 100644 --- a/apps/server/src/network/handlers/registerConnectionHandlers.ts +++ b/apps/server/src/network/handlers/registerConnectionHandlers.ts @@ -7,8 +7,9 @@ import { disconnectCoordinator } from "@server/application/coordinators/disconnectCoordinator"; import { logEvent } from "@server/logging/logger"; import { logResults, logScopes } from "@server/logging/index"; -import { clearBombRoomState, registerGameHandlers } from "./GameHandler"; +import { registerGameHandlers } from "./GameHandler"; import { registerRoomHandlers } from "./RoomHandler"; +import { createBombRoomStateStoreAdapter } from "./game/createBombRoomStateStoreAdapter"; import { createGameDisconnectOutputAdapter } from "./game/createGameOutputAdapter"; import { createRoomDisconnectOutputAdapter } from "./room/createRoomOutputAdapter"; import type { @@ -23,6 +24,7 @@ }: RegisterConnectionHandlersParams) => { const gameDisconnectOutputAdapter = createGameDisconnectOutputAdapter(io); const roomDisconnectOutputAdapter = createRoomDisconnectOutputAdapter(io); + const bombStateStoreAdapter = createBombRoomStateStoreAdapter(); io.on(protocol.SocketEvents.CONNECT, (socket: Socket) => { // 接続ログを記録してドメイン別ハンドラを登録する @@ -33,11 +35,9 @@ }); registerRoomHandlers(io, socket, roomManager); - registerGameHandlers(io, socket, gameManager, roomManager); + registerGameHandlers(io, socket, gameManager, roomManager, bombStateStoreAdapter); socket.on(protocol.SocketEvents.DISCONNECT, () => { - const roomIdBeforeDisconnect = roomManager.getRoomByPlayerId(socket.id)?.roomId; - // 切断ログ記録後にドメイン別の後処理を実行する logEvent(logScopes.NETWORK, { event: protocol.SocketEvents.DISCONNECT, @@ -49,13 +49,10 @@ socketId: socket.id, gameManager, roomManager, + bombStateStore: bombStateStoreAdapter, gameOutput: gameDisconnectOutputAdapter, roomOutput: roomDisconnectOutputAdapter, }); - - if (roomIdBeforeDisconnect && !roomManager.getRoomById(roomIdBeforeDisconnect)) { - clearBombRoomState(roomIdBeforeDisconnect, "room-deleted"); - } }); }); }; diff --git a/apps/server/src/network/types/connectionPorts.ts b/apps/server/src/network/types/connectionPorts.ts index bd7a12a..6624da9 100644 --- a/apps/server/src/network/types/connectionPorts.ts +++ b/apps/server/src/network/types/connectionPorts.ts @@ -53,7 +53,7 @@ export type DisconnectGamePort = DisconnectPlayerPort; /** 切断時のルーム処理で利用する入力ポート集合 */ -export type DisconnectRoomHandlerPort = DisconnectRoomPort & FindRoomByPlayerPort; +export type DisconnectRoomHandlerPort = DisconnectRoomPort & FindRoomByPlayerPort & FindRoomByIdPort; /** 切断調停処理へ受け渡す依存集合 */ export type DisconnectCoordinatorPortBundle = Omit;