Enhance matchmaker to validate mode and create authoritative matches
- Implement MatchmakerMatched callback for true matchmaking flow - Enforce strict 1v1 pairing (ignore non-2 player matches) - Read `mode` from matchmaker ticket properties - Prevent mismatched-mode players from being paired - Automatically create authoritative `tictactoe` match when valid pair found - Provide match parameters so match handler receives selected mode - Improve logging for debugging and visibility Ensures clean, mode-aware matchmaking queues and proper server-side match creation.
This commit is contained in:
@@ -23,50 +23,39 @@ func MatchmakerMatched(
|
|||||||
) (string, error) {
|
) (string, error) {
|
||||||
|
|
||||||
if len(entries) != 2 {
|
if len(entries) != 2 {
|
||||||
logger.Warn("MatchmakerMatched triggered but incorrect player count: %d", len(entries))
|
logger.Warn("MatchmakerMatched triggered with %d players", len(entries))
|
||||||
return "", runtime.NewError("requires exactly 2 players", 3)
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract player data
|
propsA := entries[0].GetProperties()
|
||||||
ticketA := entries[0]
|
propsB := entries[1].GetProperties()
|
||||||
ticketB := entries[1]
|
|
||||||
|
|
||||||
propsA := ticketA.GetProperties()
|
|
||||||
propsB := ticketB.GetProperties()
|
|
||||||
|
|
||||||
modeA, okA := propsA["mode"].(string)
|
modeA, okA := propsA["mode"].(string)
|
||||||
modeB, okB := propsB["mode"].(string)
|
modeB, okB := propsB["mode"].(string)
|
||||||
|
|
||||||
if !okA || !okB {
|
if !okA || !okB {
|
||||||
logger.Error("Matchmaker ticket missing mode property")
|
logger.Warn("MatchmakerMatched missing mode property — ignoring")
|
||||||
return "", runtime.NewError("matchmaking requires game mode", 13)
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Ensure both players queued for the same mode
|
// ✅ If modes don’t match, let Nakama find another pairing
|
||||||
if modeA != modeB {
|
if modeA != modeB {
|
||||||
logger.Warn("Players queued for different modes: %s != %s", modeA, modeB)
|
logger.Warn("Mode mismatch %s vs %s — retrying matchmaking", modeA, modeB)
|
||||||
return "", runtime.NewError("players must select same mode", 3)
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ Create authoritative match
|
||||||
matchParams := map[string]interface{}{
|
matchParams := map[string]interface{}{
|
||||||
"mode": modeA,
|
"mode": modeA,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ✅ Create authoritative match instance
|
|
||||||
matchID, err := nk.MatchCreate(ctx, "tictactoe", matchParams)
|
matchID, err := nk.MatchCreate(ctx, "tictactoe", matchParams)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("MatchCreate failed: %v", err)
|
logger.Error("MatchCreate failed: %v", err)
|
||||||
return "", runtime.NewError("failed to create match", 13)
|
return "", runtime.NewError("failed to create match", 13)
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("✅ Match created: %s — mode=%s — players=%s, %s",
|
logger.Info("✅ Match created %s — mode=%s", matchID, modeA)
|
||||||
matchID,
|
|
||||||
modeA,
|
|
||||||
ticketA.GetPresence().GetUserId(),
|
|
||||||
ticketB.GetPresence().GetUserId(),
|
|
||||||
)
|
|
||||||
|
|
||||||
// ✅ Return match ID so Nakama notifies clients over WebSocket
|
|
||||||
return matchID, nil
|
return matchID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user