diff --git a/apps/server/src/application/coordinators/disconnectCoordinator.ts b/apps/server/src/application/coordinators/disconnectCoordinator.ts index c76880a..f6c899f 100644 --- a/apps/server/src/application/coordinators/disconnectCoordinator.ts +++ b/apps/server/src/application/coordinators/disconnectCoordinator.ts @@ -19,7 +19,8 @@ /** 切断調停で利用する入力ポートと出力ポートの契約 */ export type DisconnectCoordinatorParams = { socketId: string; - gameManager: DisconnectPlayerPort & BombCleanupPort; + gameManager: DisconnectPlayerPort; + bombState: BombCleanupPort; roomManager: DisconnectRoomPort & FindRoomByPlayerPort & FindRoomByIdPort; gameOutput: Pick; roomOutput: Pick; @@ -29,6 +30,7 @@ export const disconnectCoordinator = ({ socketId, gameManager, + bombState, roomManager, gameOutput, roomOutput, @@ -49,6 +51,6 @@ }); if (roomId && !roomManager.getRoomById(roomId)) { - gameManager.clearBombRoomState(roomId, "room-deleted"); + bombState.clearBombRoomState(roomId, "room-deleted"); } }; diff --git a/apps/server/src/application/coordinators/readyForGameCoordinator.ts b/apps/server/src/application/coordinators/readyForGameCoordinator.ts index c87243b..41e1836 100644 --- a/apps/server/src/application/coordinators/readyForGameCoordinator.ts +++ b/apps/server/src/application/coordinators/readyForGameCoordinator.ts @@ -4,15 +4,15 @@ */ import { type GameOutputPort, - type GameRoomLookupPort, type ReadyForGamePort, } from "@server/domains/game/application/ports/gameUseCasePorts"; +import type { FindRoomByPlayerPort } from "@server/domains/room/application/ports/roomUseCasePorts"; import { readyForGameUseCase } from "@server/domains/game/application/useCases/readyForGameUseCase"; type ReadyForGameCoordinatorParams = { socketId: string; gameManager: ReadyForGamePort; - roomManager: GameRoomLookupPort; + roomManager: FindRoomByPlayerPort; output: Pick; }; diff --git a/apps/server/src/application/coordinators/startGameCoordinator.ts b/apps/server/src/application/coordinators/startGameCoordinator.ts index 766b626..049dd23 100644 --- a/apps/server/src/application/coordinators/startGameCoordinator.ts +++ b/apps/server/src/application/coordinators/startGameCoordinator.ts @@ -6,8 +6,11 @@ type BombCleanupPort, type GameOutputPort, type StartGamePort, - type StartGameRoomPort, } from "@server/domains/game/application/ports/gameUseCasePorts"; +import type { + FindRoomByOwnerPort, + RoomPhaseTransitionPort, +} from "@server/domains/room/application/ports/roomUseCasePorts"; import { startGameUseCase } from "@server/domains/game/application/useCases/startGameUseCase"; import { logEvent } from "@server/logging/logger"; import { gameUseCaseLogEvents, logResults, logScopes } from "@server/logging/index"; @@ -15,8 +18,9 @@ type StartGameCoordinatorParams = { ownerId: string; - gameManager: StartGamePort & BombCleanupPort; - roomManager: StartGameRoomPort; + gameManager: StartGamePort; + bombState: BombCleanupPort; + roomManager: FindRoomByOwnerPort & RoomPhaseTransitionPort; output: Pick< GameOutputPort, | "publishUpdatePlayersToRoom" @@ -31,6 +35,7 @@ export const startGameCoordinator = ({ ownerId, gameManager, + bombState, roomManager, output, }: StartGameCoordinatorParams) => { @@ -81,7 +86,7 @@ gameManager, onGameEnd: () => { roomManager.markRoomWaiting(updatedRoom.roomId); - gameManager.clearBombRoomState(updatedRoom.roomId, "game-ended"); + bombState.clearBombRoomState(updatedRoom.roomId, "game-ended"); }, output, }); diff --git a/apps/server/src/domains/game/GameManager.ts b/apps/server/src/domains/game/GameManager.ts index 3f86bcf..389f85c 100644 --- a/apps/server/src/domains/game/GameManager.ts +++ b/apps/server/src/domains/game/GameManager.ts @@ -3,10 +3,6 @@ * ゲームセッション集合の生成,更新,参照管理を統括する */ import type { gameTypes, GameResultPayload } from "@repo/shared"; -import { - BombRoomStateClearReason, - BombRoomStateStore, -} from "./entities/bomb/BombRoomStateStore"; import { Player } from "./entities/player/Player.js"; import { GameRoomSession } from "./application/services/GameRoomSession"; import { GameSessionLifecycleService } from "./application/services/GameSessionLifecycleService"; @@ -20,7 +16,6 @@ private roomToPlayers: Map>; private lifecycleService: GameSessionLifecycleService; private playerOperationService: GamePlayerOperationService; - private bombRoomStateStore: BombRoomStateStore; constructor() { this.sessions = new Map(); @@ -28,7 +23,6 @@ this.roomToPlayers = new Map(); this.lifecycleService = new GameSessionLifecycleService(this.sessions, this.playerToRoom, this.roomToPlayers); this.playerOperationService = new GamePlayerOperationService(this.sessions, this.playerToRoom, this.roomToPlayers); - this.bombRoomStateStore = new BombRoomStateStore(); } // 外部(GameHandlerなど)から開始時刻を取得できるようにする @@ -65,19 +59,4 @@ getRoomPlayers(roomId: string): Player[] { return this.lifecycleService.getRoomPlayers(roomId); } - - // 爆弾設置イベントを配信すべきか判定し,配信時は重複排除状態を更新する - shouldBroadcastBombPlaced(roomId: string, dedupeKey: string, nowMs: number): boolean { - return this.bombRoomStateStore.shouldBroadcastBombPlaced(roomId, dedupeKey, nowMs); - } - - // ルーム単位の連番からサーバー採番の爆弾IDを生成する - issueServerBombId(roomId: string): string { - return this.bombRoomStateStore.issueServerBombId(roomId); - } - - // 指定ルームの爆弾採番状態と重複排除状態を破棄する - clearBombRoomState(roomId: string, reason: BombRoomStateClearReason): void { - this.bombRoomStateStore.clearBombRoomState(roomId, reason); - } } \ No newline at end of file diff --git a/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts b/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts index a269b40..7b21bed 100644 --- a/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts +++ b/apps/server/src/domains/game/application/ports/gameUseCasePorts.ts @@ -29,18 +29,6 @@ getRoomStartTime(roomId: string): number | undefined; } -/** ゲーム開始調停で利用するルーム管理入力ポート */ -export interface StartGameRoomPort { - getRoomByOwnerId(ownerId: string): roomTypes.Room | undefined; - markRoomPlaying(roomId: string): roomTypes.Room | undefined; - markRoomWaiting(roomId: string): roomTypes.Room | undefined; -} - -/** ゲーム系調停で利用するプレイヤー所属ルーム解決入力ポート */ -export interface GameRoomLookupPort { - getRoomByPlayerId(playerId: string): roomTypes.Room | undefined; -} - /** 準備完了ユースケースが利用するゲーム状態参照入力ポート */ export interface ReadyForGamePort { getRoomPlayers(roomId: string): playerTypes.PlayerData[]; diff --git a/apps/server/src/domains/game/application/useCases/placeBombUseCase.ts b/apps/server/src/domains/game/application/useCases/placeBombUseCase.ts index a0e1290..0e9fde1 100644 --- a/apps/server/src/domains/game/application/useCases/placeBombUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/placeBombUseCase.ts @@ -5,12 +5,12 @@ import type { BombPlacementPort, GameOutputPort, - GameRoomLookupPort, PlaceBombInput, } from "../ports/gameUseCasePorts"; +import type { FindRoomByPlayerPort } from "@server/domains/room/application/ports/roomUseCasePorts"; type PlaceBombUseCaseParams = { - roomResolver: GameRoomLookupPort; + roomResolver: FindRoomByPlayerPort; bombStore: BombPlacementPort; input: PlaceBombInput; output: Pick; diff --git a/apps/server/src/domains/room/application/ports/roomUseCasePorts.ts b/apps/server/src/domains/room/application/ports/roomUseCasePorts.ts index 9845676..b32c711 100644 --- a/apps/server/src/domains/room/application/ports/roomUseCasePorts.ts +++ b/apps/server/src/domains/room/application/ports/roomUseCasePorts.ts @@ -31,6 +31,17 @@ getRoomByPlayerId(playerId: string): roomTypes.Room | undefined; } +/** ゲーム開始調停で利用するオーナー所属ルーム参照ポート */ +export interface FindRoomByOwnerPort { + getRoomByOwnerId(ownerId: string): roomTypes.Room | undefined; +} + +/** ゲーム開始調停で利用するルーム状態遷移ポート */ +export interface RoomPhaseTransitionPort { + markRoomPlaying(roomId: string): roomTypes.Room | undefined; + markRoomWaiting(roomId: string): roomTypes.Room | undefined; +} + /** ルームIDでの存在確認に利用する参照ポート */ export interface FindRoomByIdPort { getRoomById(roomId: string): roomTypes.Room | undefined; diff --git a/apps/server/src/network/SocketManager.ts b/apps/server/src/network/SocketManager.ts index 279a30c..6ba5c30 100644 --- a/apps/server/src/network/SocketManager.ts +++ b/apps/server/src/network/SocketManager.ts @@ -4,6 +4,7 @@ */ import { Server } from "socket.io"; import type { + SocketConnectionBombPort, SocketConnectionManagerBundle, SocketConnectionGamePort, SocketConnectionRoomPort, @@ -18,11 +19,13 @@ constructor( io: Server, gameManager: SocketConnectionGamePort, + bombState: SocketConnectionBombPort, roomManager: SocketConnectionRoomPort ) { this.io = io; this.managers = { gameManager, + bombState, roomManager, }; } diff --git a/apps/server/src/network/bootstrap/boot.ts b/apps/server/src/network/bootstrap/boot.ts index 29ba1ff..414e6eb 100644 --- a/apps/server/src/network/bootstrap/boot.ts +++ b/apps/server/src/network/bootstrap/boot.ts @@ -4,6 +4,7 @@ */ import type { Server as HttpServer } from "http"; import { GameManager } from "@server/domains/game/GameManager"; +import { BombRoomStateStore } from "@server/domains/game/entities/bomb/BombRoomStateStore"; import { RoomManager } from "@server/domains/room/RoomManager"; import { SocketManager } from "../SocketManager"; import { createIo } from "./createIo"; @@ -13,8 +14,9 @@ // ネットワーク層とドメイン層の依存を構築する const io = createIo(httpServer); const gameManager = new GameManager(); + const bombState = new BombRoomStateStore(); const roomManager = new RoomManager(); - const socketManager = new SocketManager(io, gameManager, roomManager); + const socketManager = new SocketManager(io, gameManager, bombState, roomManager); socketManager.initialize(); }; diff --git a/apps/server/src/network/handlers/game/registerGameHandlers.ts b/apps/server/src/network/handlers/game/registerGameHandlers.ts index c9ca666..d1e0fa6 100644 --- a/apps/server/src/network/handlers/game/registerGameHandlers.ts +++ b/apps/server/src/network/handlers/game/registerGameHandlers.ts @@ -7,12 +7,16 @@ import { readyForGameCoordinator } from "@server/application/coordinators/readyForGameCoordinator"; import { startGameCoordinator } from "@server/application/coordinators/startGameCoordinator"; import type { - BombStatePort, - GameRoomLookupPort, + FindRoomByOwnerPort, + FindRoomByPlayerPort, + RoomPhaseTransitionPort, +} from "@server/domains/room/application/ports/roomUseCasePorts"; +import type { + BombPlacementPort, + BombCleanupPort, MovePlayerPort, ReadyForGamePort, StartGamePort, - StartGameRoomPort, } from "@server/domains/game/application/ports/gameUseCasePorts"; import { movePlayerUseCase } from "@server/domains/game/application/useCases/movePlayerUseCase"; import { placeBombUseCase } from "@server/domains/game/application/useCases/placeBombUseCase"; @@ -34,8 +38,9 @@ export const registerGameHandlers = ( io: Server, socket: Socket, - gameManager: StartGamePort & ReadyForGamePort & MovePlayerPort & BombStatePort, - roomManager: StartGameRoomPort & GameRoomLookupPort + gameManager: StartGamePort & ReadyForGamePort & MovePlayerPort, + bombState: BombPlacementPort & BombCleanupPort, + roomManager: FindRoomByOwnerPort & FindRoomByPlayerPort & RoomPhaseTransitionPort ) => { const common = createCommonHandlerContext(io, socket); const gameOutputAdapter = createGameOutputAdapter(common); @@ -70,6 +75,7 @@ startGameCoordinator({ ownerId: socket.id, gameManager, + bombState, roomManager, output: gameOutputAdapter, }); @@ -106,7 +112,7 @@ placeBombUseCase({ roomResolver: roomManager, - bombStore: gameManager, + bombStore: bombState, 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 66850a8..5701b69 100644 --- a/apps/server/src/network/handlers/registerConnectionHandlers.ts +++ b/apps/server/src/network/handlers/registerConnectionHandlers.ts @@ -19,6 +19,7 @@ export const registerConnectionHandlers = ({ io, gameManager, + bombState, roomManager, }: RegisterConnectionHandlersParams) => { const gameDisconnectOutputAdapter = createGameDisconnectOutputAdapter(io); @@ -33,7 +34,7 @@ }); registerRoomHandlers(io, socket, roomManager); - registerGameHandlers(io, socket, gameManager, roomManager); + registerGameHandlers(io, socket, gameManager, bombState, roomManager); socket.on(protocol.SocketEvents.DISCONNECT, () => { // 切断ログ記録後にドメイン別の後処理を実行する @@ -46,6 +47,7 @@ disconnectCoordinator({ socketId: socket.id, gameManager, + bombState, roomManager, gameOutput: gameDisconnectOutputAdapter, roomOutput: roomDisconnectOutputAdapter, diff --git a/apps/server/src/network/types/connectionPorts.ts b/apps/server/src/network/types/connectionPorts.ts index 6649026..7e872b7 100644 --- a/apps/server/src/network/types/connectionPorts.ts +++ b/apps/server/src/network/types/connectionPorts.ts @@ -4,19 +4,19 @@ */ import type { Server } from "socket.io"; import type { - BombStatePort, DisconnectPlayerPort, - GameRoomLookupPort, MovePlayerPort, ReadyForGamePort, StartGamePort, - StartGameRoomPort, } from "@server/domains/game/application/ports/gameUseCasePorts"; +import type { BombStatePort } from "@server/domains/game/application/ports/gameUseCasePorts"; import type { DisconnectRoomPort, + FindRoomByOwnerPort, FindRoomByIdPort, FindRoomByPlayerPort, JoinRoomPort, + RoomPhaseTransitionPort, } from "@server/domains/room/application/ports/roomUseCasePorts"; import type { DisconnectCoordinatorParams } from "../../application/coordinators/disconnectCoordinator"; @@ -24,38 +24,44 @@ export type ConnectionGamePort = & StartGamePort & ReadyForGamePort - & MovePlayerPort - & BombStatePort; + & MovePlayerPort; /** 接続時のルーム処理で利用する入力ポート集合 */ export type ConnectionRoomPort = & JoinRoomPort - & StartGameRoomPort - & GameRoomLookupPort; + & FindRoomByOwnerPort + & FindRoomByPlayerPort + & RoomPhaseTransitionPort; /** ソケット接続全体で利用するゲーム管理ポート集合 */ export type SocketConnectionGamePort = & ConnectionGamePort & DisconnectPlayerPort; +/** ソケット接続全体で利用する爆弾状態ポート集合 */ +export type SocketConnectionBombPort = BombStatePort; + /** ソケット接続全体で利用するルーム管理ポート集合 */ export type SocketConnectionRoomPort = & ConnectionRoomPort & DisconnectRoomPort - & FindRoomByIdPort - & FindRoomByPlayerPort; + & FindRoomByIdPort; /** ソケット接続ハンドラで受け取るマネージャ依存の束 */ export type SocketConnectionManagerBundle = { gameManager: SocketConnectionGamePort; + bombState: SocketConnectionBombPort; roomManager: SocketConnectionRoomPort; }; /** 切断時のゲーム処理で利用する入力ポート */ -export type DisconnectGamePort = DisconnectPlayerPort; +export type DisconnectGamePort = Pick; /** 切断時のルーム処理で利用する入力ポート集合 */ -export type DisconnectRoomHandlerPort = DisconnectRoomPort & FindRoomByPlayerPort & FindRoomByIdPort; +export type DisconnectRoomHandlerPort = Pick< + SocketConnectionRoomPort, + "removePlayer" | "getRoomByPlayerId" | "getRoomById" +>; /** 切断調停処理へ受け渡す依存集合 */ export type DisconnectCoordinatorPortBundle = Omit;