iosgame-centergkturnbasedmatch

Proper GKTurnBasedMatch End Of Match When participantQuitOutOfTurnWithOutcome


In my turn based match, I am unable to cleanly end the match when an out of turn player quits the match. I believe this is preventing me from starting a rematch.

Here is what I have observed. When I examine the completed game status of this game from the GKTurnBasedMatchmakerViewController of Player 1's device, it shows that the match outcome of Player 1 is Quit and the match outcome of Player 2 is "This player's turn". However, if I examine the completed game status of this game from the GKTurnBasedMatchmakerViewController of Player 2's device, it shows that the match outcome of Player 1 is Quit and the match outcome of Player 2 is "Won". BUT, if I click on "View Game" from the GKTurnBasedMatchmakerViewController from within the Player 1 device, the match outcome switches to "Won" for Player 2. How do I end this game properly so that Player 2 has a match outcome of "Won" from the perspective of Player 1?

In my scenario, player 1 starts a match and takes his turn. Then player 2 starts his turn. During that time, player 1 quits the match. The code sequence is then as follows:

Player 1:

[currentMatch participantQuitOutOfTurnWithOutcome:GKTurnBasedMatchOutcomeQuit withCompletionHandler:nil];

Player 2 - after receiving a call to handleTurnEventForMatch:didBecomeActive:

        // For each participant, set their matchOutcome relative to the local player who has just won.
        for (GKTurnBasedParticipant *part in [currentMatch.participants) {
            if ([part.playerID isEqualToString:[GKLocalPlayer localPlayer].playerID]) {
                part.matchOutcome = GKTurnBasedMatchOutcomeWon;
            }
            else {
                part.matchOutcome = GKTurnBasedMatchOutcomeQuit;

            }
        }
        [currentMatch endMatchInTurnWithMatchData: data
                             completionHandler: ^(NSError *error) {
                                if (error) {
                                    NSLog(@"%@", error);
                                }
                                else {
                                    NSLog(@"After win: match ended successfully");
                                }];

Player 1 receives a prompt asking whether they want a rematch. If the user responds affirmatively, the following is sent:

[currentMatch rematchWithCompletionHandler:^(GKTurnBasedMatch *reMatch, NSError *error) {
    if (error) {
        NSLog(@"In rematchWithCompletionHandler. Error creating rematch: %@", error.localizedDescription);
    } else {
        NSLog(@"Success");
    }];

Unfortunately, the above rematch attempt fails because of the incorrect status of Player 2. The resultant error message from above is:

The requested operation could not be completed because the match request is invalid.

The following stack overflow problem suggests this is due the errant match data described above: Trouble Using the new rematchWithCompletionHandler method from Game Center


Solution

  • In order to solve this problem, I had to programmatically load the match data to force the matchOutcome of player 2 to switch to the state of "Won". So, instead of immediately calling rematchWithCompletionHandler when the user affirms the prompt for a rematch, I do the following when they affirm the prompt for a rematch:

    [GKTurnBasedMatch loadMatchWithID:currentMatch.matchID withCompletionHandler:
      ^(GKTurnBasedMatch *match, NSError *error) {
        if (error) {
            NSLog(@"In requestRematch, failed to receive match data: %@", error.localizedDescription);
        }
        else {
             // Received the match data. Now request a rematch
             [match rematchWithCompletionHandler:
                ^(GKTurnBasedMatch *reMatch, NSError *error) {
                  if (error) {
                      NSLog(@"In requestRematch: rematchWithCompletionHandler. Error creating rematch: %@", error.localizedDescription);
                  }
    
                  else
                  {
                      NSLog(@"In requestRematch: Rematch granted with new matchID=%@. currentMatch was: %@", match.matchID, currentMatch.matchID);
    
                      // Do something with the reMatch data
                  }
    
              }];
         }
    }];