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 [session, setSession] = useState<Session | null>(null);
|
||||||
const [socket, setSocket] = useState<Socket | null>(null);
|
const [socket, setSocket] = useState<Socket | null>(null);
|
||||||
const [matchId, setMatchId] = useState<string | null>(null);
|
const [matchId, setMatchId] = useState<string | null>(null);
|
||||||
|
const lastModeRef = React.useRef<string | null>(null);
|
||||||
|
const socketRef = React.useRef<Socket | null>(null);
|
||||||
|
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
// LOGIN
|
// LOGIN
|
||||||
@@ -62,17 +64,32 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
|||||||
const s = client.createSocket(undefined, undefined); // no SSL on localhost
|
const s = client.createSocket(undefined, undefined); // no SSL on localhost
|
||||||
await s.connect(newSession, true);
|
await s.connect(newSession, true);
|
||||||
setSocket(s);
|
setSocket(s);
|
||||||
|
socketRef.current = s;
|
||||||
|
|
||||||
console.log("[Nakama] WebSocket connected");
|
console.log("[Nakama] WebSocket connected");
|
||||||
|
|
||||||
// MATCHMAKER MATCHED CALLBACK
|
// MATCHMAKER MATCHED CALLBACK
|
||||||
s.onmatchmakermatched = async (matched: MatchmakerMatched) => {
|
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);
|
console.log("[Nakama] MATCHED:", matched);
|
||||||
|
|
||||||
setMatchId(matched.match_id);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await s.joinMatch(matched.match_id);
|
await s.joinMatch(matched.match_id);
|
||||||
|
setMatchId(matched.match_id);
|
||||||
console.log("[Nakama] Auto-joined match:", matched.match_id);
|
console.log("[Nakama] Auto-joined match:", matched.match_id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("[Nakama] Failed to join match:", err);
|
console.error("[Nakama] Failed to join match:", err);
|
||||||
@@ -84,6 +101,7 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
|||||||
// MATCHMAKING
|
// MATCHMAKING
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
async function joinMatchmaker(mode: string) {
|
async function joinMatchmaker(mode: string) {
|
||||||
|
const socket = socketRef.current;
|
||||||
if (!socket) throw new Error("socket missing");
|
if (!socket) throw new Error("socket missing");
|
||||||
|
|
||||||
console.log(`[Nakama] Matchmaking... with +mode:"${mode}"`);
|
console.log(`[Nakama] Matchmaking... with +mode:"${mode}"`);
|
||||||
@@ -94,6 +112,8 @@ export function NakamaProvider({ children }: { children: React.ReactNode }) {
|
|||||||
{ mode } // stringProperties
|
{ mode } // stringProperties
|
||||||
);
|
);
|
||||||
|
|
||||||
|
lastModeRef.current = mode;
|
||||||
|
|
||||||
return ticket.ticket;
|
return ticket.ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user