diff --git a/apps/server/src/domains/game/GameLoop.ts b/apps/server/src/domains/game/GameLoop.ts index 65a7e69..2d9ac33 100644 --- a/apps/server/src/domains/game/GameLoop.ts +++ b/apps/server/src/domains/game/GameLoop.ts @@ -2,6 +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"; // コールバックで渡すデータの型定義 export interface TickData { @@ -76,14 +77,23 @@ }, this.tickRate); - console.log(`[GameLoop] Started for room: ${this.roomId} at ${this.tickRate}ms`); + logEvent("GameLoop", { + event: "GAME_LOOP", + result: "started", + roomId: this.roomId, + tickRate: this.tickRate, + }); } stop() { if (this.loopId) { clearInterval(this.loopId); this.loopId = null; - console.log(`[GameLoop] Stopped for room: ${this.roomId}`); + logEvent("GameLoop", { + event: "GAME_LOOP", + result: "stopped", + roomId: this.roomId, + }); } } } \ No newline at end of file diff --git a/apps/server/src/domains/game/application/services/GameSessionService.ts b/apps/server/src/domains/game/application/services/GameSessionService.ts index ab33e56..48a5e3b 100644 --- a/apps/server/src/domains/game/application/services/GameSessionService.ts +++ b/apps/server/src/domains/game/application/services/GameSessionService.ts @@ -3,6 +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"; export class GameSessionService { private mapStore: MapStore; @@ -26,7 +27,11 @@ onGameEnd: () => void ) { if (this.gameLoops.has(roomId)) { - console.log("[GameManager] startGameLoop ignored (already running)", { roomId }); + logEvent("GameSessionService", { + event: "START_GAME_LOOP", + result: "ignored_already_running", + roomId, + }); return; } @@ -49,7 +54,12 @@ loop.start(); this.gameLoops.set(roomId, loop); - console.log("[GameManager] game loop started", { roomId, playerCount: playerIds.length }); + logEvent("GameSessionService", { + event: "START_GAME_LOOP", + result: "started", + roomId, + playerCount: playerIds.length, + }); } public stopGameLoop(roomId: string) { @@ -58,9 +68,17 @@ loop.stop(); this.gameLoops.delete(roomId); this.roomStartTimes.delete(roomId); - console.log("[GameManager] game loop stopped", { roomId }); + logEvent("GameSessionService", { + event: "STOP_GAME_LOOP", + result: "stopped", + roomId, + }); } else { - console.log("[GameManager] stopGameLoop ignored (not running)", { roomId }); + logEvent("GameSessionService", { + event: "STOP_GAME_LOOP", + result: "ignored_not_running", + roomId, + }); } } diff --git a/apps/server/src/domains/game/application/services/PlayerRegistry.ts b/apps/server/src/domains/game/application/services/PlayerRegistry.ts index 5233ce4..e42e35e 100644 --- a/apps/server/src/domains/game/application/services/PlayerRegistry.ts +++ b/apps/server/src/domains/game/application/services/PlayerRegistry.ts @@ -1,5 +1,6 @@ import { config } from "@repo/shared"; import { Player } from "../../entities/Player.js"; +import { logEvent } from "@server/network/logging/logEvent"; export class PlayerRegistry { private players: Map; @@ -13,16 +14,30 @@ player.x = config.GAME_CONFIG.GRID_COLS / 2; player.y = config.GAME_CONFIG.GRID_ROWS / 2; this.players.set(id, player); - console.log("[GameManager] player added", { playerId: id, totalPlayers: this.players.size }); + logEvent("PlayerRegistry", { + event: "PLAYER_ADD", + result: "added", + socketId: id, + totalPlayers: this.players.size, + }); return player; } public removePlayer(id: string) { const existed = this.players.delete(id); if (existed) { - console.log("[GameManager] player removed", { playerId: id, totalPlayers: this.players.size }); + logEvent("PlayerRegistry", { + event: "PLAYER_REMOVE", + result: "removed", + socketId: id, + totalPlayers: this.players.size, + }); } else { - console.log("[GameManager] player remove ignored (not found)", { playerId: id }); + logEvent("PlayerRegistry", { + event: "PLAYER_REMOVE", + result: "ignored_not_found", + socketId: id, + }); } } @@ -33,15 +48,29 @@ public movePlayer(id: string, x: number, y: number) { const player = this.players.get(id); if (player) { - console.log(`Move Request -> ID:${id.slice(0, 4)} x:${Math.round(x)} y:${Math.round(y)}`); + logEvent("PlayerRegistry", { + event: "MOVE", + result: "received", + socketId: id, + x: Math.round(x), + y: Math.round(y), + }); if (typeof x !== "number" || typeof y !== "number" || isNaN(x) || isNaN(y)) { - console.log("⚠️ 無効なデータなので無視しました"); + logEvent("PlayerRegistry", { + event: "MOVE", + result: "ignored_invalid_payload", + socketId: id, + }); return; } player.x = x; player.y = y; } else { - console.log("[GameManager] move ignored (player not found)", { playerId: id }); + logEvent("PlayerRegistry", { + event: "MOVE", + result: "ignored_player_not_found", + socketId: id, + }); } } diff --git a/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts b/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts index 1db69d0..660cd23 100644 --- a/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/disconnectUseCase.ts @@ -1,5 +1,6 @@ import { protocol } from "@repo/shared"; import type { DisconnectPlayerPort } from "../ports/gameUseCasePorts"; +import { logEvent } from "@server/network/logging/logEvent"; type EmitToAll = (event: string, payload?: unknown) => void; @@ -16,5 +17,9 @@ }: DisconnectUseCaseParams) => { gameManager.removePlayer(playerId); emitToAll(protocol.SocketEvents.REMOVE_PLAYER, playerId); - console.log("[GameHandler] player removed", { playerId }); + logEvent("GameUseCase", { + event: "DISCONNECT", + result: "player_removed", + socketId: playerId, + }); }; diff --git a/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts b/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts index 92ab796..8681f3f 100644 --- a/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/readyForGameUseCase.ts @@ -1,5 +1,6 @@ import { protocol } from "@repo/shared"; import type { ReadyForGamePort } from "../ports/gameUseCasePorts"; +import { logEvent } from "@server/network/logging/logEvent"; type EmitToSocket = (event: string, payload?: unknown) => void; @@ -19,13 +20,20 @@ const allPlayers = gameManager.getAllPlayers(); emitToSocket(protocol.SocketEvents.CURRENT_PLAYERS, allPlayers); - console.log("[GameHandler] READY_FOR_GAME received", { + logEvent("GameUseCase", { + event: "READY_FOR_GAME", + result: "received", socketId, + roomId, totalPlayers: allPlayers.length, }); if (!roomId) { - console.log("[GameHandler] READY_FOR_GAME missing roomId", { socketId }); + logEvent("GameUseCase", { + event: "READY_FOR_GAME", + result: "ignored_missing_room", + socketId, + }); return; } @@ -35,7 +43,9 @@ } emitToSocket(protocol.SocketEvents.GAME_START, { startTime }); - console.log("[GameHandler] GAME_START sent to ready client", { + logEvent("GameUseCase", { + event: "GAME_START", + result: "emitted", socketId, roomId, startTime, diff --git a/apps/server/src/domains/game/application/useCases/startGameUseCase.ts b/apps/server/src/domains/game/application/useCases/startGameUseCase.ts index 41b2772..0362675 100644 --- a/apps/server/src/domains/game/application/useCases/startGameUseCase.ts +++ b/apps/server/src/domains/game/application/useCases/startGameUseCase.ts @@ -1,6 +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"; type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void; @@ -19,18 +20,29 @@ }: StartGameUseCaseParams) => { const room = roomManager.getRoomByOwnerId(ownerId); if (!room) { - console.log("[GameHandler] START_GAME ignored (no room)", { socketId: ownerId }); + logEvent("GameUseCase", { + event: "START_GAME", + result: "ignored_no_room", + socketId: ownerId, + }); return; } if (room.status === roomConsts.RoomPhase.PLAYING) { - console.log("[GameHandler] START_GAME ignored (already playing)", { roomId: room.roomId }); + logEvent("GameUseCase", { + event: "START_GAME", + result: "ignored_already_playing", + roomId: room.roomId, + socketId: ownerId, + }); return; } - console.log("[GameHandler] START_GAME accepted", { + logEvent("GameUseCase", { + event: "START_GAME", + result: "accepted", roomId: room.roomId, - ownerId, + socketId: ownerId, totalPlayers: room.players.length, }); @@ -55,7 +67,12 @@ } }, () => { - console.log(`[GameHandler] ルーム ${room.roomId} のゲームが終了しました (3分経過)`); + logEvent("GameUseCase", { + event: "GAME_END", + result: "emitted", + roomId: room.roomId, + reason: "duration_elapsed", + }); emitToRoom(room.roomId, protocol.SocketEvents.GAME_END); room.status = roomConsts.RoomPhase.WAITING; } diff --git a/apps/server/src/domains/game/handlers/onDisconnect.ts b/apps/server/src/domains/game/handlers/onDisconnect.ts index 5555397..579bcec 100644 --- a/apps/server/src/domains/game/handlers/onDisconnect.ts +++ b/apps/server/src/domains/game/handlers/onDisconnect.ts @@ -1,22 +1,20 @@ 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: (event, payload) => { - if (payload === undefined) { - io.emit(event); - return; - } - - io.emit(event, payload); - }, + emitToAll, }); }; diff --git a/apps/server/src/domains/game/handlers/onPing.ts b/apps/server/src/domains/game/handlers/onPing.ts index 99c8f88..e95998d 100644 --- a/apps/server/src/domains/game/handlers/onPing.ts +++ b/apps/server/src/domains/game/handlers/onPing.ts @@ -1,16 +1,14 @@ 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: (event, payload) => { - if (payload === undefined) { - socket.emit(event); - return; - } - - socket.emit(event, payload); - }, + emitToSocket, }); }; diff --git a/apps/server/src/domains/game/handlers/onReadyForGame.ts b/apps/server/src/domains/game/handlers/onReadyForGame.ts index 6bece4f..3f88132 100644 --- a/apps/server/src/domains/game/handlers/onReadyForGame.ts +++ b/apps/server/src/domains/game/handlers/onReadyForGame.ts @@ -1,24 +1,21 @@ 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: (event, payload) => { - if (payload === undefined) { - socket.emit(event); - return; - } - - socket.emit(event, payload); - }, + emitToSocket, }); }; diff --git a/apps/server/src/domains/game/handlers/onStartGame.ts b/apps/server/src/domains/game/handlers/onStartGame.ts index 528caaa..62efb9e 100644 --- a/apps/server/src/domains/game/handlers/onStartGame.ts +++ b/apps/server/src/domains/game/handlers/onStartGame.ts @@ -2,6 +2,9 @@ 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, @@ -9,17 +12,12 @@ roomManager: RoomManager, ownerId: string ) => { + const emitToRoom = getEmitToRoom(io); + startGameUseCase({ ownerId, gameManager, roomManager, - emitToRoom: (roomId, event, payload) => { - if (payload === undefined) { - io.to(roomId).emit(event); - return; - } - - io.to(roomId).emit(event, payload); - }, + emitToRoom, }); }; diff --git a/apps/server/src/domains/room/RoomHandler.ts b/apps/server/src/domains/room/RoomHandler.ts index 756cb63..8e70325 100644 --- a/apps/server/src/domains/room/RoomHandler.ts +++ b/apps/server/src/domains/room/RoomHandler.ts @@ -4,8 +4,12 @@ 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; @@ -16,14 +20,7 @@ roomManager, socketId: socket.id, data, - emitToRoom: (targetRoomId, event, payload) => { - if (payload === undefined) { - io.to(targetRoomId).emit(event); - return; - } - - io.to(targetRoomId).emit(event, payload); - }, + emitToRoom, }); }); @@ -33,16 +30,11 @@ * 切断時のルームクリーンアップ処理 */ export const handleRoomDisconnect = (io: Server, socket: Socket, roomManager: RoomManager) => { + const emitToRoom = getEmitToRoom(io); + roomDisconnectUseCase({ roomManager, socketId: socket.id, - emitToRoom: (roomId, event, payload) => { - if (payload === undefined) { - io.to(roomId).emit(event); - return; - } - - io.to(roomId).emit(event, payload); - }, + emitToRoom, }); }; \ No newline at end of file diff --git a/apps/server/src/domains/room/RoomManager.ts b/apps/server/src/domains/room/RoomManager.ts index 48832ec..defaf38 100644 --- a/apps/server/src/domains/room/RoomManager.ts +++ b/apps/server/src/domains/room/RoomManager.ts @@ -1,83 +1,32 @@ -import { roomConsts, config } from "@repo/shared"; import type { roomTypes } from "@repo/shared"; +import { RoomJoinService } from "./application/services/RoomJoinService"; +import { RoomExitService } from "./application/services/RoomExitService"; +import { RoomQueryService } from "./application/services/RoomQueryService"; export class RoomManager { private rooms: Map = new Map(); + private roomJoinService: RoomJoinService; + private roomExitService: RoomExitService; + private roomQueryService: RoomQueryService; + + constructor() { + this.roomJoinService = new RoomJoinService(this.rooms); + this.roomExitService = new RoomExitService(this.rooms); + this.roomQueryService = new RoomQueryService(this.rooms); + } // ルームにプレイヤーを追加(なければ作成) public addPlayerToRoom(roomId: string, socketId: string, playerName: string): roomTypes.Room { - let room = this.rooms.get(roomId); - if (!room) { - room = { - roomId: roomId, - ownerId: socketId, - players: [], - status: roomConsts.RoomPhase.WAITING, - maxPlayers: config.GAME_CONFIG.MAX_PLAYERS_PER_ROOM - }; - this.rooms.set(roomId, room); - console.log("[RoomManager] created room", { roomId, ownerId: socketId }); - } - - const newPlayer: roomTypes.RoomMember = { - id: socketId, - name: playerName, - isOwner: room.ownerId === socketId, - isReady: false - }; - room.players.push(newPlayer); - console.log("[RoomManager] player joined", { - roomId, - socketId, - playerName, - totalPlayers: room.players.length - }); - - return room; + return this.roomJoinService.addPlayerToRoom(roomId, socketId, playerName); } // プレイヤーをルームから削除し、更新があったルームの配列を返す public removePlayer(socketId: string): roomTypes.Room[] { - const updatedRooms: roomTypes.Room[] = []; - - for (const [roomId, room] of this.rooms.entries()) { - const playerIndex = room.players.findIndex(p => p.id === socketId); - if (playerIndex !== -1) { - room.players.splice(playerIndex, 1); - console.log("[RoomManager] player left", { - roomId, - socketId, - totalPlayers: room.players.length - }); - - if (room.players.length === 0) { - // 空ルーム削除 - this.rooms.delete(roomId); - console.log("[RoomManager] deleted room", { roomId }); - } else { - // オーナー切断時所有権移譲処理 - if (room.ownerId === socketId) { - room.ownerId = room.players[0].id; - room.players[0].isOwner = true; - console.log("[RoomManager] transferred ownership", { - roomId, - newOwnerId: room.ownerId - }); - } - updatedRooms.push(room); - } - } - } - return updatedRooms; + return this.roomExitService.removePlayer(socketId); } // オーナーIDからルームを取得 public getRoomByOwnerId(ownerId: string): roomTypes.Room | undefined { - for (const room of this.rooms.values()) { - if (room.ownerId === ownerId) { - return room; - } - } - return undefined; + return this.roomQueryService.getRoomByOwnerId(ownerId); } } \ 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 new file mode 100644 index 0000000..7378f7d --- /dev/null +++ b/apps/server/src/domains/room/application/services/RoomExitService.ts @@ -0,0 +1,53 @@ +import type { roomTypes } from "@repo/shared"; +import { logEvent } from "@server/network/logging/logEvent"; + +export class RoomExitService { + constructor(private rooms: Map) {} + + public removePlayer(socketId: string): roomTypes.Room[] { + const updatedRooms: roomTypes.Room[] = []; + + for (const [roomId, room] of this.rooms.entries()) { + const playerIndex = room.players.findIndex((player) => player.id === socketId); + if (playerIndex === -1) { + continue; + } + + room.players.splice(playerIndex, 1); + logEvent("RoomExitService", { + event: "PLAYER_LEAVE", + result: "removed", + roomId, + socketId, + totalPlayers: room.players.length, + }); + + if (room.players.length === 0) { + this.rooms.delete(roomId); + logEvent("RoomExitService", { + event: "ROOM_DELETE", + result: "deleted", + roomId, + socketId, + }); + continue; + } + + if (room.ownerId === socketId) { + room.ownerId = room.players[0].id; + room.players[0].isOwner = true; + logEvent("RoomExitService", { + event: "OWNER_TRANSFER", + result: "transferred", + roomId, + socketId, + newOwnerId: room.ownerId, + }); + } + + updatedRooms.push(room); + } + + return updatedRooms; + } +} diff --git a/apps/server/src/domains/room/application/services/RoomJoinService.ts b/apps/server/src/domains/room/application/services/RoomJoinService.ts new file mode 100644 index 0000000..fcb5570 --- /dev/null +++ b/apps/server/src/domains/room/application/services/RoomJoinService.ts @@ -0,0 +1,47 @@ +import { config, roomConsts } from "@repo/shared"; +import type { roomTypes } from "@repo/shared"; +import { logEvent } from "@server/network/logging/logEvent"; + +export class RoomJoinService { + constructor(private rooms: Map) {} + + public addPlayerToRoom(roomId: string, socketId: string, playerName: string): roomTypes.Room { + let room = this.rooms.get(roomId); + if (!room) { + room = { + roomId, + ownerId: socketId, + players: [], + status: roomConsts.RoomPhase.WAITING, + maxPlayers: config.GAME_CONFIG.MAX_PLAYERS_PER_ROOM, + }; + this.rooms.set(roomId, room); + logEvent("RoomJoinService", { + event: "ROOM_CREATE", + result: "created", + roomId, + socketId, + ownerId: socketId, + }); + } + + const newPlayer: roomTypes.RoomMember = { + id: socketId, + name: playerName, + isOwner: room.ownerId === socketId, + isReady: false, + }; + + room.players.push(newPlayer); + logEvent("RoomJoinService", { + event: "PLAYER_JOIN", + result: "joined", + roomId, + socketId, + playerName, + totalPlayers: room.players.length, + }); + + return room; + } +} diff --git a/apps/server/src/domains/room/application/services/RoomQueryService.ts b/apps/server/src/domains/room/application/services/RoomQueryService.ts new file mode 100644 index 0000000..3ad5dc2 --- /dev/null +++ b/apps/server/src/domains/room/application/services/RoomQueryService.ts @@ -0,0 +1,15 @@ +import type { roomTypes } from "@repo/shared"; + +export class RoomQueryService { + constructor(private rooms: Map) {} + + public getRoomByOwnerId(ownerId: string): roomTypes.Room | undefined { + for (const room of this.rooms.values()) { + if (room.ownerId === ownerId) { + return room; + } + } + + return undefined; + } +} diff --git a/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts b/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts index 2123b35..f3d11b7 100644 --- a/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts +++ b/apps/server/src/domains/room/application/useCases/joinRoomUseCase.ts @@ -1,6 +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"; type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void; @@ -18,13 +19,22 @@ emitToRoom, }: JoinRoomUseCaseParams) => { const { roomId, playerName } = data; - console.log("[RoomHandler] JOIN_ROOM received", { roomId, socketId, playerName }); + logEvent("RoomUseCase", { + event: "JOIN_ROOM", + result: "received", + roomId, + socketId, + playerName, + }); const room = roomManager.addPlayerToRoom(roomId, socketId, playerName); emitToRoom(roomId, protocol.SocketEvents.ROOM_UPDATE, room); - console.log("[RoomHandler] ROOM_UPDATE emitted", { + logEvent("RoomUseCase", { + event: "ROOM_UPDATE", + result: "emitted", roomId, + socketId, ownerId: room.ownerId, totalPlayers: room.players.length, }); diff --git a/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts b/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts index be33326..0d71846 100644 --- a/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts +++ b/apps/server/src/domains/room/application/useCases/roomDisconnectUseCase.ts @@ -1,5 +1,6 @@ import { protocol } from "@repo/shared"; import type { DisconnectRoomPort } from "../ports/roomUseCasePorts"; +import { logEvent } from "@server/network/logging/logEvent"; type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void; @@ -15,15 +16,20 @@ emitToRoom, }: RoomDisconnectUseCaseParams) => { const updatedRooms = roomManager.removePlayer(socketId); - console.log("[RoomHandler] disconnect cleanup", { + logEvent("RoomUseCase", { + event: "DISCONNECT", + result: "processed", socketId, updatedRoomCount: updatedRooms.length, }); updatedRooms.forEach((room) => { emitToRoom(room.roomId, protocol.SocketEvents.ROOM_UPDATE, room); - console.log("[RoomHandler] ROOM_UPDATE emitted", { + logEvent("RoomUseCase", { + event: "ROOM_UPDATE", + result: "emitted", roomId: room.roomId, + socketId, ownerId: room.ownerId, totalPlayers: room.players.length, }); diff --git a/apps/server/src/network/adapters/socketEmitters.ts b/apps/server/src/network/adapters/socketEmitters.ts new file mode 100644 index 0000000..32439b9 --- /dev/null +++ b/apps/server/src/network/adapters/socketEmitters.ts @@ -0,0 +1,34 @@ +import { Server, Socket } from "socket.io"; + +type EmitPayload = unknown; + +const emitWithOptionalPayload = ( + emit: (event: string, payload?: EmitPayload) => void, + event: string, + payload?: EmitPayload +) => { + if (payload === undefined) { + emit(event); + return; + } + + emit(event, payload); +}; + +export const createEmitToRoom = (io: Server) => { + return (roomId: string, event: string, payload?: EmitPayload) => { + emitWithOptionalPayload((eventName, body) => io.to(roomId).emit(eventName, body), event, payload); + }; +}; + +export const createEmitToSocket = (socket: Socket) => { + return (event: string, payload?: EmitPayload) => { + emitWithOptionalPayload((eventName, body) => socket.emit(eventName, body), event, payload); + }; +}; + +export const createEmitToAll = (io: Server) => { + return (event: string, payload?: EmitPayload) => { + emitWithOptionalPayload((eventName, body) => io.emit(eventName, body), event, payload); + }; +}; diff --git a/apps/server/src/network/logging/logEvent.ts b/apps/server/src/network/logging/logEvent.ts new file mode 100644 index 0000000..626324c --- /dev/null +++ b/apps/server/src/network/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); +};