Note that there are some explanatory texts on larger screens.

plurals
  1. POCant receive game center invitations
    primarykey
    data
    text
    <p>I am trying to develop a realtime multiplayer game for IOS by using cocos2d by using the tutorial on <a href="http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-22" rel="nofollow">http://www.raywenderlich.com/3325/how-to-make-a-simple-multiplayer-game-with-game-center-tutorial-part-22</a></p> <p>Everything works fine including auto matching with a random player but inviting a friend doesn't work because other device cannot receive an invitation.</p> <p>When I clicked on invite friends button and then selected a friend by using the standard game center interface, it says waiting (forever) and nothing happens. My friend cannot receive an invitation from game center (no notifications). </p> <p>I can invite a friend by using nearby friends functionality (when this functionality is enabled on both devices) but no invitation notification when nearby friends is disabled.</p> <p>I spent hours and hours for searching on Google, found similar cases but no solution.</p> <p><strong>Some early feedback about possible answers:</strong></p> <ul> <li>I use two devices (one iPhone and one iPad), no simulator</li> <li>All settings on iTunes connect are fine including multiplayer settings</li> <li>I validated that both devices are connected to sandbox by using different test accounts</li> <li>I've already checked the notification settings for Game center on both devices</li> <li>I've already checked all proxy/firewall issues and tried on both WiFi and Cellular for both devices</li> <li>Game invitations are enabled for both of the devices/accounts</li> <li>I've already checked the bundle IDs, app version IDs, etc...</li> <li>Both of the devices are IOS 6.x and App target version os IOS 5.0</li> <li>I have no other issues about game center (leaderboards, random matchmaking, etc... all fine)</li> <li>I call the inviteHandler method as soon after I authenticated a user as possible as mentioned in Apple documentation.</li> </ul> <p><strong>Here is my Game center helper class Header file:</strong></p> <pre><code>#import &lt;Foundation/Foundation.h&gt; #import &lt;GameKit/GameKit.h&gt; @protocol GCHelperDelegate - (void)matchStarted; - (void)matchEnded; - (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID; - (void)inviteReceived; @end @interface GCHelper : NSObject &lt;GKMatchmakerViewControllerDelegate, GKMatchDelegate&gt;{ BOOL gameCenterAvailable; BOOL userAuthenticated; UIViewController *presentingViewController; GKMatch *match; BOOL matchStarted; id &lt;GCHelperDelegate&gt; delegate; NSMutableDictionary *playersDict; GKInvite *pendingInvite; NSArray *pendingPlayersToInvite; NSMutableArray *unsentScores; } @property (retain) GKInvite *pendingInvite; @property (retain) NSArray *pendingPlayersToInvite; @property (assign, readonly) BOOL gameCenterAvailable; @property (retain) NSMutableDictionary *playersDict; @property (retain) UIViewController *presentingViewController; @property (retain) GKMatch *match; @property (assign) id &lt;GCHelperDelegate&gt; delegate; - (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id&lt;GCHelperDelegate&gt;)theDelegate; - (BOOL) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent; + (GCHelper *)sharedInstance; - (void)authenticateLocalUser; @end </code></pre> <p><strong>And here is the implementation of the game center helper class</strong></p> <pre><code>#import "GCHelper.h" @implementation GCHelper @synthesize gameCenterAvailable; @synthesize presentingViewController; @synthesize match; @synthesize delegate; @synthesize playersDict; @synthesize pendingInvite; @synthesize pendingPlayersToInvite; #pragma mark Initialization static GCHelper *sharedHelper = nil; + (GCHelper *) sharedInstance { if (!sharedHelper) { sharedHelper = [[GCHelper alloc] init]; } return sharedHelper; } - (BOOL)isGameCenterAvailable { // check for presence of GKLocalPlayer API Class gcClass = (NSClassFromString(@"GKLocalPlayer")); // check if the device is running iOS 4.1 or later NSString *reqSysVer = @"4.1"; NSString *currSysVer = [[UIDevice currentDevice] systemVersion]; BOOL osVersionSupported = ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending); return (gcClass &amp;&amp; osVersionSupported); } - (id)init { if ((self = [super init])) { gameCenterAvailable = [self isGameCenterAvailable]; if (gameCenterAvailable) { NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; [nc addObserver:self selector:@selector(authenticationChanged) name:GKPlayerAuthenticationDidChangeNotificationName object:nil]; } } return self; } - (void)authenticationChanged { if ([GKLocalPlayer localPlayer].isAuthenticated &amp;&amp; !userAuthenticated) { NSLog(@"Authentication changed: player authenticated."); userAuthenticated = TRUE; [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) { NSLog(@"Received invite"); self.pendingInvite = acceptedInvite; self.pendingPlayersToInvite = playersToInvite; [delegate inviteReceived]; }; } else if (![GKLocalPlayer localPlayer].isAuthenticated &amp;&amp; userAuthenticated) { NSLog(@"Authentication changed: player not authenticated"); userAuthenticated = FALSE; } } - (void)lookupPlayers { NSLog(@"Looking up %d players...", match.playerIDs.count); [GKPlayer loadPlayersForIdentifiers:match.playerIDs withCompletionHandler:^(NSArray *players, NSError *error) { if (error != nil) { NSLog(@"Error retrieving player info: %@", error.localizedDescription); matchStarted = NO; [delegate matchEnded]; } else { // Populate players dict self.playersDict = [NSMutableDictionary dictionaryWithCapacity:players.count]; for (GKPlayer *player in players) { NSLog(@"Found player: %@", player.alias); [playersDict setObject:player forKey:player.playerID]; } // Notify delegate match can begin matchStarted = YES; [delegate matchStarted]; } }]; } #pragma mark User functions - (void)authenticateLocalUser { if (!gameCenterAvailable) return; NSLog(@"Authenticating local user..."); if ([GKLocalPlayer localPlayer].authenticated == NO) { [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:nil]; } else { NSLog(@"Already authenticated!"); } } - (void)findMatchWithMinPlayers:(int)minPlayers maxPlayers:(int)maxPlayers viewController:(UIViewController *)viewController delegate:(id&lt;GCHelperDelegate&gt;)theDelegate { if (!gameCenterAvailable) return; matchStarted = NO; self.match = nil; self.presentingViewController = viewController; delegate = theDelegate; if (pendingInvite != nil) { [presentingViewController dismissModalViewControllerAnimated:NO]; GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:pendingInvite] autorelease]; mmvc.matchmakerDelegate = self; [presentingViewController presentModalViewController:mmvc animated:YES]; self.pendingInvite = nil; self.pendingPlayersToInvite = nil; } else { [presentingViewController dismissModalViewControllerAnimated:NO]; GKMatchRequest *request = [[[GKMatchRequest alloc] init] autorelease]; request.minPlayers = minPlayers; request.maxPlayers = maxPlayers; request.playersToInvite = pendingPlayersToInvite; GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithMatchRequest:request] autorelease]; mmvc.matchmakerDelegate = self; [presentingViewController presentModalViewController:mmvc animated:YES]; self.pendingInvite = nil; self.pendingPlayersToInvite = nil; } } #pragma mark GKMatchmakerViewControllerDelegate // The user has cancelled matchmaking - (void)matchmakerViewControllerWasCancelled:(GKMatchmakerViewController *)viewController { [presentingViewController dismissModalViewControllerAnimated:YES]; } // Matchmaking has failed with an error - (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFailWithError:(NSError *)error { [presentingViewController dismissModalViewControllerAnimated:YES]; NSLog(@"Error finding match: %@", error.localizedDescription); } // A peer-to-peer match has been found, the game should start - (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch { [presentingViewController dismissModalViewControllerAnimated:YES]; self.match = theMatch; match.delegate = self; if (!matchStarted &amp;&amp; match.expectedPlayerCount == 0) { NSLog(@"Ready to start match!"); [self lookupPlayers]; } } #pragma mark GKMatchDelegate // The match received data sent from the player. - (void)match:(GKMatch *)theMatch didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID { if (match != theMatch) return; [delegate match:theMatch didReceiveData:data fromPlayer:playerID]; } // The player state changed (eg. connected or disconnected) - (void)match:(GKMatch *)theMatch player:(NSString *)playerID didChangeState:(GKPlayerConnectionState)state { if (match != theMatch) return; switch (state) { case GKPlayerStateConnected: // handle a new player connection. NSLog(@"Player connected!"); if (!matchStarted &amp;&amp; theMatch.expectedPlayerCount == 0) { NSLog(@"Ready to start match!"); [self lookupPlayers]; } break; case GKPlayerStateDisconnected: // a player just disconnected. NSLog(@"Player disconnected!"); matchStarted = NO; [delegate matchEnded]; break; } } // The match was unable to connect with the player due to an error. - (void)match:(GKMatch *)theMatch connectionWithPlayerFailed:(NSString *)playerID withError:(NSError *)error { if (match != theMatch) return; NSLog(@"Failed to connect to player with error: %@", error.localizedDescription); matchStarted = NO; [delegate matchEnded]; } // The match was unable to be established with any players due to an error. - (void)match:(GKMatch *)theMatch didFailWithError:(NSError *)error { if (match != theMatch) return; NSLog(@"Match failed with error: %@", error.localizedDescription); matchStarted = NO; [delegate matchEnded]; } - (void)reportScore:(int64_t)score forCategory:(NSString *)category { // Only execute if OS supports Game Center &amp; player is logged in if ([self isGameCenterAvailable] &amp;&amp; [GKLocalPlayer localPlayer].authenticated == YES) { // Create score object GKScore *scoreReporter = [[[GKScore alloc] initWithCategory:category] autorelease]; // Set the score value scoreReporter.value = score; // Try to send [scoreReporter reportScoreWithCompletionHandler:^(NSError *error) { if (error != nil) { // Handle reporting error here by adding object to a serializable array, to be sent again later [unsentScores addObject:scoreReporter]; } }]; } } - (BOOL) reportAchievementIdentifier: (NSString*) identifier percentComplete: (float) percent { if ([self isGameCenterAvailable] &amp;&amp; [GKLocalPlayer localPlayer].authenticated == YES) { GKAchievement *achievement = [[[GKAchievement alloc] initWithIdentifier: identifier] autorelease]; if (achievement) { achievement.percentComplete = percent; [achievement reportAchievementWithCompletionHandler:^(NSError *error) { if (error != nil) { // Retain the achievement object and try again later (not shown). } }]; } return YES; } return NO; } @end </code></pre> <p><strong>And Finally this is how I call the game center from my game layer (I tried two different options but none of them worked)</strong></p> <p><em>Option 1</em></p> <pre><code>[[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController: [[[UIApplication sharedApplication] keyWindow] rootViewController] delegate: self]; </code></pre> <p><em>Option 2</em></p> <pre><code>AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; UINavigationController *viewController = [app navController]; [[GCHelper sharedInstance] findMatchWithMinPlayers:2 maxPlayers:2 viewController:viewController delegate:self]; </code></pre> <p>Any help will be appreciated. Thanks in advance...</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload