diff --git a/apps/server/src/handlers.ts b/apps/server/src/handlers.ts index 8aa2cd4..8ab1faf 100644 --- a/apps/server/src/handlers.ts +++ b/apps/server/src/handlers.ts @@ -324,6 +324,22 @@ export function registerRoomHandlers( broadcastState(room) }) + socket.on("room:leave", () => { + const code = socket.data.roomCode + const playerId = socket.data.playerId + if (!code || !playerId) { + return + } + socket.leave(code) + socket.data.roomCode = undefined + socket.data.playerId = undefined + const room = rooms.leave(code, playerId) + if (room) { + io.to(room.code).emit("player:left", { playerId }) + broadcastState(room) + } + }) + socket.on("disconnect", () => { const affected = rooms.handleDisconnect(socket.id) if (!affected) { diff --git a/apps/server/src/rooms.ts b/apps/server/src/rooms.ts index 1aa79f3..d32dd67 100644 --- a/apps/server/src/rooms.ts +++ b/apps/server/src/rooms.ts @@ -94,6 +94,28 @@ export class RoomManager { return this.rooms.get(code) } + /** + * Retire un joueur d'une room (départ volontaire). Réassigne l'hôte si besoin, + * supprime la room si plus personne. Renvoie la room (ou null si supprimée). + */ + leave(code: string, playerId: string): ServerRoom | null { + const room = this.rooms.get(code) + if (!room) { + return null + } + room.players.delete(playerId) + room.scores.delete(playerId) + if (room.players.size === 0) { + this.rooms.delete(code) + return null + } + if (room.hostId === playerId) { + const named = [...room.players.values()].find((p) => p.name !== "") + room.hostId = (named ?? [...room.players.values()][0]).id + } + return room + } + /** * Marque le joueur d'un socket comme déconnecté. * Retourne la room affectée et le playerId, ou null si non rattaché. diff --git a/apps/web/src/components/game-end-view.tsx b/apps/web/src/components/game-end-view.tsx index 5e5bd39..ce64d4d 100644 --- a/apps/web/src/components/game-end-view.tsx +++ b/apps/web/src/components/game-end-view.tsx @@ -133,7 +133,7 @@ export function GameEndView({ snapshot }: { snapshot: RoomSnapshot }) { const finalScores = useRoomStore((s) => s.finalScores) const gameTracks = useRoomStore((s) => s.gameTracks) const gameRecap = useRoomStore((s) => s.gameRecap) - const reset = useRoomStore((s) => s.reset) + const leaveRoom = useRoomStore((s) => s.leaveRoom) const returnToLobby = useRoomStore((s) => s.returnToLobby) const isHost = snapshot.hostId === playerId @@ -284,7 +284,7 @@ export function GameEndView({ snapshot }: { snapshot: RoomSnapshot }) {
)} -