How to sync score when game center is not available? - iphone

imagine there is no internet connection when user is playing. The score cannot be submitted to game center. However I save the highscore on the phone using NSUserDefaults too.
So when the user plays next time and is connected to game center should I sync this score he achieved playing "offline"?
Is that a good practice?

Per the Apple Game Center docs, the answer is YES.
Make Sure Your Game Sends Data Again After a Network Failure
When you implement leaderboards or achievements, your game reports a
player’s scores or achievement progress to Game Center. However,
networking is never perfectly reliable. If a networking error occurs,
your game should save the Game Kit object and retry the action again
at a later time. Both the GKScore and GKAchievement classes support
the NSCoding protocol, so your game can archive those objects when it
moves into the background.
Set up a cache that keeps your score data (I use NSUserDefaults) to preserve data between sessions, and every so often (like, each time the user enters the app) test to see if Game Center is reachable, and if so, upload your cached scores. Let me know if you need any code - this post is pretty old, so I won't be surprised if no one ever answers :)

Also per the Apple docs for iOS 5.0 and later network error related issues are handled by a background reporting task so the developer does not need to write anything to handle this if not supporting previous iOS versions.
(from GKScore Class Reference for method reportScoreWithCompletionHandler:)
If the error is a network error and your game is running on iOS 4.3 or earlier, your game should periodically attempt to report the progress until the score is successfully reported. On iOS 5.0 and later, the background reporting task automatically handles network errors on your game’s behalf.
I am not sure what is supposed to happen if no one is logged into Game Center at all though (no network related/ submission issues) when a high score is achieved and then someone logs in later. In that case no GKScore object can even be created because there is no authenticated player and so there is no way to know who actually achieved the score whenever the next person logs into Game Center. Seems handling logged in (even without a network connection temporarily) is best practice but if no one is logged in at all and a high score is gained then it's just tough luck because it is not known who earned it, other than saving it as a device high score. If anyone handles that case then please tell.

Good question.
In my point of view, if a user is offline and is still playing, the score he/she scores should be saved locally. And when he/she again appears online, the offline score shouldn't be submitted online. Because if offline score is submitted, the purpose of making the game online is defeated.

Related

GKTurnBasedMatch push notifications are very inconsistent

