import { config } from "@repo/shared";
import { GameLoop, type TickData } from "../../GameLoop";
import { Player } from "../../entities/Player.js";
import { MapStore } from "../../states/MapStore";
import { logEvent } from "@server/logging/logEvent";
export class GameSessionService {
private mapStores: Map<string, MapStore>;
private gameLoops: Map<string, GameLoop>;
private roomStartTimes: Map<string, number>;
constructor(private players: Map<string, Player>) {
this.mapStores = new Map();
this.gameLoops = new Map();
this.roomStartTimes = new Map();
}
public getRoomStartTime(roomId: string): number | undefined {
return this.roomStartTimes.get(roomId);
}
public startGameLoop(
roomId: string,
playerIds: string[],
onTick: (data: TickData) => void,
onGameEnd: () => void
) {
if (this.gameLoops.has(roomId)) {
logEvent("GameSessionService", {
event: "START_GAME_LOOP",
result: "ignored_already_running",
roomId,
});
return;
}
const tickRate = config.GAME_CONFIG.PLAYER_POSITION_UPDATE_MS;
this.roomStartTimes.set(roomId, Date.now());
const mapStore = this.mapStores.get(roomId) ?? new MapStore();
this.mapStores.set(roomId, mapStore);
const loop = new GameLoop(
roomId,
tickRate,
playerIds,
this.players,
mapStore,
onTick,
() => {
this.roomStartTimes.delete(roomId);
this.gameLoops.delete(roomId);
this.mapStores.delete(roomId);
onGameEnd();
}
);
loop.start();
this.gameLoops.set(roomId, loop);
logEvent("GameSessionService", {
event: "START_GAME_LOOP",
result: "started",
roomId,
playerCount: playerIds.length,
});
}
public stopGameLoop(roomId: string) {
const loop = this.gameLoops.get(roomId);
if (loop) {
loop.stop();
this.gameLoops.delete(roomId);
this.roomStartTimes.delete(roomId);
this.mapStores.delete(roomId);
logEvent("GameSessionService", {
event: "STOP_GAME_LOOP",
result: "stopped",
roomId,
});
} else {
logEvent("GameSessionService", {
event: "STOP_GAME_LOOP",
result: "ignored_not_running",
roomId,
});
}
}
}