Newer
Older
PixelPaintWar / apps / server / src / domains / game / application / useCases / executeStartGameUseCase.ts
import { protocol, roomConsts } from "@repo/shared";
import { RoomManager } from "@server/domains/room/RoomManager";
import type { StartGamePort } from "../ports/gameUseCasePorts";

type EmitToRoom = (roomId: string, event: string, payload?: unknown) => void;

type ExecuteStartGameUseCaseParams = {
  ownerId: string;
  gameManager: StartGamePort;
  roomManager: RoomManager;
  emitToRoom: EmitToRoom;
};

export const executeStartGameUseCase = ({
  ownerId,
  gameManager,
  roomManager,
  emitToRoom,
}: ExecuteStartGameUseCaseParams) => {
  const room = roomManager.getRoomByOwnerId(ownerId);
  if (!room) {
    console.log("[GameHandler] START_GAME ignored (no room)", { socketId: ownerId });
    return;
  }

  if (room.status === roomConsts.RoomPhase.PLAYING) {
    console.log("[GameHandler] START_GAME ignored (already playing)", { roomId: room.roomId });
    return;
  }

  console.log("[GameHandler] START_GAME accepted", {
    roomId: room.roomId,
    ownerId,
    totalPlayers: room.players.length,
  });

  room.status = roomConsts.RoomPhase.PLAYING;

  const playerIds = room.players.map((p: { id: string }) => p.id);

  room.players.forEach((p: { id: string }) => {
    gameManager.addPlayer(p.id);
  });

  gameManager.startGameLoop(
    room.roomId,
    playerIds,
    (tickData) => {
      tickData.players.forEach((playerData) => {
        emitToRoom(room.roomId, protocol.SocketEvents.UPDATE_PLAYER, playerData);
      });

      if (tickData.cellUpdates.length > 0) {
        emitToRoom(room.roomId, protocol.SocketEvents.UPDATE_MAP_CELLS, tickData.cellUpdates);
      }
    },
    () => {
      console.log(`[GameHandler] ルーム ${room.roomId} のゲームが終了しました (3分経過)`);
      emitToRoom(room.roomId, protocol.SocketEvents.GAME_END);
      room.status = roomConsts.RoomPhase.WAITING;
    }
  );

  const startTime = gameManager.getRoomStartTime(room.roomId) || Date.now();
  emitToRoom(room.roomId, protocol.SocketEvents.GAME_START, { startTime });
};