Actualizar sistema de admin y mejoras en lobby
This commit is contained in:
@@ -82,6 +82,13 @@
|
|||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<h3>Player Management</h3>
|
<h3>Player Management</h3>
|
||||||
<div class="control-buttons">
|
<div class="control-buttons">
|
||||||
|
<button
|
||||||
|
@click="shufflePlayers"
|
||||||
|
class="btn btn-shuffle"
|
||||||
|
:disabled="isLoadingGlobal"
|
||||||
|
>
|
||||||
|
🎲 Shuffle Players
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
@click="sendAllToLobby"
|
@click="sendAllToLobby"
|
||||||
class="btn btn-lobby-all"
|
class="btn btn-lobby-all"
|
||||||
@@ -386,6 +393,30 @@ async function changeGlobalVariant() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function shufflePlayers() {
|
||||||
|
if (!confirm('Are you sure you want to SHUFFLE all players? This will randomly redistribute players between rooms and assign new roles!')) return;
|
||||||
|
|
||||||
|
isLoadingGlobal.value = true;
|
||||||
|
try {
|
||||||
|
const response = await fetch(`${import.meta.env.VITE_API_URL || 'http://localhost:3000/api'}/admin/shuffle-players`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' }
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) throw new Error('Failed to shuffle players');
|
||||||
|
|
||||||
|
const result = await response.json();
|
||||||
|
console.log('Players shuffled successfully:', result.message);
|
||||||
|
alert(`Shuffle completed! ${result.message}`);
|
||||||
|
await fetchData();
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to shuffle players:', error);
|
||||||
|
alert('Failed to shuffle players. Check console for details.');
|
||||||
|
} finally {
|
||||||
|
isLoadingGlobal.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function sendAllToLobby() {
|
async function sendAllToLobby() {
|
||||||
if (!confirm('Are you sure you want to send ALL players back to the lobby? This will end all active games!')) return;
|
if (!confirm('Are you sure you want to send ALL players back to the lobby? This will end all active games!')) return;
|
||||||
|
|
||||||
@@ -683,6 +714,11 @@ const selectedRoom = computed(() => {
|
|||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-shuffle {
|
||||||
|
background: linear-gradient(135deg, #ff6b35 0%, #f7931e 100%);
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
.btn-lobby-all {
|
.btn-lobby-all {
|
||||||
background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
|
background: linear-gradient(135deg, #2196f3 0%, #1976d2 100%);
|
||||||
color: white;
|
color: white;
|
||||||
|
|||||||
@@ -211,6 +211,23 @@ onMounted(() => {
|
|||||||
// Handle room closure/disconnection
|
// Handle room closure/disconnection
|
||||||
room.onLeave((code) => {
|
room.onLeave((code) => {
|
||||||
console.log('[DemoGame] Room disconnected with code:', code);
|
console.log('[DemoGame] Room disconnected with code:', code);
|
||||||
|
|
||||||
|
// Handle shuffle disconnection specially
|
||||||
|
if (code === 1002) {
|
||||||
|
console.log('[DemoGame] Disconnected for player shuffle - will redirect to lobby');
|
||||||
|
try {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.localStorage.removeItem('snatch.game.roomId');
|
||||||
|
window.localStorage.removeItem('snatch.game.sessionId');
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
// Redirect to lobby and let it handle the shuffle redirect
|
||||||
|
router.push('/');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal disconnection handling
|
||||||
// Always clean up local storage when room closes
|
// Always clean up local storage when room closes
|
||||||
try {
|
try {
|
||||||
if (typeof window !== 'undefined') {
|
if (typeof window !== 'undefined') {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Request, Response, Router } from "express";
|
import { Request, Response, Router } from "express";
|
||||||
import { matchMaker } from "colyseus";
|
import { matchMaker } from "colyseus";
|
||||||
import { GameRoom } from "./rooms/GameRoom";
|
import { GameRoom } from "./rooms/GameRoom";
|
||||||
|
import { NameManager } from "./utils/nameManager";
|
||||||
|
|
||||||
// SSE connections storage
|
// SSE connections storage
|
||||||
const sseClients = new Set<Response>();
|
const sseClients = new Set<Response>();
|
||||||
@@ -292,6 +293,145 @@ adminRouter.post("/admin/send-all-to-lobby", async (req: Request, res: Response)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
adminRouter.post("/admin/shuffle-players", async (req: Request, res: Response) => {
|
||||||
|
try {
|
||||||
|
console.log("[AdminAPI] Starting player shuffle...");
|
||||||
|
|
||||||
|
// 1. Get all game rooms and their players
|
||||||
|
const gameRooms = await matchMaker.query({ name: "game" });
|
||||||
|
|
||||||
|
if (gameRooms.length === 0) {
|
||||||
|
return res.json({ success: true, message: "No game rooms to shuffle" });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[AdminAPI] Found ${gameRooms.length} game rooms for shuffle`);
|
||||||
|
|
||||||
|
// 2. Extract all players from all rooms
|
||||||
|
const allPlayers: any[] = [];
|
||||||
|
const roomsInfo: { roomId: string; variant: string }[] = [];
|
||||||
|
|
||||||
|
for (const room of gameRooms) {
|
||||||
|
try {
|
||||||
|
const roomState = await matchMaker.remoteRoomCall(room.roomId, "getState");
|
||||||
|
|
||||||
|
roomsInfo.push({
|
||||||
|
roomId: room.roomId,
|
||||||
|
variant: roomState.variant || 'G1'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Collect players with their full info
|
||||||
|
if (roomState.players && roomState.players.length > 0) {
|
||||||
|
roomState.players.forEach((player: any) => {
|
||||||
|
allPlayers.push({
|
||||||
|
uuid: player.uuid || player.sessionId, // Use actual UUID if available
|
||||||
|
name: player.name,
|
||||||
|
color: player.color,
|
||||||
|
sessionId: player.sessionId
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to get state for room ${room.roomId}:`, error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[AdminAPI] Collected ${allPlayers.length} players for shuffle`);
|
||||||
|
|
||||||
|
if (allPlayers.length === 0) {
|
||||||
|
return res.json({ success: true, message: "No players found to shuffle" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Shuffle players array
|
||||||
|
const shuffledPlayers = [...allPlayers];
|
||||||
|
for (let i = shuffledPlayers.length - 1; i > 0; i--) {
|
||||||
|
const j = Math.floor(Math.random() * (i + 1));
|
||||||
|
[shuffledPlayers[i], shuffledPlayers[j]] = [shuffledPlayers[j], shuffledPlayers[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Create groups of 2 players
|
||||||
|
const playerGroups: any[][] = [];
|
||||||
|
const extraPlayers: any[] = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < shuffledPlayers.length; i += 2) {
|
||||||
|
if (i + 1 < shuffledPlayers.length) {
|
||||||
|
playerGroups.push([shuffledPlayers[i], shuffledPlayers[i + 1]]);
|
||||||
|
} else {
|
||||||
|
extraPlayers.push(shuffledPlayers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[AdminAPI] Created ${playerGroups.length} player groups, ${extraPlayers.length} extra players`);
|
||||||
|
|
||||||
|
// 5. Start shuffle process
|
||||||
|
NameManager.getInstance().startShuffle();
|
||||||
|
|
||||||
|
// 6. Assign players to rooms and roles randomly
|
||||||
|
const assignments: { [roomId: string]: { p1: any; p2: any } } = {};
|
||||||
|
|
||||||
|
for (let i = 0; i < playerGroups.length && i < roomsInfo.length; i++) {
|
||||||
|
const group = playerGroups[i];
|
||||||
|
const roomInfo = roomsInfo[i];
|
||||||
|
|
||||||
|
// Randomly assign P1 and P2 roles
|
||||||
|
const [player1, player2] = Math.random() < 0.5 ? [group[0], group[1]] : [group[1], group[0]];
|
||||||
|
|
||||||
|
assignments[roomInfo.roomId] = {
|
||||||
|
p1: { ...player1, role: 'P1' },
|
||||||
|
p2: { ...player2, role: 'P2' }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Store assignments in NameManager for lobby redirects
|
||||||
|
NameManager.getInstance().assignPlayerToRoom(player1.uuid, roomInfo.roomId, 'P1');
|
||||||
|
NameManager.getInstance().assignPlayerToRoom(player2.uuid, roomInfo.roomId, 'P2');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. Clear all rooms first
|
||||||
|
console.log("[AdminAPI] Clearing all game rooms for shuffle...");
|
||||||
|
const clearPromises = gameRooms.map(room =>
|
||||||
|
matchMaker.remoteRoomCall(room.roomId, "executeAdminCommand", ["clearForShuffle"])
|
||||||
|
.catch(error => console.error(`Failed to clear room ${room.roomId}:`, error))
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.allSettled(clearPromises);
|
||||||
|
|
||||||
|
// 8. Wait a bit for rooms to clear, then assign new players
|
||||||
|
setTimeout(async () => {
|
||||||
|
console.log("[AdminAPI] Assigning shuffled players to rooms...");
|
||||||
|
|
||||||
|
const assignPromises = Object.entries(assignments).map(([roomId, assignment]) =>
|
||||||
|
matchMaker.remoteRoomCall(roomId, "executeAdminCommand", ["assignShuffledPlayers", assignment])
|
||||||
|
.catch(error => console.error(`Failed to assign players to room ${roomId}:`, error))
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.allSettled(assignPromises);
|
||||||
|
|
||||||
|
// Handle extra players - they go to lobby
|
||||||
|
extraPlayers.forEach(player => {
|
||||||
|
console.log(`[AdminAPI] Player ${player.name} will remain in lobby (odd number of players)`);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("[AdminAPI] Player shuffle completed!");
|
||||||
|
|
||||||
|
// Cleanup after a delay
|
||||||
|
setTimeout(() => {
|
||||||
|
NameManager.getInstance().endShuffle();
|
||||||
|
broadcastDashboardUpdate();
|
||||||
|
}, 10000); // 10 seconds for all players to reconnect
|
||||||
|
|
||||||
|
}, 3000); // 3 seconds delay
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
message: `Shuffle initiated for ${allPlayers.length} players across ${gameRooms.length} rooms. ${playerGroups.length} pairs created, ${extraPlayers.length} players will go to lobby.`
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[AdminAPI] Error shuffling players:", error);
|
||||||
|
NameManager.getInstance().endShuffle(); // Cleanup on error
|
||||||
|
res.status(500).json({ error: "Failed to shuffle players" });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// SSE endpoint for real-time dashboard updates
|
// SSE endpoint for real-time dashboard updates
|
||||||
adminRouter.get("/dashboard-stream", (req: Request, res: Response) => {
|
adminRouter.get("/dashboard-stream", (req: Request, res: Response) => {
|
||||||
// Set SSE headers
|
// Set SSE headers
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ export class GameRoom extends Room<GameState> {
|
|||||||
maxClients = 2;
|
maxClients = 2;
|
||||||
private gameInterval?: NodeJS.Timeout;
|
private gameInterval?: NodeJS.Timeout;
|
||||||
private recentSystemMessage: { text: string; kind: string; timestamp: number } | null = null;
|
private recentSystemMessage: { text: string; kind: string; timestamp: number } | null = null;
|
||||||
|
|
||||||
|
// For shuffle functionality
|
||||||
|
private expectedShuffledPlayers: { p1?: any; p2?: any } = {};
|
||||||
|
private isWaitingForShuffledPlayers: boolean = false;
|
||||||
|
private sessionToUuid: Map<string, string> = new Map();
|
||||||
|
|
||||||
private sysChat(text: string, kind: string) {
|
private sysChat(text: string, kind: string) {
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
@@ -228,12 +233,23 @@ export class GameRoom extends Room<GameState> {
|
|||||||
|
|
||||||
onJoin(client: Client, options: any) {
|
onJoin(client: Client, options: any) {
|
||||||
console.log(`[GameRoom] ${client.sessionId} joined room ${this.roomId} with name: ${options.playerName}`);
|
console.log(`[GameRoom] ${client.sessionId} joined room ${this.roomId} with name: ${options.playerName}`);
|
||||||
|
|
||||||
|
// Special handling for shuffled players
|
||||||
|
if (this.isWaitingForShuffledPlayers && options.uuid) {
|
||||||
|
return this.handleShuffledPlayerJoin(client, options);
|
||||||
|
}
|
||||||
|
|
||||||
// Prevent new joins if game already started or two players are registered
|
// Prevent new joins if game already started or two players are registered
|
||||||
if (this.state.gameStatus !== GameStatus.WAITING || this.state.players.size >= 2) {
|
if (this.state.gameStatus !== GameStatus.WAITING || this.state.players.size >= 2) {
|
||||||
try { client.leave(1000); } catch {}
|
try { client.leave(1000); } catch {}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Store UUID mapping if provided
|
||||||
|
if (options.uuid) {
|
||||||
|
this.sessionToUuid.set(client.sessionId, options.uuid);
|
||||||
|
}
|
||||||
|
|
||||||
// Use the playerName passed from the lobby - don't generate a new one!
|
// Use the playerName passed from the lobby - don't generate a new one!
|
||||||
const playerName = options.playerName || "player";
|
const playerName = options.playerName || "player";
|
||||||
const playerColor = (options.playerColor && typeof options.playerColor === 'string') ? options.playerColor : "#667eea";
|
const playerColor = (options.playerColor && typeof options.playerColor === 'string') ? options.playerColor : "#667eea";
|
||||||
@@ -568,11 +584,124 @@ export class GameRoom extends Room<GameState> {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'clearForShuffle':
|
||||||
|
this.handleClearForShuffle();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'assignShuffledPlayers':
|
||||||
|
const playerAssignments = args[0];
|
||||||
|
this.handleAssignShuffledPlayers(playerAssignments);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
console.warn(`[GameRoom] Unknown admin command: ${command}`);
|
console.warn(`[GameRoom] Unknown admin command: ${command}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleClearForShuffle() {
|
||||||
|
console.log(`[GameRoom] Clearing room ${this.roomId} for shuffle`);
|
||||||
|
|
||||||
|
this.sysChat('🎲 Admin está reorganizando jugadores...', 'admin_shuffle');
|
||||||
|
|
||||||
|
// Give players a moment to see the message
|
||||||
|
setTimeout(() => {
|
||||||
|
// Disconnect all clients with special code for shuffle
|
||||||
|
this.clients.forEach(client => {
|
||||||
|
try {
|
||||||
|
client.leave(1002); // Special code for shuffle
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to disconnect client ${client.sessionId}:`, error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Reset room state but keep variant
|
||||||
|
const currentVariant = this.state.currentVariant;
|
||||||
|
this.state.restartGame();
|
||||||
|
this.state.currentVariant = currentVariant;
|
||||||
|
|
||||||
|
// Prepare for new players
|
||||||
|
this.isWaitingForShuffledPlayers = true;
|
||||||
|
this.expectedShuffledPlayers = {};
|
||||||
|
|
||||||
|
broadcastDashboardUpdate();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleAssignShuffledPlayers(assignments: { p1?: any; p2?: any }) {
|
||||||
|
console.log(`[GameRoom] Assigning shuffled players to room ${this.roomId}:`, assignments);
|
||||||
|
|
||||||
|
this.expectedShuffledPlayers = assignments;
|
||||||
|
this.isWaitingForShuffledPlayers = true;
|
||||||
|
|
||||||
|
// Update metadata
|
||||||
|
this.setMetadata({
|
||||||
|
gameStatus: 'waiting',
|
||||||
|
currentRound: 1,
|
||||||
|
currentVariant: this.state.currentVariant
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleShuffledPlayerJoin(client: Client, options: any) {
|
||||||
|
const uuid = options.uuid;
|
||||||
|
console.log(`[GameRoom] Shuffled player ${uuid} trying to join room ${this.roomId}`);
|
||||||
|
|
||||||
|
// Check if this player is expected in this room
|
||||||
|
let expectedRole: 'P1' | 'P2' | null = null;
|
||||||
|
|
||||||
|
if (this.expectedShuffledPlayers.p1?.uuid === uuid) {
|
||||||
|
expectedRole = 'P1';
|
||||||
|
} else if (this.expectedShuffledPlayers.p2?.uuid === uuid) {
|
||||||
|
expectedRole = 'P2';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!expectedRole) {
|
||||||
|
console.log(`[GameRoom] Player ${uuid} not expected in room ${this.roomId}, rejecting`);
|
||||||
|
try { client.leave(1000); } catch {}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get player info from expected data
|
||||||
|
const expectedPlayerData = expectedRole === 'P1' ? this.expectedShuffledPlayers.p1 : this.expectedShuffledPlayers.p2;
|
||||||
|
|
||||||
|
console.log(`[GameRoom] Adding shuffled player ${uuid} as ${expectedRole} in room ${this.roomId}`);
|
||||||
|
|
||||||
|
// Add player with the expected role
|
||||||
|
const player = this.state.addPlayer(client.sessionId, expectedPlayerData.name);
|
||||||
|
player.role = expectedRole;
|
||||||
|
player.color = expectedPlayerData.color || "#667eea";
|
||||||
|
|
||||||
|
// Set role IDs
|
||||||
|
if (expectedRole === 'P1') {
|
||||||
|
this.state.p1Id = client.sessionId;
|
||||||
|
} else {
|
||||||
|
this.state.p2Id = client.sessionId;
|
||||||
|
}
|
||||||
|
|
||||||
|
client.send("playerInfo", {
|
||||||
|
sessionId: client.sessionId,
|
||||||
|
name: expectedPlayerData.name,
|
||||||
|
roomId: this.roomId
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove from NameManager assignment once joined
|
||||||
|
NameManager.getInstance().removePlayerRoomAssignment(uuid);
|
||||||
|
|
||||||
|
// Check if room is complete
|
||||||
|
if (this.state.players.size === 2) {
|
||||||
|
this.isWaitingForShuffledPlayers = false;
|
||||||
|
this.expectedShuffledPlayers = {};
|
||||||
|
this.sysChat(`🎲 Reorganización completa - ¡comenzando partida!`, 'shuffle_complete');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
this.startGame();
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
this.sysChat(`🎲 Esperando más jugadores reorganizados...`, 'shuffle_waiting');
|
||||||
|
}
|
||||||
|
|
||||||
|
broadcastDashboardUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
private getConnectedPlayersCount(): number {
|
private getConnectedPlayersCount(): number {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
this.state.players.forEach(player => {
|
this.state.players.forEach(player => {
|
||||||
@@ -586,6 +715,7 @@ export class GameRoom extends Room<GameState> {
|
|||||||
roomId: this.roomId,
|
roomId: this.roomId,
|
||||||
players: Array.from(this.state.players.values()).map(p => ({
|
players: Array.from(this.state.players.values()).map(p => ({
|
||||||
sessionId: p.sessionId,
|
sessionId: p.sessionId,
|
||||||
|
uuid: this.sessionToUuid.get(p.sessionId) || p.sessionId, // Include UUID for shuffle
|
||||||
name: p.name,
|
name: p.name,
|
||||||
role: p.role,
|
role: p.role,
|
||||||
pavoTokens: p.pavoTokens,
|
pavoTokens: p.pavoTokens,
|
||||||
|
|||||||
@@ -38,6 +38,33 @@ export class LobbyRoom extends Room<LobbyState> {
|
|||||||
if (options.uuid) {
|
if (options.uuid) {
|
||||||
this.sessionToUuid.set(client.sessionId, options.uuid);
|
this.sessionToUuid.set(client.sessionId, options.uuid);
|
||||||
|
|
||||||
|
// Check for shuffle redirect FIRST
|
||||||
|
if (NameManager.getInstance().isShuffleInProgress()) {
|
||||||
|
const assignment = NameManager.getInstance().getPlayerRoomAssignment(options.uuid);
|
||||||
|
if (assignment) {
|
||||||
|
console.log(`[LobbyRoom] Redirecting shuffled player ${options.uuid} to room ${assignment.roomId} as ${assignment.role}`);
|
||||||
|
|
||||||
|
// Add player temporarily to lobby state
|
||||||
|
const existingName = NameManager.getInstance().getPlayerName(options.uuid);
|
||||||
|
this.state.addPlayer(client.sessionId, existingName || "");
|
||||||
|
|
||||||
|
// Send welcome first
|
||||||
|
client.send("welcome", {
|
||||||
|
sessionId: client.sessionId,
|
||||||
|
name: existingName || "",
|
||||||
|
color: this.state.players.get(client.sessionId)?.color || "#667eea"
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then immediately redirect to assigned room
|
||||||
|
setTimeout(() => {
|
||||||
|
this.handleJoinRoom(client, assignment.roomId);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Normal lobby join flow
|
||||||
// Check if this UUID already has a name
|
// Check if this UUID already has a name
|
||||||
const existingName = NameManager.getInstance().getPlayerName(options.uuid);
|
const existingName = NameManager.getInstance().getPlayerName(options.uuid);
|
||||||
this.state.addPlayer(client.sessionId, existingName || "");
|
this.state.addPlayer(client.sessionId, existingName || "");
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
export class NameManager {
|
export class NameManager {
|
||||||
private static instance: NameManager;
|
private static instance: NameManager;
|
||||||
private uuidToName: Map<string, string> = new Map();
|
private uuidToName: Map<string, string> = new Map();
|
||||||
|
|
||||||
|
// For shuffle functionality
|
||||||
|
private roomAssignments: Map<string, { roomId: string; role: 'P1' | 'P2' }> = new Map();
|
||||||
|
private shuffleInProgress: boolean = false;
|
||||||
|
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
@@ -55,4 +59,35 @@ export class NameManager {
|
|||||||
getAllActivePlayers(): string[] {
|
getAllActivePlayers(): string[] {
|
||||||
return Array.from(this.uuidToName.values());
|
return Array.from(this.uuidToName.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shuffle functionality methods
|
||||||
|
startShuffle(): void {
|
||||||
|
this.shuffleInProgress = true;
|
||||||
|
this.roomAssignments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
endShuffle(): void {
|
||||||
|
this.shuffleInProgress = false;
|
||||||
|
this.roomAssignments.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
isShuffleInProgress(): boolean {
|
||||||
|
return this.shuffleInProgress;
|
||||||
|
}
|
||||||
|
|
||||||
|
assignPlayerToRoom(uuid: string, roomId: string, role: 'P1' | 'P2'): void {
|
||||||
|
this.roomAssignments.set(uuid, { roomId, role });
|
||||||
|
}
|
||||||
|
|
||||||
|
getPlayerRoomAssignment(uuid: string): { roomId: string; role: 'P1' | 'P2' } | undefined {
|
||||||
|
return this.roomAssignments.get(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
removePlayerRoomAssignment(uuid: string): void {
|
||||||
|
this.roomAssignments.delete(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
getAllRoomAssignments(): Map<string, { roomId: string; role: 'P1' | 'P2' }> {
|
||||||
|
return new Map(this.roomAssignments);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user