feat(matchmaking): add automatic requeue on match rejection
- Detect Nakama error code 3 ("No match ID or token found") when a
match is rejected due to incompatible match properties (e.g., mode mismatch).
- Preserve last selected game mode using a ref so client can requeue
automatically without user interaction.
- Implement fallback logic to call joinMatchmaker() again after server
rejection.
- Improve robustness of matchmaking flow by ensuring players remain
in queue until a valid match is formed.
This commit is contained in:
@@ -47,6 +47,8 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
||||
const [session, setSession] = useState<Session | null>(null);
|
||||
const [socket, setSocket] = useState<Socket | null>(null);
|
||||
const [matchId, setMatchId] = useState<string | null>(null);
|
||||
const lastModeRef = React.useRef<string | null>(null);
|
||||
const socketRef = React.useRef<Socket | null>(null);
|
||||
|
||||
// ----------------------------------------------------
|
||||
// LOGIN
|
||||
@@ -62,17 +64,32 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
||||
const s = client.createSocket(undefined, undefined); // no SSL on localhost
|
||||
await s.connect(newSession, true);
|
||||
setSocket(s);
|
||||
socketRef.current = s;
|
||||
|
||||
console.log("[Nakama] WebSocket connected");
|
||||
|
||||
// MATCHMAKER MATCHED CALLBACK
|
||||
s.onmatchmakermatched = async (matched: MatchmakerMatched) => {
|
||||
// 1) If match_id is empty → server rejected the group.
|
||||
if (!matched.match_id) {
|
||||
console.warn("[Nakama] Match rejected by server. Auto-requeueing...");
|
||||
|
||||
if (lastModeRef.current) {
|
||||
try {
|
||||
await joinMatchmaker(lastModeRef.current);
|
||||
} catch (e) {
|
||||
console.error("[Nakama] Requeue failed:", e);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) Valid match: continue as usual.
|
||||
console.log("[Nakama] MATCHED:", matched);
|
||||
|
||||
setMatchId(matched.match_id);
|
||||
|
||||
try {
|
||||
await s.joinMatch(matched.match_id);
|
||||
setMatchId(matched.match_id);
|
||||
console.log("[Nakama] Auto-joined match:", matched.match_id);
|
||||
} catch (err) {
|
||||
console.error("[Nakama] Failed to join match:", err);
|
||||
@@ -84,6 +101,7 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
||||
// MATCHMAKING
|
||||
// ----------------------------------------------------
|
||||
async function joinMatchmaker(mode: string) {
|
||||
const socket = socketRef.current;
|
||||
if (!socket) throw new Error("socket missing");
|
||||
|
||||
console.log(`[Nakama] Matchmaking... with +mode:"${mode}"`);
|
||||
@@ -94,6 +112,8 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
||||
{ mode } // stringProperties
|
||||
);
|
||||
|
||||
lastModeRef.current = mode;
|
||||
|
||||
return ticket.ticket;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user