Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GameKit matchmaking fails for 3G connections

I am making a multiplayer game for iOS and I read the material in Apple Developer Center, specifically this one. Here is my code for custom matchmaking, which is pretty straightforward:

- (void)findProgrammaticMatch {

    GKMatchRequest *request = [[GKMatchRequest alloc] init];
    request.minPlayers = 2;
    request.maxPlayers = 2;
    request.defaultNumberOfPlayers = 2;
    request.playersToInvite = nil;
    request.playerAttributes = 0;
    request.playerGroup = 0;

    UILabel *loading = (UILabel *)[aiw viewWithTag:792];

    [[GKMatchmaker sharedMatchmaker] findMatchForRequest:request withCompletionHandler:^(GKMatch *match, NSError *error) {
        if (error){

            //error handling
            [loaderLayer stopAnimating];
            UIButton *cancelButton = (UIButton *)[loaderLayer viewWithTag:442];
            [cancelButton setTitle:@"Go Back" forState:UIControlStateNormal];
            loading.text = @"Cannot find any players. Please try again later.";

        } else if (match != nil) {

            //save match
            self.match = match;
            self.match.delegate = self;

            loading.text = @"Found a player. Preparing session...";

            if (!self.matchStarted && match.expectedPlayerCount == 0) {

                self.matchStarted = YES;
                //begin game logic
                [self.scene setState:1];
                self.myTicket = 1000+arc4random_uniform(999);
                [self.scene send:self.myTicket];
                [self stopLoading];
            }

        }
    }];  
}

However, matchmaking fails when one or more devices are connected to the internet via cellular networks. When I investigated the underlying error I found out that even if it is a wifi to wifi case, the completion handler does not work as intended. That is, match.expectedPlayerCount is never 0. Instead, the game starts when - (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state handler is invoked after the completion handler as following:

...
- (void)match:(GKMatch *)match player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state {
    switch (state) {
        case GKPlayerStateConnected:
            self.matchStarted = YES;
            //begin game logic
            [self.scene setState:1];
            self.myTicket = 1000+arc4random_uniform(999);
            [self.scene send:self.myTicket];
            [self stopLoading];
            break;
...

The problem now is if a device with 3g is connected (and matched-sort of) didChangeState is never invoked. I checked for several other related questions on the internet and this site, although they are far from being satisfactory. I also read that sandbox servers of Game Center are not reliable and for some people production version worked perfectly(it just works!) despite the errors in sandbox mode, but I don't want to take that risk. Has anybody have experienced similar problem with their multiplayer game?

like image 983
Hgeg Avatar asked Apr 08 '15 18:04

Hgeg


2 Answers

Hgeg,

There is nothing wrong with your code. You have to allow cellular data usage to your app which needs users permission.

The following paragraph is selected from Apple's support website :

At the Foundation layer, you can use the setAllowsCellularAccess: method on NSMutableURLRequest to specify whether a request can be sent over a cellular connection. You can also use the allowsCellularAccess to check the current value.

At the Core Foundation layer, you can achieve the same thing by setting the kCFStreamPropertyNoCellular property before opening a stream obtained from the CFSocketStream or CFHTTPStream APIs.

In older versions of iOS, you can continue to use the kSCNetworkReachabilityFlagsIsWWAN as a best-effort way of determining whether traffic will be sent over a cellular connection, but you should be aware of its limitations.

Good luck

Iman

like image 149
Iman Avatar answered Nov 04 '22 08:11

Iman


According to the latest apple news, from iOS 9, the sand box mode will no longer exist, instead of the sandbox you'll have one unified environment.Unified envoiroment

So you'll have just one unified environments where you can share the same accounts, this should solve all the usual problems from the SandBox mode.

The new Unified System it's also compatible with TestFlight so you'll be able to test you code across multiple device and accounts.

All of these changes will be made directly by apple, so the only think that you can do it's to wait until they update to the new system, so far it's the only way to be sure that it's not a Sand Box problem. For more info please have a loot at the WWDC video

like image 44
Max_Power89 Avatar answered Nov 04 '22 08:11

Max_Power89