reconexio

This commit is contained in:
2025-08-15 19:58:09 -06:00
parent 5e42eb7d54
commit 9b84008f19
4 changed files with 51 additions and 31 deletions

View File

@@ -115,8 +115,12 @@ onMounted(async () => {
const room = await colyseusService.joinLobby();
colorInput.value = colyseusService.playerColor.value || '#667eea';
let resumed = false;
const guardResume = () => { if (resumed) return true; resumed = true; return false; };
// Prefer reconnection token path to bypass locked rooms
room.onMessage("resumeReconnection", async (data: any) => {
if (guardResume()) return;
try {
await colyseusService.reconnectWithToken(data.token);
// Leave lobby before navigating
@@ -132,6 +136,7 @@ onMounted(async () => {
// Listen for server-initiated resume to existing game (fallback joinById)
room.onMessage("resumeGame", async (data: any) => {
if (guardResume()) return;
try {
const gameRoom = await colyseusService.joinGameRoom(data.roomId);
// Leave lobby before navigating

View File

@@ -368,12 +368,18 @@ adminRouter.post("/admin/shuffle-players", async (req: Request, res: Response) =
// 6. Assign players to rooms and roles randomly
const assignments: { [roomId: string]: { p1: any; p2: any } } = {};
// Shuffle rooms so pairs go to random rooms
const shuffledRooms = [...roomsInfo];
for (let i = shuffledRooms.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[shuffledRooms[i], shuffledRooms[j]] = [shuffledRooms[j], shuffledRooms[i]];
}
for (let i = 0; i < playerGroups.length && i < roomsInfo.length; i++) {
for (let i = 0; i < playerGroups.length && i < shuffledRooms.length; i++) {
const group = playerGroups[i];
const roomInfo = roomsInfo[i];
const roomInfo = shuffledRooms[i];
// Randomly assign P1 and P2 roles
// Randomize roles P1/P2
const [player1, player2] = Math.random() < 0.5 ? [group[0], group[1]] : [group[1], group[0]];
assignments[roomInfo.roomId] = {
@@ -393,6 +399,17 @@ adminRouter.post("/admin/shuffle-players", async (req: Request, res: Response) =
.catch(error => console.error(`Failed to clear room ${room.roomId}:`, error))
);
// Clear current-room and reconnection tokens for all players to avoid resume during shuffle
try {
allPlayers.forEach(p => {
const u = p.uuid;
if (u) {
NameManager.getInstance().clearCurrentRoom(u);
(NameManager.getInstance() as any).clearReconnectToken?.(u);
}
});
} catch {}
await Promise.allSettled(clearPromises);
// 8. Wait a bit for rooms to clear, then assign new players

View File

@@ -49,7 +49,7 @@ export class LobbyRoom extends Room<LobbyState> {
}, 2000);
}
onJoin(client: Client, options: any) {
async onJoin(client: Client, options: any) {
console.log(`[LobbyRoom] ${client.sessionId} joined lobby with UUID: ${options.uuid}`);
// Enforce UUID presence and allowlist (if configured)
if (!options.uuid || !isUuidAllowed(options.uuid)) {
@@ -62,32 +62,7 @@ export class LobbyRoom extends Room<LobbyState> {
if (options.uuid) {
this.sessionToUuid.set(client.sessionId, options.uuid);
// If this UUID has a current active game room assignment, redirect there
try {
const currentRoomId = NameManager.getInstance().getCurrentRoom(options.uuid);
if (currentRoomId) {
// Verify room exists and is not finished
matchMaker.query({ roomId: currentRoomId }).then((rooms) => {
const room = rooms[0];
const status = room?.metadata?.gameStatus || "waiting";
if (room && status !== "finished") {
const token = NameManager.getInstance().getReconnectToken(options.uuid);
if (token) {
// Prefer reconnection token to bypass room lock
client.send("resumeReconnection", { token });
} else {
// Fallback to joinById path
client.send("resumeGame", { roomId: currentRoomId });
}
// Mark as in game on lobby state to avoid duplicate quickPlay
const p = this.state.players.get(client.sessionId);
if (p) p.inGame = true;
return;
}
}).catch(() => {});
}
} catch {}
// (duplicate resume check removed; handled below with await)
// Check for shuffle redirect FIRST
if (NameManager.getInstance().isShuffleInProgress()) {
const assignment = NameManager.getInstance().getPlayerRoomAssignment(options.uuid);
@@ -123,6 +98,25 @@ export class LobbyRoom extends Room<LobbyState> {
}
}
// If not in shuffle, check if UUID has active current room to resume
try {
const currentRoomId = NameManager.getInstance().getCurrentRoom(options.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(options.uuid);
if (token) {
client.send("resumeReconnection", { token });
} else {
client.send("resumeGame", { roomId: currentRoomId });
}
return; // Don't proceed with normal lobby join
}
}
} catch {}
// Normal lobby join flow
// Check if this UUID already has a name
const existingName = NameManager.getInstance().getPlayerName(options.uuid);

View File

@@ -45,7 +45,11 @@ export class LobbyState extends Schema {
}
removePlayer(sessionId: string): void {
this.players.delete(sessionId);
try {
if (this.players.has(sessionId)) {
this.players.delete(sessionId);
}
} catch {}
this.totalPlayers = this.players.size;
}