reconexio
This commit is contained in:
@@ -115,8 +115,12 @@ onMounted(async () => {
|
|||||||
const room = await colyseusService.joinLobby();
|
const room = await colyseusService.joinLobby();
|
||||||
colorInput.value = colyseusService.playerColor.value || '#667eea';
|
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
|
// Prefer reconnection token path to bypass locked rooms
|
||||||
room.onMessage("resumeReconnection", async (data: any) => {
|
room.onMessage("resumeReconnection", async (data: any) => {
|
||||||
|
if (guardResume()) return;
|
||||||
try {
|
try {
|
||||||
await colyseusService.reconnectWithToken(data.token);
|
await colyseusService.reconnectWithToken(data.token);
|
||||||
// Leave lobby before navigating
|
// Leave lobby before navigating
|
||||||
@@ -132,6 +136,7 @@ onMounted(async () => {
|
|||||||
|
|
||||||
// Listen for server-initiated resume to existing game (fallback joinById)
|
// Listen for server-initiated resume to existing game (fallback joinById)
|
||||||
room.onMessage("resumeGame", async (data: any) => {
|
room.onMessage("resumeGame", async (data: any) => {
|
||||||
|
if (guardResume()) return;
|
||||||
try {
|
try {
|
||||||
const gameRoom = await colyseusService.joinGameRoom(data.roomId);
|
const gameRoom = await colyseusService.joinGameRoom(data.roomId);
|
||||||
// Leave lobby before navigating
|
// Leave lobby before navigating
|
||||||
|
|||||||
@@ -368,12 +368,18 @@ adminRouter.post("/admin/shuffle-players", async (req: Request, res: Response) =
|
|||||||
|
|
||||||
// 6. Assign players to rooms and roles randomly
|
// 6. Assign players to rooms and roles randomly
|
||||||
const assignments: { [roomId: string]: { p1: any; p2: any } } = {};
|
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 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]];
|
const [player1, player2] = Math.random() < 0.5 ? [group[0], group[1]] : [group[1], group[0]];
|
||||||
|
|
||||||
assignments[roomInfo.roomId] = {
|
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))
|
.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);
|
await Promise.allSettled(clearPromises);
|
||||||
|
|
||||||
// 8. Wait a bit for rooms to clear, then assign new players
|
// 8. Wait a bit for rooms to clear, then assign new players
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export class LobbyRoom extends Room<LobbyState> {
|
|||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
onJoin(client: Client, options: any) {
|
async onJoin(client: Client, options: any) {
|
||||||
console.log(`[LobbyRoom] ${client.sessionId} joined lobby with UUID: ${options.uuid}`);
|
console.log(`[LobbyRoom] ${client.sessionId} joined lobby with UUID: ${options.uuid}`);
|
||||||
// Enforce UUID presence and allowlist (if configured)
|
// Enforce UUID presence and allowlist (if configured)
|
||||||
if (!options.uuid || !isUuidAllowed(options.uuid)) {
|
if (!options.uuid || !isUuidAllowed(options.uuid)) {
|
||||||
@@ -62,32 +62,7 @@ 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);
|
||||||
|
|
||||||
// If this UUID has a current active game room assignment, redirect there
|
// (duplicate resume check removed; handled below with await)
|
||||||
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 {}
|
|
||||||
|
|
||||||
// Check for shuffle redirect FIRST
|
// Check for shuffle redirect FIRST
|
||||||
if (NameManager.getInstance().isShuffleInProgress()) {
|
if (NameManager.getInstance().isShuffleInProgress()) {
|
||||||
const assignment = NameManager.getInstance().getPlayerRoomAssignment(options.uuid);
|
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
|
// 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);
|
||||||
|
|||||||
@@ -45,7 +45,11 @@ export class LobbyState extends Schema {
|
|||||||
}
|
}
|
||||||
|
|
||||||
removePlayer(sessionId: string): void {
|
removePlayer(sessionId: string): void {
|
||||||
this.players.delete(sessionId);
|
try {
|
||||||
|
if (this.players.has(sessionId)) {
|
||||||
|
this.players.delete(sessionId);
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
this.totalPlayers = this.players.size;
|
this.totalPlayers = this.players.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user