diff --git a/apps/server/eslint.config.mjs b/apps/server/eslint.config.mjs index f2adfcd..e50ff7f 100644 --- a/apps/server/eslint.config.mjs +++ b/apps/server/eslint.config.mjs @@ -21,6 +21,29 @@ }, rules: { 'local/prefer-relative-for-local-server-path': 'warn', + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'socket.io', + message: + 'socket.io の import は network 配下のみにしてください。', + }, + { + name: 'socket.io-client', + message: + 'socket.io-client の import は network 配下のみにしてください。', + }, + ], + }, + ], + }, + }, + { + files: ['src/network/**/*.ts'], + rules: { + 'no-restricted-imports': 'off', }, }, ]; \ No newline at end of file diff --git a/apps/server/src/domains/game/GameHandler.ts b/apps/server/src/domains/game/GameHandler.ts deleted file mode 100644 index d1409db..0000000 --- a/apps/server/src/domains/game/GameHandler.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Server, Socket } from "socket.io"; -import { GameManager } from "./GameManager"; -import { RoomManager } from "@server/domains/room/RoomManager"; -import { protocol } from "@repo/shared"; -import type { playerTypes } from "@repo/shared"; -import { onPing } from "./handlers/onPing"; -import { onStartGame } from "./handlers/onStartGame"; -import { onReadyForGame } from "./handlers/onReadyForGame"; -import { onMove } from "./handlers/onMove"; -import { onDisconnect } from "./handlers/onDisconnect"; - -export const registerGameHandlers = (io: Server, socket: Socket, gameManager: GameManager, roomManager: RoomManager) => { - - // クライアントから送られてきた時刻をそのまま返しつつ、サーバーの現在時刻も添える - socket.on(protocol.SocketEvents.PING, (clientTime: number) => { - onPing(socket, clientTime); - }); - - // ゲーム開始要求処理 - socket.on(protocol.SocketEvents.START_GAME, () => { - onStartGame(io, gameManager, roomManager, socket.id); - }); - - // 画面準備完了通知受信時初期データ返却 - socket.on(protocol.SocketEvents.READY_FOR_GAME, () => { - onReadyForGame(socket, gameManager); - }); - - // ゲームプレイ中イベント群 - socket.on(protocol.SocketEvents.MOVE, (data: playerTypes.MovePayload) => { - onMove(gameManager, socket.id, data); - }); - -}; - -/** - * 切断時のゲームクリーンアップ処理 - */ -export const handleGameDisconnect = (io: Server, gameManager: GameManager, playerId: string) => { - onDisconnect(io, gameManager, playerId); -}; \ No newline at end of file diff --git a/apps/server/src/domains/game/GameLoop.ts b/apps/server/src/domains/game/GameLoop.ts index 2d9ac33..a36b44b 100644 --- a/apps/server/src/domains/game/GameLoop.ts +++ b/apps/server/src/domains/game/GameLoop.ts @@ -2,7 +2,7 @@ import { MapStore } from "./states/MapStore"; import { gridMapLogic, config } from "@repo/shared"; import type { gridMapTypes } from "@repo/shared"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; // コールバックで渡すデータの型定義 export interface TickData { diff --git a/apps/server/src/domains/game/application/services/GameSessionService.ts b/apps/server/src/domains/game/application/services/GameSessionService.ts index 48a5e3b..d91ee70 100644 --- a/apps/server/src/domains/game/application/services/GameSessionService.ts +++ b/apps/server/src/domains/game/application/services/GameSessionService.ts @@ -3,7 +3,7 @@ import { GameLoop, type TickData } from "../../GameLoop"; import { Player } from "../../entities/Player.js"; import { MapStore } from "../../states/MapStore"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; export class GameSessionService { private mapStore: MapStore; diff --git a/apps/server/src/domains/game/application/services/PlayerRegistry.ts b/apps/server/src/domains/game/application/services/PlayerRegistry.ts index e42e35e..abef2f5 100644 --- a/apps/server/src/domains/game/application/services/PlayerRegistry.ts +++ b/apps/server/src/domains/game/application/services/PlayerRegistry.ts @@ -1,6 +1,6 @@ import { config } from "@repo/shared"; import { Player } from "../../entities/Player.js"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; export class PlayerRegistry { private players: Map; diff --git a/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts b/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts index 660cd23..327a343 100644 --- a/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts @@ -1,6 +1,6 @@ import { protocol } from "@repo/shared"; import type { DisconnectPlayerPort } from "../ports/gameUseCasePorts"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; type EmitToAll = (event: string, payload?: unknown) => void; diff --git a/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts b/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts index 8681f3f..dd57ff0 100644 --- a/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts @@ -1,6 +1,6 @@ import { protocol } from "@repo/shared"; import type { ReadyForGamePort } from "../ports/gameUseCasePorts"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; type EmitToSocket = (event: string, payload?: unknown) => void; diff --git a/apps/server/src/domains/game/application/useCases/startGameUseCase.ts b/apps/server/src/domains/game/application/useCases/startGameUseCase.ts index 0362675..1e3d1d8 100644 --- a/apps/server/src/domains/game/application/useCases/startGameUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/startGameUseCase.ts @@ -1,7 +1,7 @@ import { protocol, roomConsts } from "@repo/shared"; import { RoomManager } from "@server/domains/room/RoomManager"; import type { StartGamePort } from "../ports/gameUseCasePorts"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void; diff --git a/apps/server/src/domains/game/handlers/onDisconnect.ts b/apps/server/src/domains/game/handlers/onDisconnect.ts deleted file mode 100644 index 579bcec..0000000 --- a/apps/server/src/domains/game/handlers/onDisconnect.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Server } from "socket.io"; -import { GameManager } from "@server/domains/game/GameManager"; -import { disconnectUseCase } from "@server/domains/game/application/useCases/disconnectUseCase"; -import { createEmitToAll } from "@server/network/adapters/socketEmitters"; - -const getEmitToAll = (io: Server) => createEmitToAll(io); - -export const onDisconnect = ( - io: Server, - gameManager: GameManager, - playerId: string -) => { - const emitToAll = getEmitToAll(io); - - disconnectUseCase({ - gameManager, - playerId, - emitToAll, - }); -}; diff --git a/apps/server/src/domains/game/handlers/onMove.ts b/apps/server/src/domains/game/handlers/onMove.ts deleted file mode 100644 index b07d713..0000000 --- a/apps/server/src/domains/game/handlers/onMove.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { GameManager } from "@server/domains/game/GameManager"; -import type { playerTypes } from "@repo/shared"; -import { movePlayerUseCase } from "@server/domains/game/application/useCases/movePlayerUseCase"; - -export const onMove = ( - gameManager: GameManager, - playerId: string, - data: playerTypes.MovePayload -) => { - movePlayerUseCase({ - gameManager, - playerId, - move: data, - }); -}; diff --git a/apps/server/src/domains/game/handlers/onPing.ts b/apps/server/src/domains/game/handlers/onPing.ts deleted file mode 100644 index e95998d..0000000 --- a/apps/server/src/domains/game/handlers/onPing.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Socket } from "socket.io"; -import { pingUseCase } from "@server/domains/game/application/useCases/pingUseCase"; -import { createEmitToSocket } from "@server/network/adapters/socketEmitters"; - -const getEmitToSocket = (socket: Socket) => createEmitToSocket(socket); - -export const onPing = (socket: Socket, clientTime: number) => { - const emitToSocket = getEmitToSocket(socket); - - pingUseCase({ - clientTime, - emitToSocket, - }); -}; diff --git a/apps/server/src/domains/game/handlers/onReadyForGame.ts b/apps/server/src/domains/game/handlers/onReadyForGame.ts deleted file mode 100644 index 3f88132..0000000 --- a/apps/server/src/domains/game/handlers/onReadyForGame.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Socket } from "socket.io"; -import { GameManager } from "@server/domains/game/GameManager"; -import { readyForGameUseCase } from "@server/domains/game/application/useCases/readyForGameUseCase"; -import { createEmitToSocket } from "@server/network/adapters/socketEmitters"; - -const getEmitToSocket = (socket: Socket) => createEmitToSocket(socket); - -export const onReadyForGame = ( - socket: Socket, - gameManager: GameManager -) => { - const roomId = Array.from(socket.rooms).find((room) => room !== socket.id); - const emitToSocket = getEmitToSocket(socket); - - readyForGameUseCase({ - socketId: socket.id, - roomId, - gameManager, - emitToSocket, - }); -}; diff --git a/apps/server/src/domains/game/handlers/onStartGame.ts b/apps/server/src/domains/game/handlers/onStartGame.ts deleted file mode 100644 index 62efb9e..0000000 --- a/apps/server/src/domains/game/handlers/onStartGame.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Server } from "socket.io"; -import { GameManager } from "@server/domains/game/GameManager"; -import { RoomManager } from "@server/domains/room/RoomManager"; -import { startGameUseCase } from "@server/domains/game/application/useCases/startGameUseCase"; -import { createEmitToRoom } from "@server/network/adapters/socketEmitters"; - -const getEmitToRoom = (io: Server) => createEmitToRoom(io); - -export const onStartGame = ( - io: Server, - gameManager: GameManager, - roomManager: RoomManager, - ownerId: string -) => { - const emitToRoom = getEmitToRoom(io); - - startGameUseCase({ - ownerId, - gameManager, - roomManager, - emitToRoom, - }); -}; diff --git a/apps/server/src/domains/room/RoomHandler.ts b/apps/server/src/domains/room/RoomHandler.ts deleted file mode 100644 index 8e70325..0000000 --- a/apps/server/src/domains/room/RoomHandler.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Server, Socket } from "socket.io"; -import { RoomManager } from "./RoomManager"; -import { protocol } from "@repo/shared"; -import type { roomTypes } from "@repo/shared"; -import { joinRoomUseCase } from "./application/useCases/joinRoomUseCase"; -import { roomDisconnectUseCase } from "./application/useCases/roomDisconnectUseCase"; -import { createEmitToRoom } from "@server/network/adapters/socketEmitters"; - -const getEmitToRoom = (io: Server) => createEmitToRoom(io); - -export const registerRoomHandlers = (io: Server, socket: Socket, roomManager: RoomManager) => { - const emitToRoom = getEmitToRoom(io); - - socket.on(protocol.SocketEvents.JOIN_ROOM, (data: roomTypes.JoinRoomPayload) => { - const { roomId } = data; - - socket.join(roomId); - - joinRoomUseCase({ - roomManager, - socketId: socket.id, - data, - emitToRoom, - }); - }); - -}; - -/** - * 切断時のルームクリーンアップ処理 - */ -export const handleRoomDisconnect = (io: Server, socket: Socket, roomManager: RoomManager) => { - const emitToRoom = getEmitToRoom(io); - - roomDisconnectUseCase({ - roomManager, - socketId: socket.id, - emitToRoom, - }); -}; \ No newline at end of file diff --git a/apps/server/src/domains/room/application/services/RoomExitService.ts b/apps/server/src/domains/room/application/services/RoomExitService.ts index 7378f7d..f7b8106 100644 --- a/apps/server/src/domains/room/application/services/RoomExitService.ts +++ b/apps/server/src/domains/room/application/services/RoomExitService.ts @@ -1,5 +1,5 @@ import type { roomTypes } from "@repo/shared"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; export class RoomExitService { constructor(private rooms: Map) {} diff --git a/apps/server/src/domains/room/application/services/RoomJoinService.ts b/apps/server/src/domains/room/application/services/RoomJoinService.ts index fcb5570..c9082d7 100644 --- a/apps/server/src/domains/room/application/services/RoomJoinService.ts +++ b/apps/server/src/domains/room/application/services/RoomJoinService.ts @@ -1,6 +1,6 @@ import { config, roomConsts } from "@repo/shared"; import type { roomTypes } from "@repo/shared"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; export class RoomJoinService { constructor(private rooms: Map) {} diff --git a/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts b/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts index f3d11b7..1123299 100644 --- a/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts +++ b/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts @@ -1,7 +1,7 @@ import { protocol } from "@repo/shared"; import type { roomTypes } from "@repo/shared"; import type { JoinRoomPort } from "../ports/roomUseCasePorts"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void; diff --git a/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts b/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts index 0d71846..e3c4a14 100644 --- a/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts +++ b/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts @@ -1,6 +1,6 @@ import { protocol } from "@repo/shared"; import type { DisconnectRoomPort } from "../ports/roomUseCasePorts"; -import { logEvent } from "@server/network/logging/logEvent"; +import { logEvent } from "@server/logging/logEvent"; type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void; diff --git a/apps/server/src/index.ts b/apps/server/src/index.ts index 55840bf..77f2750 100644 --- a/apps/server/src/index.ts +++ b/apps/server/src/index.ts @@ -1,39 +1,13 @@ -import { Server } from "socket.io"; -import { createServer } from "http"; -import { GameManager } from "./domains/game/GameManager"; -import { RoomManager } from "./domains/room/RoomManager"; -import { SocketManager } from "./network/SocketManager"; +import { createHttpServer } from "./network/bootstrap/createHttpServer"; +import { boot } from "./network/bootstrap/boot"; import { config } from "@repo/shared"; // サーバー待受ポート const PORT = process.env.PORT || config.NETWORK_CONFIG.DEV_SERVER_PORT; // HTTP サーバー・Socket.io サーバー生成 -const httpServer = createServer((req, res) => { - // Render の HTTP ヘルスチェック向けに 200 を返す - if (req.url === "/") { - res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); - res.end("ok"); - return; - } - - res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }); - res.end("not found"); -}); -const io = new Server(httpServer, { - cors: { - // 開発環境向け全オリジン許可設定 - origin: config.NETWORK_CONFIG.CORS_ORIGIN, - methods: [...config.NETWORK_CONFIG.CORS_METHODS] - }, -}); - -// ゲーム管理・通信管理クラス初期化 -const gameManager = new GameManager(); -const roomManager = new RoomManager(); -const socketManager = new SocketManager(io, gameManager, roomManager); - -socketManager.initialize(); +const httpServer = createHttpServer(); +boot(httpServer); // HTTP サーバー起動 httpServer.listen(PORT, () => { diff --git a/apps/server/src/logging/logEvent.ts b/apps/server/src/logging/logEvent.ts new file mode 100644 index 0000000..626324c --- /dev/null +++ b/apps/server/src/logging/logEvent.ts @@ -0,0 +1,11 @@ +type LogEventPayload = { + event: string; + result: string; + socketId?: string; + roomId?: string; + [key: string]: unknown; +}; + +export const logEvent = (scope: string, payload: LogEventPayload) => { + console.log(`[${scope}]`, payload); +}; diff --git a/apps/server/src/network/SocketManager.ts b/apps/server/src/network/SocketManager.ts index 01bff7d..6ab7ad5 100644 --- a/apps/server/src/network/SocketManager.ts +++ b/apps/server/src/network/SocketManager.ts @@ -2,8 +2,8 @@ import { GameManager } from "@server/domains/game/GameManager"; import { RoomManager } from "@server/domains/room/RoomManager"; import { protocol } from "@repo/shared"; -import { registerRoomHandlers, handleRoomDisconnect } from "@server/domains/room/RoomHandler"; -import { registerGameHandlers, handleGameDisconnect } from "@server/domains/game/GameHandler"; +import { registerRoomHandlers, handleRoomDisconnect } from "./handlers/RoomHandler"; +import { registerGameHandlers, handleGameDisconnect } from "./handlers/GameHandler"; export class SocketManager { private io: Server; diff --git a/apps/server/src/network/bootstrap/boot.ts b/apps/server/src/network/bootstrap/boot.ts new file mode 100644 index 0000000..004c870 --- /dev/null +++ b/apps/server/src/network/bootstrap/boot.ts @@ -0,0 +1,14 @@ +import type { Server as HttpServer } from "http"; +import { GameManager } from "@server/domains/game/GameManager"; +import { RoomManager } from "@server/domains/room/RoomManager"; +import { SocketManager } from "../SocketManager"; +import { createIo } from "./createIo"; + +export const boot = (httpServer: HttpServer) => { + const io = createIo(httpServer); + const gameManager = new GameManager(); + const roomManager = new RoomManager(); + const socketManager = new SocketManager(io, gameManager, roomManager); + + socketManager.initialize(); +}; diff --git a/apps/server/src/network/bootstrap/createHttpServer.ts b/apps/server/src/network/bootstrap/createHttpServer.ts new file mode 100644 index 0000000..3434920 --- /dev/null +++ b/apps/server/src/network/bootstrap/createHttpServer.ts @@ -0,0 +1,14 @@ +import { createServer } from "http"; + +export const createHttpServer = () => { + return createServer((req, res) => { + if (req.url === "/") { + res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("ok"); + return; + } + + res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }); + res.end("not found"); + }); +}; diff --git a/apps/server/src/network/bootstrap/createIo.ts b/apps/server/src/network/bootstrap/createIo.ts new file mode 100644 index 0000000..e77fb86 --- /dev/null +++ b/apps/server/src/network/bootstrap/createIo.ts @@ -0,0 +1,12 @@ +import { Server } from "socket.io"; +import { config } from "@repo/shared"; +import type { Server as HttpServer } from "http"; + +export const createIo = (httpServer: HttpServer) => { + return new Server(httpServer, { + cors: { + origin: config.NETWORK_CONFIG.CORS_ORIGIN, + methods: [...config.NETWORK_CONFIG.CORS_METHODS], + }, + }); +}; diff --git a/apps/server/src/network/createIo.ts b/apps/server/src/network/createIo.ts new file mode 100644 index 0000000..e77fb86 --- /dev/null +++ b/apps/server/src/network/createIo.ts @@ -0,0 +1,12 @@ +import { Server } from "socket.io"; +import { config } from "@repo/shared"; +import type { Server as HttpServer } from "http"; + +export const createIo = (httpServer: HttpServer) => { + return new Server(httpServer, { + cors: { + origin: config.NETWORK_CONFIG.CORS_ORIGIN, + methods: [...config.NETWORK_CONFIG.CORS_METHODS], + }, + }); +}; diff --git a/apps/server/src/network/handlers/CommonHandler.ts b/apps/server/src/network/handlers/CommonHandler.ts new file mode 100644 index 0000000..ef0dc0e --- /dev/null +++ b/apps/server/src/network/handlers/CommonHandler.ts @@ -0,0 +1,23 @@ +import { Server, Socket } from "socket.io"; +import { + createEmitToAll, + createEmitToRoom, + createEmitToSocket, +} from "@server/network/adapters/socketEmitters"; + +export type CommonHandlerContext = { + emitToAll: ReturnType; + emitToRoom: ReturnType; + emitToSocket: ReturnType; +}; + +export const createCommonHandlerContext = ( + io: Server, + socket: Socket +): CommonHandlerContext => { + return { + emitToAll: createEmitToAll(io), + emitToRoom: createEmitToRoom(io), + emitToSocket: createEmitToSocket(socket), + }; +}; diff --git a/apps/server/src/network/handlers/GameHandler.ts b/apps/server/src/network/handlers/GameHandler.ts new file mode 100644 index 0000000..c6b1ef1 --- /dev/null +++ b/apps/server/src/network/handlers/GameHandler.ts @@ -0,0 +1,2 @@ +export { registerGameHandlers } from "./game/registerGameHandlers"; +export { handleGameDisconnect } from "./game/handleGameDisconnect"; diff --git a/apps/server/src/network/handlers/RoomHandler.ts b/apps/server/src/network/handlers/RoomHandler.ts new file mode 100644 index 0000000..dcd3d5e --- /dev/null +++ b/apps/server/src/network/handlers/RoomHandler.ts @@ -0,0 +1,2 @@ +export { registerRoomHandlers } from "./room/registerRoomHandlers"; +export { handleRoomDisconnect } from "./room/handleRoomDisconnect"; diff --git a/apps/server/src/network/handlers/game/handleGameDisconnect.ts b/apps/server/src/network/handlers/game/handleGameDisconnect.ts new file mode 100644 index 0000000..dc9e33d --- /dev/null +++ b/apps/server/src/network/handlers/game/handleGameDisconnect.ts @@ -0,0 +1,16 @@ +import { Server } from "socket.io"; +import { GameManager } from "@server/domains/game/GameManager"; +import { disconnectUseCase } from "@server/domains/game/application/useCases/disconnectUseCase"; +import { createEmitToAll } from "@server/network/adapters/socketEmitters"; + +export const handleGameDisconnect = ( + io: Server, + gameManager: GameManager, + playerId: string +) => { + disconnectUseCase({ + gameManager, + playerId, + emitToAll: createEmitToAll(io), + }); +}; diff --git a/apps/server/src/network/handlers/game/registerGameHandlers.ts b/apps/server/src/network/handlers/game/registerGameHandlers.ts new file mode 100644 index 0000000..61a8f65 --- /dev/null +++ b/apps/server/src/network/handlers/game/registerGameHandlers.ts @@ -0,0 +1,54 @@ +import { Server, Socket } from "socket.io"; +import { GameManager } from "@server/domains/game/GameManager"; +import { RoomManager } from "@server/domains/room/RoomManager"; +import { protocol } from "@repo/shared"; +import type { playerTypes } from "@repo/shared"; +import { pingUseCase } from "@server/domains/game/application/useCases/pingUseCase"; +import { startGameUseCase } from "@server/domains/game/application/useCases/startGameUseCase"; +import { readyForGameUseCase } from "@server/domains/game/application/useCases/readyForGameUseCase"; +import { movePlayerUseCase } from "@server/domains/game/application/useCases/movePlayerUseCase"; +import { createCommonHandlerContext } from "@server/network/handlers/CommonHandler"; + +export const registerGameHandlers = ( + io: Server, + socket: Socket, + gameManager: GameManager, + roomManager: RoomManager +) => { + const common = createCommonHandlerContext(io, socket); + + socket.on(protocol.SocketEvents.PING, (clientTime: number) => { + pingUseCase({ + clientTime, + emitToSocket: common.emitToSocket, + }); + }); + + socket.on(protocol.SocketEvents.START_GAME, () => { + startGameUseCase({ + ownerId: socket.id, + gameManager, + roomManager, + emitToRoom: common.emitToRoom, + }); + }); + + socket.on(protocol.SocketEvents.READY_FOR_GAME, () => { + const roomId = Array.from(socket.rooms).find((room) => room !== socket.id); + + readyForGameUseCase({ + socketId: socket.id, + roomId, + gameManager, + emitToSocket: common.emitToSocket, + }); + }); + + socket.on(protocol.SocketEvents.MOVE, (data: playerTypes.MovePayload) => { + movePlayerUseCase({ + gameManager, + playerId: socket.id, + move: data, + }); + }); +}; diff --git a/apps/server/src/network/handlers/room/handleRoomDisconnect.ts b/apps/server/src/network/handlers/room/handleRoomDisconnect.ts new file mode 100644 index 0000000..03046af --- /dev/null +++ b/apps/server/src/network/handlers/room/handleRoomDisconnect.ts @@ -0,0 +1,16 @@ +import { Server, Socket } from "socket.io"; +import { RoomManager } from "@server/domains/room/RoomManager"; +import { roomDisconnectUseCase } from "@server/domains/room/application/useCases/roomDisconnectUseCase"; +import { createEmitToRoom } from "@server/network/adapters/socketEmitters"; + +export const handleRoomDisconnect = ( + io: Server, + socket: Socket, + roomManager: RoomManager +) => { + roomDisconnectUseCase({ + roomManager, + socketId: socket.id, + emitToRoom: createEmitToRoom(io), + }); +}; diff --git a/apps/server/src/network/handlers/room/registerRoomHandlers.ts b/apps/server/src/network/handlers/room/registerRoomHandlers.ts new file mode 100644 index 0000000..f5173b5 --- /dev/null +++ b/apps/server/src/network/handlers/room/registerRoomHandlers.ts @@ -0,0 +1,27 @@ +import { Server, Socket } from "socket.io"; +import { RoomManager } from "@server/domains/room/RoomManager"; +import { protocol } from "@repo/shared"; +import type { roomTypes } from "@repo/shared"; +import { joinRoomUseCase } from "@server/domains/room/application/useCases/joinRoomUseCase"; +import { createCommonHandlerContext } from "@server/network/handlers/CommonHandler"; + +export const registerRoomHandlers = ( + io: Server, + socket: Socket, + roomManager: RoomManager +) => { + const common = createCommonHandlerContext(io, socket); + + socket.on(protocol.SocketEvents.JOIN_ROOM, (data: roomTypes.JoinRoomPayload) => { + const { roomId } = data; + + socket.join(roomId); + + joinRoomUseCase({ + roomManager, + socketId: socket.id, + data, + emitToRoom: common.emitToRoom, + }); + }); +}; diff --git a/apps/server/src/network/logging/logEvent.ts b/apps/server/src/network/logging/logEvent.ts deleted file mode 100644 index 626324c..0000000 --- a/apps/server/src/network/logging/logEvent.ts +++ /dev/null @@ -1,11 +0,0 @@ -type LogEventPayload = { - event: string; - result: string; - socketId?: string; - roomId?: string; - [key: string]: unknown; -}; - -export const logEvent = (scope: string, payload: LogEventPayload) => { - console.log(`[${scope}]`, payload); -}; diff --git "a/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" "b/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" index 8a7a56b..3e34b9e 100644 --- "a/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" +++ "b/docs/01_Env/ENV_01_\347\222\260\345\242\203\346\247\213\347\257\211\343\203\273\346\212\200\350\241\223\343\202\271\343\202\277\343\203\203\343\202\257.txt" @@ -95,20 +95,35 @@ │ ├── tsconfig.json # TS設定 │ └── src/ │ ├── index.ts # サーバー起点 + │ ├── logging/ + │ │ └── logEvent.ts # 共通ログ出力 │ ├── domains/ │ │ ├── game/ - │ │ │ ├── GameHandler.ts # ゲーム入出力 │ │ │ ├── GameLoop.ts # 固定ループ │ │ │ ├── GameManager.ts # ゲーム状態管理 + │ │ │ ├── application/ # ユースケース・サービス │ │ │ ├── entities/ │ │ │ │ └── Player.ts # サーバーPlayer │ │ │ └── states/ │ │ │ └── MapStore.ts # マップ状態保持 │ │ └── room/ - │ │ ├── RoomHandler.ts # ルーム入出力 + │ │ ├── application/ # ユースケース・サービス │ │ └── RoomManager.ts # ルーム管理 │ └── network/ - │ └── SocketManager.ts # WS接続管理 + │ ├── SocketManager.ts # WS接続管理 + │ ├── adapters/ + │ │ └── socketEmitters.ts # 送信アダプタ + │ ├── handlers/ + │ │ ├── CommonHandler.ts # 共通WSハンドラ + │ │ ├── GameHandler.ts # ゲームWSハンドラ(中間層) + │ │ ├── RoomHandler.ts # ルームWSハンドラ(中間層) + │ │ ├── game/ # ゲーム中粒度配線 + │ │ └── room/ # ルーム中粒度配線 + │ ├── bootstrap/ + │ │ ├── createHttpServer.ts # HTTP生成 + │ │ ├── createIo.ts # Socket.IO生成 + │ │ └── boot.ts # 起動配線 + │ └── createIo.ts # 互換用ファイル ├── docs/ │ ├── 01_Env/ │ │ ├── ENV_01_環境構築・技術スタック.txt # 環境・技術定義 @@ -188,13 +203,13 @@ - 採用理由: 50人同時対戦時の大量のスプライト描画と60fps維持のため. ・UI Library: Preact (または Vanilla HTML/CSS) - 採用理由: ゲームループへの負荷を避けつつ,軽量なHUDを構築するため. - ・Network: Native WebSocket API + ・Network: socket.io-client 3-3. バックエンド (Server) ・Runtime: Node.js ・Execution: tsx (開発時の高速実行・ウォッチ用) - ・WebSocket Library: ws - - 採用理由: 軽量かつ標準的.uWebSockets.js への移行も視野に入れるが初期は ws で実装. + ・WebSocket Library: Socket.IO + - 採用理由: 接続管理・イベント配線を明確化しやすく,Client 側 (socket.io-client) と整合するため. ・Logic: 独自ループ (20Hz固定) - Physics Engine: 使用しない (shared/physics.ts による独自グリッド判定)