shuffle players implementado correctamente
This commit is contained in:
@@ -6,6 +6,26 @@ import { broadcastDashboardUpdate } from "../adminApi";
|
||||
|
||||
export class GameRoom extends Room<GameState> {
|
||||
maxClients = 2;
|
||||
|
||||
getAvailableData() {
|
||||
// If waiting for shuffled players, report as available regardless of current client count
|
||||
if (this.isWaitingForShuffledPlayers) {
|
||||
return {
|
||||
clients: 0,
|
||||
maxClients: this.maxClients,
|
||||
metadata: this.metadata
|
||||
};
|
||||
}
|
||||
return super.getAvailableData();
|
||||
}
|
||||
|
||||
hasReachedMaxClients() {
|
||||
// If waiting for shuffled players, allow up to 2 new clients regardless of current count
|
||||
if (this.isWaitingForShuffledPlayers) {
|
||||
return false;
|
||||
}
|
||||
return super.hasReachedMaxClients();
|
||||
}
|
||||
private gameInterval?: NodeJS.Timeout;
|
||||
private recentSystemMessage: { text: string; kind: string; timestamp: number } | null = null;
|
||||
|
||||
@@ -242,7 +262,7 @@ export class GameRoom extends Room<GameState> {
|
||||
}
|
||||
|
||||
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}, isShuffleJoin: ${options.isShuffleJoin}, isWaitingForShuffledPlayers: ${this.isWaitingForShuffledPlayers}, playersCount: ${this.state.players.size}`);
|
||||
const uuid = options?.uuid as string | undefined;
|
||||
|
||||
// UUID-based reconnection: if game already started or room is full, allow join if UUID matches a participant
|
||||
@@ -283,12 +303,13 @@ export class GameRoom extends Room<GameState> {
|
||||
}
|
||||
|
||||
// Special handling for shuffled players
|
||||
if (this.isWaitingForShuffledPlayers && options.uuid) {
|
||||
if ((this.isWaitingForShuffledPlayers || options.isShuffleJoin) && options.uuid) {
|
||||
return this.handleShuffledPlayerJoin(client, options);
|
||||
}
|
||||
|
||||
// Prevent new joins if game already started or two players are registered
|
||||
if (this.state.gameStatus !== GameStatus.WAITING || this.state.players.size >= 2) {
|
||||
// BUT allow if waiting for shuffled players (they should go through shuffle handler above)
|
||||
if ((this.state.gameStatus !== GameStatus.WAITING || this.state.players.size >= 2) && !this.isWaitingForShuffledPlayers) {
|
||||
try { client.leave(1000); } catch {}
|
||||
return;
|
||||
}
|
||||
@@ -685,10 +706,18 @@ export class GameRoom extends Room<GameState> {
|
||||
}
|
||||
});
|
||||
|
||||
// Clear all players from state completely
|
||||
this.state.players.clear();
|
||||
this.state.p1Id = "";
|
||||
this.state.p2Id = "";
|
||||
this.sessionToUuid.clear();
|
||||
|
||||
// Reset room state but keep variant
|
||||
const currentVariant = this.state.currentVariant;
|
||||
this.state.restartGame();
|
||||
this.state.currentVariant = currentVariant;
|
||||
// Ensure room is accepting new joins after shuffle
|
||||
try { (this as any).unlock?.(); } catch {}
|
||||
|
||||
// Prepare for new players
|
||||
this.isWaitingForShuffledPlayers = true;
|
||||
@@ -704,42 +733,75 @@ export class GameRoom extends Room<GameState> {
|
||||
this.expectedShuffledPlayers = assignments;
|
||||
this.isWaitingForShuffledPlayers = true;
|
||||
|
||||
// Update metadata
|
||||
// Update metadata to reflect that room is waiting for shuffled players
|
||||
this.setMetadata({
|
||||
gameStatus: 'waiting',
|
||||
currentRound: 1,
|
||||
currentVariant: this.state.currentVariant
|
||||
currentVariant: this.state.currentVariant,
|
||||
playersCount: 0, // Force reset player count
|
||||
maxClients: 2
|
||||
});
|
||||
|
||||
// Make sure the room is unlocked and can accept new connections
|
||||
try {
|
||||
(this as any).unlock?.();
|
||||
// Force Colyseus to recalculate available slots
|
||||
(this as any).maxClients = 2;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
private handleShuffledPlayerJoin(client: Client, options: any) {
|
||||
const uuid = options.uuid;
|
||||
console.log(`[GameRoom] Shuffled player ${uuid} trying to join room ${this.roomId}`);
|
||||
console.log(`[GameRoom] Shuffled player ${uuid} trying to join room ${this.roomId} with options:`, options);
|
||||
console.log(`[GameRoom] Room state - isWaitingForShuffledPlayers: ${this.isWaitingForShuffledPlayers}, playersCount: ${this.state.players.size}, expectedPlayers:`, this.expectedShuffledPlayers);
|
||||
|
||||
// Check if this player is expected in this room
|
||||
let expectedRole: 'P1' | 'P2' | null = null;
|
||||
let expectedRole: 'P1' | 'P2' | null = options.role || null;
|
||||
|
||||
if (this.expectedShuffledPlayers.p1?.uuid === uuid) {
|
||||
expectedRole = 'P1';
|
||||
} else if (this.expectedShuffledPlayers.p2?.uuid === uuid) {
|
||||
expectedRole = 'P2';
|
||||
// If role not provided, determine from expected players
|
||||
if (!expectedRole) {
|
||||
if (this.expectedShuffledPlayers.p1?.uuid === uuid) {
|
||||
expectedRole = 'P1';
|
||||
} else if (this.expectedShuffledPlayers.p2?.uuid === uuid) {
|
||||
expectedRole = 'P2';
|
||||
}
|
||||
}
|
||||
|
||||
if (!expectedRole) {
|
||||
// Fallback: consult NameManager assignment if not set yet in room
|
||||
try {
|
||||
const { NameManager } = require("../utils/nameManager");
|
||||
const assign = NameManager.getInstance().getPlayerRoomAssignment(uuid);
|
||||
if (assign && assign.roomId === this.roomId) {
|
||||
expectedRole = assign.role;
|
||||
if (assign.role === 'P1' && !this.expectedShuffledPlayers.p1) {
|
||||
this.expectedShuffledPlayers.p1 = { uuid, name: options.playerName || 'player', color: options.playerColor };
|
||||
} else if (assign.role === 'P2' && !this.expectedShuffledPlayers.p2) {
|
||||
this.expectedShuffledPlayers.p2 = { uuid, name: options.playerName || 'player', color: options.playerColor };
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
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
|
||||
// Get player info from expected data or use provided options as fallback
|
||||
const expectedPlayerData = expectedRole === 'P1' ? this.expectedShuffledPlayers.p1 : this.expectedShuffledPlayers.p2;
|
||||
const playerName = expectedPlayerData?.name || options.playerName || 'player';
|
||||
const playerColor = expectedPlayerData?.color || options.playerColor || "#667eea";
|
||||
|
||||
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);
|
||||
const player = this.state.addPlayer(client.sessionId, playerName);
|
||||
player.role = expectedRole;
|
||||
player.color = expectedPlayerData.color || "#667eea";
|
||||
player.color = playerColor;
|
||||
(player as any).uuid = uuid;
|
||||
this.sessionToUuid.set(client.sessionId, uuid);
|
||||
|
||||
// Set role IDs
|
||||
if (expectedRole === 'P1') {
|
||||
@@ -750,12 +812,16 @@ export class GameRoom extends Room<GameState> {
|
||||
|
||||
client.send("playerInfo", {
|
||||
sessionId: client.sessionId,
|
||||
name: expectedPlayerData.name,
|
||||
name: playerName,
|
||||
roomId: this.roomId
|
||||
});
|
||||
|
||||
// Remove from NameManager assignment once joined
|
||||
NameManager.getInstance().removePlayerRoomAssignment(uuid);
|
||||
// Update mappings in NameManager
|
||||
try {
|
||||
const { NameManager } = require("../utils/nameManager");
|
||||
NameManager.getInstance().setCurrentRoom(uuid, this.roomId);
|
||||
NameManager.getInstance().removePlayerRoomAssignment(uuid);
|
||||
} catch {}
|
||||
|
||||
// Check if room is complete
|
||||
if (this.state.players.size === 2) {
|
||||
|
||||
@@ -44,6 +44,52 @@ export class LobbyRoom extends Room<LobbyState> {
|
||||
this.handleJoinRoom(client, roomId);
|
||||
});
|
||||
|
||||
// Client asks server to suggest a resume target (after listeners are ready)
|
||||
this.onMessage("resumeMe", async (client) => {
|
||||
const uuid = this.sessionToUuid.get(client.sessionId);
|
||||
if (!uuid) return;
|
||||
|
||||
// If shuffle in progress and an assignment exists, prefer it
|
||||
if (NameManager.getInstance().isShuffleInProgress()) {
|
||||
const assignment = NameManager.getInstance().getPlayerRoomAssignment(uuid);
|
||||
if (assignment) {
|
||||
try {
|
||||
const delay = assignment.role === 'P1' ? 150 : 750; // stagger joins to avoid full race
|
||||
const playerName = NameManager.getInstance().getPlayerName(uuid) || "";
|
||||
const playerColor = NameManager.getInstance().getPlayerColor(uuid) || "#667eea";
|
||||
|
||||
setTimeout(() => {
|
||||
try {
|
||||
client.send("shuffleRedirect", {
|
||||
roomId: assignment.roomId,
|
||||
role: assignment.role,
|
||||
playerName,
|
||||
playerColor,
|
||||
isShuffleJoin: true
|
||||
});
|
||||
} catch {}
|
||||
}, delay);
|
||||
} catch {}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, try current room mapping
|
||||
try {
|
||||
const currentRoomId = NameManager.getInstance().getCurrentRoom(uuid);
|
||||
if (currentRoomId) {
|
||||
const rooms = await matchMaker.query({ roomId: currentRoomId });
|
||||
const room = rooms[0];
|
||||
const status = room?.metadata?.gameStatus || "waiting";
|
||||
if (room && status !== "finished") {
|
||||
const token = NameManager.getInstance().getReconnectToken(uuid);
|
||||
if (token) { client.send("resumeReconnection", { token }); }
|
||||
else { client.send("resumeGame", { roomId: currentRoomId }); }
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
});
|
||||
|
||||
this.updateInterval = setInterval(() => {
|
||||
this.updateAvailableRooms();
|
||||
}, 2000);
|
||||
@@ -88,12 +134,8 @@ export class LobbyRoom extends Room<LobbyState> {
|
||||
name: existingName || "",
|
||||
color: this.state.players.get(client.sessionId)?.color || "#667eea"
|
||||
});
|
||||
|
||||
// Then immediately redirect to assigned room
|
||||
setTimeout(() => {
|
||||
this.handleJoinRoom(client, assignment.roomId);
|
||||
}, 500);
|
||||
|
||||
// Do not push immediate redirect here; client will send "resumeMe" after handlers are ready
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -237,7 +279,7 @@ export class LobbyRoom extends Room<LobbyState> {
|
||||
}
|
||||
}
|
||||
|
||||
private async handleJoinRoom(client: Client, roomId: string) {
|
||||
private async handleJoinRoom(client: Client, roomId: string, opts?: { force?: boolean }) {
|
||||
const player = this.state.players.get(client.sessionId);
|
||||
if (!player || player.inGame) return;
|
||||
if (!player.name || !player.name.trim()) {
|
||||
@@ -246,12 +288,13 @@ export class LobbyRoom extends Room<LobbyState> {
|
||||
}
|
||||
|
||||
try {
|
||||
// Verify the room exists and is available
|
||||
const rooms = await matchMaker.query({ roomId });
|
||||
|
||||
const status = rooms[0]?.metadata?.gameStatus || "waiting";
|
||||
if (rooms.length === 0 || rooms[0].clients >= 2 || status !== "waiting") {
|
||||
throw new Error("Room not available");
|
||||
if (!opts?.force) {
|
||||
// Verify the room exists and is available
|
||||
const rooms = await matchMaker.query({ roomId });
|
||||
const status = rooms[0]?.metadata?.gameStatus || "waiting";
|
||||
if (rooms.length === 0 || rooms[0].clients >= 2 || status !== "waiting") {
|
||||
throw new Error("Room not available");
|
||||
}
|
||||
}
|
||||
|
||||
this.state.setPlayerInGame(client.sessionId, true);
|
||||
|
||||
Reference in New Issue
Block a user