I'm testing a turn based game between two devices. As far as I understand, sending a turn with [GKTurnBasedMatch endTurnWithNextParticipants:], for example, should automatically push a game center notification to the opponent. Sometimes, this works just as expected: the turn is sent and right away a banner notification shows up on the other device. All is well.
What is baffling me is that other times, even though the turn itself is sent properly (I can tell because when the opponent refreshes the matches, the match is up-to-date), there's no push notification coming in.
Are there any holes in my understanding here? If I'm understanding correctly, the inconsistent notifications shouldn't have anything to do with my code, because the issue here isn't how I handle notifications, it's that there is no notification at all. In other words, [handleTurnEventForMatch:] (aGKTurnBasedEventHandlerDelegate method) doesn't have anything to do with it (I don't think) because if no notification is being received, it's never going to be called anyway.
So, I'm just wondering if anyone has had any experience with this. Is it possible that this is due to something in my code? Or, is it possible that the Game Center sandbox is responsible for the inconsistencies, and there's nothing I can do about it?
Any thoughts or ideas would be much appreciated.
It is an issue with GameCenter's sandbox mode. In order for your device to enter sandbox mode you have to open/run your app and authenticate game center. If you say, open a different (published) game after your game is open it will leave sandbox mode and and go back to regular game center mode.
Even if your game is running in the background, as long as it is the last game-center enabled game opened you should get the push notifications as normal. But if you open the game, and then kill the process, you will no longer be in sandbox mode and will not receive the push notifications.
For those who are experiencing similar problems: this turned out to be a Game Center sandbox problem. It had nothing to do with my code, and things were fine in the App Store release. So, read through the comments here and make sure there aren't other things factoring into whatever issues you're having...but know that it's possible that you're simply experiencing some Game Center sandbox issues that are out of your control!
I am also facing the same problem. My game stops receiving turn events and turn notifications from Game Center, I finished my game and was testing, but this week, the problem started to happen. It was working like a charm but suddenly instances started not to receiving turn events for a couple of days.
I am using the iOS7 SDK and targeting iOS7 (turn event handling is different than prior iOS versions, I will need exchanges in upcoming game features, that's why I am using iOS7).
Then I made a test app to check if it was same with iOS6 and prior SDKs, but no help, it was same. So don't waste your time to upgrade your code to iOS7 hoping it would work, the problem is there. I also tried many things, like resetting devices and settings, using new users, etc.
I also tried it with Ray Wenderlich's Turn-Based Gaming with iOS 5 tutorial, by downloading source code, and it doesn't work neither.
The thing is, usually when I launch the game, game receives turn events, but after a few turns, it just stops, and when it stops receiving, stops like forever. If I reload the match, I can get the updated match and it's data is also updated, so I can make the turn. It means match is updated on Game Center. So, either Game Center is not pushing the data to users (possibly this is happening because user cannot receive notifications from Game Center when the game is in background), or the GameKit is not firing the event to the handler.
I don't know why it is happening, or why it started to happen, but I can't release my game like this, hoping that it would work out of sandbox. I will be trying a couple of more things (like maybe trying turn reminders of iOS7, to see if they push it to the user), then I will ask to Apple's support team. One other thing i am planning to do is, putting my test app to App Store and see it if works out of sandbox.
Hopefully it is a sandbox problem.

High score system iphone game

I have made a simple class that allows me to submit scores to my online highscore-system, but I am wondering what I would do if there is no internet connection availible. I save the scores in a plist, but it doesn't get synchronised there, that happens after a player gets a new highscore, after a game thus. If there is no connection with the internet, the score won't get submitted.
My question is : "How can I make sure that the highscores are synchronised when there is a connection availible?"
Thanks in advance,
Joe
The last Cocos2d game I wrote I used Steffen Itterheim’s GameKitHelper class for this to great effect.
Also see:
Integrate Gamecenter in cocos2d game
Synchronizing Offline Game Center Achievements and Scores
You could probably adapt one of these for your own high-score system, but it does beg the question "why not use game center?"
You can keep a record of the score upload status (with date+time, so you can have multiple scores) in a file and check it on startup for any scores that weren't synchronized.
I don't know anything about iPhone development yet, but on a logic level, why don't you have a boolean flag set to false stating that it never was synced online yet. Then when the game starts, check the flag and if the flag is false and internet is available update the score data. You can either then set the flag to be true, or delete the value out of the plist.

iPhone Game pause and resume, is it worth implementing?

Allow me to describe my situation:
I want to develop a game, that is round-base, and pay-to-play. That means you pay one coin, for one round of game, like Pinball etc.
The problem is, when there is interruption, ideally the game should pause, and resume whenever the user desires. Implementing that seems to be a challenge. Say my game was put into background, I would save the game state in ApplicationDidEnterBackground. However the game may or may not get terminated while in the background. So the next launch could be a "fresh start" , or, a "resume from last saved state".
If the app is left in the background long enough, say 1 week, its almost certain that other apps fighting for memory will cause the game to be terminated at some point. When the user starts my app again, they would be playing from a new round, meaning that the previously unfinished game, is gone.
From a customer point of view, this is unfair.
What I can think of is, to implement it so that whenever my app is brought to the foreground, I would go check if there was a saved game. If there was, I shall resume it instead. This poses a security issue:
Saved game, either in most primitive plist format or other formats, are persisted, and poses security problems. (What if players edit the game state and score 10 million points as top score... etc)
Are there any recommended ways to tackle these problems?
I see some Apps simply give up on saving the game, and a new round will be started on resume. Those are not paid to play games, otherwise I can imagine users getting very angry.
I have seen some Apps that saves the game state for a while, but when it got terminated, when next launched, it will start a fresh round. Which seems just as unacceptable in the case where players actually paid money for the round.
And when taken into account the possibility of crashes, I cannot come up with a good solution that ensure paying customer will get to play a full round of game. It would really help me if someone with relevant experience could share their thoughts, and how they make their decisions.
Why not tie the round finishing to the payment? If the round doesn't finish, no payment is taken. If the user's credits are insufficient at the time the round finishes, you could give them the option to purchase more credits immediately (via in-app purchase) to finish the current round.
That simplifies your task as a developer, and also provides a way to prompt the user for additional payment in a non-obnoxious way.
Here's a great tutorial on using NSCoding to save game states. It won't have any problem with the player going in a editing the file, as it is done in NSCoding. If a user REALLY wants to figure out how to un-encode the file and change the contents, which is crazy, you could do some kind of encryption on the data BEFORE you write it to file, so there would be no way the user could change it. Hope that helps!

OpenFeint, Game Center and multiple users

I'm about to add highscore support to my mobile game and I have a basic understanding problem with leaderboard services like OpenFeint or Apples Game Center:
Suppose I'm logged in to OpenFeint and/or Game Center with my account. Then a pal of mine wants to play, I hand him my device and he gets the best score ever. Is there any way he can get his score listed under his name now? My understanding is that he can't, because when the game is over the score is saved, and it is automatically saved for the current account, which happens to be mine at that moment. Tough luck.
This would mean that if I play the game with my pal in turns we would constantly have to log in and out from both services after each game to get it right in the case that one of us gets a highscore. That seems a bit awkward...
Do I overlook something or is this just the way it works? Or do I have to take care for this situation as a developer? Or do the OpenFeint/GameKit SDKs handle this automatically somehow?
I don't know about Open Feint, but at least for Game Center I think the answer to your question is: Yes, that's just the way it works. Even if you know the Game Center id's for both you and your friend, you don't have the ability to save stats for anyone but the logged in game center player.
It does seems possible that they could have supported this use case, to allow more than one player to be "signed in" on a given device, and then the game could just present a "PlayerA", "PlayerB" button to choose who's playing, instead of having to run the Game Center app to do the switch. But I imagine this use case wasn't a super high priority. (They'd rather have each of you playing on your own devices. And in fact some services like ScoreLoop keep things simple by enforcing a single player per device, period.)

Game Center API + In-App Purchases API = Two different user accounts for a single app?

If I have an app that supports Game Center and I'd like to provide Achievements for completing a puzzle pack that's sold as an in-app purchase, how do I sync the iTunes account that's being charged for the in-app purchase with the Game Center user account that's doing the buying? As I understand it, they're two separate user accounts that are accessed in two different locations (The Game Center account is accessed in the Game Center app and the iTunes account is accessed in the Settings app).
How do I avoid this from happening...
Game Center Player1 logs in, runs my app and purchases a puzzle pack
Game Center Player1 logs out, Game Center Player2 logs in, runs my app and plays to completion the puzzle pack that Player1 purchased and Player2 is awarded the Achievement.
Game Center Player2 logs out, Game Center Player1 logs in and finds the puzzle pack he/she purchased as already completed, so Player1 is unable to gain that same achievement.
Am I misunderstanding something with how these user accounts work? If not, is there a way to sync a Game Center account with an iTunes account as players log in and out of my game? Is there any kind of a work around for this problem? This seems like it would be a fairly common issue with any multiplayer games that sell content.
Thanks so much!
That is a good question. :) As far as achievements go, I guess you could store them on the device with the playerId from the logged in GKPlayer, and once an achievement has been finished for a logged in player, you synch with Game Center.
As far as synching iTunes and Game Center accounts I really don't know. Usually you store some information on whether a purchase has been made (i.e. a feature available) on the device. Would it be logical that using that feature (or being allowed to use it) should be device dependent, not GC user dependent? But then what happens if someone uses their account to just download your content again and again to their friends' devices?
Hmm... I hope some other people will share their thoughts on this. But I found that Game Center questions receive very low views and answers :(
So here's how I'm going to do this, it's actually a fairly straightforward approach. I'm going to locally track users progress in the purchased puzzle packs using core data, since it's quick to get up and running. Each time a new GC user logs in, I'll create a new user object and track their progress in the puzzle packs and report the achievements in GC when needed. When that GC user logs in later, I'll just adjust the state of the puzzle packs to match their current progress defined in core data. This way, any iTunes account can purchase the puzzle packs and they'll inherently be available to anyone using the device. Whenever any GC users log into GC and play my app, they'll all have access to the same purchased puzzle packs, but their progress and achievements will be maintained independently of other GC users.
If GC isn't installed on the device, I can disable all GC features and just init the app as tho there's only one default player.
Should be simple to do.
I am trying to come up with the solution to resolve this issue as well. If using the server product delivery mode, the problem could be largely resolved. The application sends the purchased items to server;sever deliver the item to application after checking credentials. There are some corner cases I still don't know how to resolve, basically to handle the case when the whole flow is interrupted, which depeneds on the implementation of IAP. Still not 100% sure yet.
Could you keep a record on the phone about which achievements have been bought by particular users, and then check which user is on and either enable or disable the purchased content - you'd have to have a means of keeping track of different players progress (I can see potential problems where a user might not be logged in to GC, etc etc). I haven't done this yet, tho I'm planning it for my next game.