iOS: Retrieve Game Center friends who are online - ios

I can retrieve all Game Center friends with this code...
GKLocalPlayer *lp = [GKLocalPlayer localPlayer];
if (lp.authenticated)
{
[lp loadFriendsWithCompletionHandler:^(NSArray *friends, NSError *error)
{
NSLog(#"MY FRIENDS: %#",friends);
if (friends != nil)
{
[GKPlayer loadPlayersForIdentifiers:friends withCompletionHandler:^(NSArray *players, NSError *error)
{
if (error != nil)
{
// Handle the error.
NSLog(#"PLAYERLIST ERROR: %#",[error localizedDescription]);
}
if (players != nil)
{
// Process the array of GKPlayer objects.
NSLog(#"PLAYERS: %#",players);
}
}];
}
}];
}
... however, is there a way to retrieve only the friends with GameKit who are online?

It does not look like you are able to. Since GKPlayer does not offer any way to view if a player is online or not.
Also since technically once a person logs on to Game Center they are "Online" till they log off. Meaning they could be online for days while using their phone. When they are logged on if you send them an invite they will get the trumpet noise.
http://developer.apple.com/library/IOS/#documentation/GameKit/Reference/GKPlayer_Ref/Reference/Reference.html#//apple_ref/doc/uid/TP40009599

Related

How to prevent _User table from growing unnecessarily when using PFAnonymousUtils iOS SDK?

What is the best way to handle the scenario described below?
I am giving the user limited access (READONLY) when logged in anonymously.
The problem i am facing is that i am afraid is that the _User table would grow unnecessarily with redundant data.
Steps:
1. user logged in anonymously
2. clear cache
3. logged in anonymously again
problem : rows in _User table is added, older user is not removed.
Code:
+ (void) ParseLoginAnonymouslyWithBlock:(LoginAnonymousBLock)completionBlock {
// if ([PFUser currentUser] && [ParseUtilities isUserAnonymous]) {
// // user already logged in anonymously.
// // prevent duplicates in table
// completionBlock([PFUser currentUser], nil);
// return;
// }
[PFAnonymousUtils logInWithBlock:^(PFUser *user, NSError *error) {
// if (error) {
// completionBlock (user, error);
// } else {
// completionBlock (user, error);
// }
completionBlock(user, error);
}];
}
In View controller:
- (IBAction)loginGuestTapped:(id)sender {
NSLog(#"Guest Login tapped");
[ParseUtilities ParseLoginAnonymouslyWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
NSLog(#"%#", &error);
} else {
NSLog(#"success");
// user logged in
NSLog(#"isanonymous: %i and %#", [ParseUtilities isUserAnonymous], [PFUser currentUser]);
}
}];
}
You could just add a 'latest_activity' flag into every user and update it when the user uses your app.
Then create a BackgroundJob (https://parse.com/docs/js/guide#cloud_code) and remove the anonymous users that are older than ~2weeks?
What you could also do is setup Push Notifications in you app and for each user that gave you a push notification token make sure the push notification does not 'reach' the recipient. In that case you can delete him since he doesn't even have the app installed anymore. (False positives are much lower in this case than the other, but you should combine them anyway!)

How can I get player names in Game Center multiplayer?

As the title says I wondering how you can show both the local players alias and the other GKplayers alias. I'm using this Game Center manager i found on the internet https://github.com/nihalahmed/GameCenterManager. However I can only find a method for displaying the local players alias.
- (NSString *)localPlayerDisplayName {
if ([self isGameCenterAvailable] && [GKLocalPlayer localPlayer].authenticated) {
if ([[GKLocalPlayer localPlayer] respondsToSelector:#selector(displayName)]) {
return [GKLocalPlayer localPlayer].displayName;
} else {
return [GKLocalPlayer localPlayer].alias;
}
}
return #"unknownPlayer";
}
How can possibly find the other GKPlayers alias?
You need to ask Game Center for a player (or players) based on something like their identifiers (or a list of friends, or various other items). From there, you can get the alias and other information just like you do for the local player.
Here's skeleton code from the Game Center documentation, for example:
- (void) loadPlayerData: (NSArray *) identifiers
{
[GKPlayer loadPlayersForIdentifiers:identifiers withCompletionHandler:^(NSArray *players, NSError *error) {
if (error != nil)
{
// Handle the error.
}
if (players != nil)
{
// Process the array of GKPlayer objects.
}
}];
}
If you need help on creating the array of players to begin with, you can get that by asking for the player's friends list, or the currently-connected player, or various other ways.

iOS GameCenter Integration Error

In DidFinishLaunchingWithOptions I am trying to authenticate the player with this code
// Authenticate Player with Game Center
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
// Handle the call back from Game Center Authentication
[localPlayer localPlayer.authenticateHandler:^(NSError *error)
{
if (localPlayer.isAuthenticated)
{
// Player was successfully authenticated.
// Perform additional tasks for the authenticated player.
}
else if (error != nil)
{
NSLog(#"error : %#", [error description]);
}
}];
return YES;
}
But I get the error on this line [localPlayer localPlayer.authenticateHandler:^(NSError *error) saying missing a square bracket ']' and is pointing at the full stop '.'
I can't get this working
Thanks
You're not sending a message to the local player instance, so this is plain grammatically incorrect.
Please read.
You should be doing something like:
[localPlayer setAuthenticateHandler:
^(UIViewController *viewController, NSError *error) {
// ...
}
];

gamecenter turnbased save match data out of turn

Any chance I can save/update matchdata even when it is not my turn?
[currentMatch saveCurrentTurnWithMatchData:data completionHandler:^(NSError *error) {
if (error)
{ }];
The above code can be used if it is still this user's turn, but what if it is not this user's turn? How do I send data between two players?
As of iOS 6.0, you cannot. :(
You can save match data without advancing the turn (assuming you are
the current player). see - saveCurrentTurnWithMatchData:completionHandler:
You can end a game out of turn. see - participantQuitOutOfTurnWithOutcome:withCompletionHandler:
However, you cannot update match data out of turn.
GKTurnBasedMatch Reference
Try this
- (void) advanceTurn
{
NSData *updatedMatchData = [this.gameData encodeMatchData];
NSArray *sortedPlayerOrder = [this.gameData encodePlayerOrder];
this.MyMatch.message = [this.gameData matchAppropriateMessage];
[this.myMatch endTurnWithNextParticipants: sortedPlayerOrder turnTimeOut: GKTurnTimeoutDefault
matchData: updatedMatchData completionHandler ^(NSError *error) {
if (error)
{
// Handle the error.
}
}];
}

iOS GameCenter GKErrorCanceled

I'm in sandbox mode implementing game center in my application. The problem comes when I log to gameCenter, in some devices works fine in some others I get a GKErrorCanceled without even get the interface shown.
This devices don't have any user logged in gameCenter so it's not related to have a non sandbox account logged. My code is:
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
//First we try the new iOS6 authentification method for gamekit, if it's not implemented we will use the deprecated one
if ([localPlayer respondsToSelector:#selector(setAuthenticateHandler:)]) {
if (localPlayer.isAuthenticated) {
this->setState(connectionLoged);
this->getDelegate().socialConnectionDidSucceedLogin(*this);
return;
}
else if(!localPlayer.isAuthenticated && localPlayer.authenticateHandler){
this->setState(connectionClosed);
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string("The user already resign to login"));
return;
}
else{
localPlayer.authenticateHandler = ^(UIViewController* viewController, NSError* error){
if (localPlayer.isAuthenticated)
{
_name = [localPlayer.displayName UTF8String];
_userId = [localPlayer.playerID UTF8String];
[GKPlayer loadPlayersForIdentifiers:localPlayer.friends withCompletionHandler:^(NSArray *players, NSError *error) {
for (GKPlayer* player in players) {
if ([player isFriend]) {
NSDictionary* dict =
#{#"displayName" : player.displayName,
#"alias" : player.alias,
#"playerID" : player.playerID};
AttrDictionary* playerInfo = [dict hydraAttrDictionary];
SocialFriend* socialfriend = this->getNewFriendInstance(*playerInfo);
this->addFriend(socialfriend);
delete playerInfo;
}
}
this->getDelegate().socialConnectionDidSucceedLogin(*this);
this->setState(connectionLoged);
}];
}
else if(viewController){
UIViewController* rootViewController = (UIViewController*) [UIApplication sharedApplication].keyWindow.rootViewController ;
[rootViewController presentModalViewController:viewController animated:YES];
}
else{
if(error){
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string([error.description UTF8String]));
}
else{
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string("User cancelled login"));
}
}
};
}
}
//deprecated at IOs 6 authentification method
else
[localPlayer authenticateWithCompletionHandler:^(NSError *error) {
if (localPlayer.isAuthenticated)
{
_name = [localPlayer.displayName UTF8String];
_userId = [localPlayer.playerID UTF8String];
[GKPlayer loadPlayersForIdentifiers:localPlayer.friends withCompletionHandler:^(NSArray *players, NSError *error) {
for (GKPlayer* player in players) {
if ([player isFriend]) {
NSDictionary* dict =
#{#"displayName" : player.displayName,
#"alias" : player.alias,
#"playerID" : player.playerID};
AttrDictionary* playerInfo = [dict hydraAttrDictionary];
SocialFriend* socialfriend = this->getNewFriendInstance(*playerInfo);
this->addFriend(socialfriend);
delete playerInfo;
}
}
this->getDelegate().socialConnectionDidSucceedLogin(*this);
this->setState(connectionLoged);
}];
}
else{
NSString* errorString = [error localizedDescription];
this->getDelegate().socialConnectionDidFailToLogin(*this, std::string([errorString UTF8String]));
this->setState(connectionClosed);
}
}];
I need the code compatible with iOS 6 and iOS 5 so you will see I have the two implementations. For iOS 6 the completion handler returns with an UIViewController null and the error as I say. I'm afraid that in production it happends the same. In the simulator all works fine.
PS- You will find some c++ code, it's because I implement a c++ wrapper for GameCenter as my game is write in cocos2dx...
When someone cancels out of the interface to sign in to game center, it will give you GKErrorCanceled. The third time in a row that they cancel, it will warn them that it will disable game center.
If they do choose to disable game center, then it won't show the interface anymore, and it will just give you GKErrorCanceled instead.
Once game center has been disabled, the only way to sign in is by going into the actual game center app.
The 3 times in a row could be in any app or any combination of apps that use game center, and game center will be disabled for all apps that use game center. The 3 times in a row restarts every time they sign in to game center.
This is for both sandbox and non-sandbox.
This is for both ios 5 and ios 6.

Resources