There are two decisions to make timers, with "update:" and with actions.
But i need a timer that could continue even if the player close the game.
So when player comes back to game after a certain time, his progress could be saved. Could i use CFAbsoluteTime to make this?
You should look at the Date/Time instead of in-app timers for this purpose.
Essentially, you need to track the time passed between launches of the app. You can do this via storing the Date in the user defaults when the app is closed, and comparing it to the current Date when the app is openened the next time to figure out how much time has passed.
You may want to look at using an external clock, like grabbing the time from a website, this will prevent people from simply changing there clocks to alter time. (This will not however prevent people from altering the DNS to go to there own web servers, but will most people go through that trouble for a simple game)
Related
In my game I am using device time for timers and I want to prevent bots and cheats such as changing game time during No Wifi or offline gameplay. How can I achieve this?
Depends really. If putting the time BACK is the issue, then you could store a 'latest time' and check the current time is greater than it. Just keep the stored time up to date during online play and check when offline.
If putting the time FORWARD is the issue then you could just store a counter somewhere from the start of the game, instead of using the realtime clock.
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!
I am working on a casual game with some improvement over time, much like TinyTower.
But the biggest flaw in TinyTower (and all respect, its a cute game) is that cheating is too easy. The game relies on the device time, so when it says that "this is done in eight hours" you just set your clock eight hours ahead, get the thing, and then turn it back.
Now, I need to make sure that this isnt a way people can win in my game. I had one idea that i could crossreference the system time with the server time, but I can't rely on the connection being open, since offline play is an option.
I could also set up a sensor indicating if the OS time suddently was before last-played-time, you would earn an invisible cheat-suspicion counter. Three of these, and the game would reset, and mark you as a cheater.
The final option was to simply not care, let cheaters be cheaters. But if I am to have a competative element, with hoghscores and such, i really need this to work.
So... The question is this:
Does anyone know a safe reliable way of detecting how much time has passed since last time a user last had the app open?
A few ideas:
1) Have the app always keep track of current-time vs. last-closed-time. When you see it go backwards, increment a counter in all current saved games, and reject high scores from games where this counter has a sufficiently high value.
2) When submitting high scores, submit the device's current time. If that's sufficiently ahead of the server time, reject the high score.
3) When starting a game, check the time against the time at which the current version of the game was released. If the user is supposedly starting a game before the game was released, complain.
The app delegate is notified of significant time changes. You can catch these calls to applicationSignificantTimeChange: and watch for significant forward or backward time jumps.
Of course, that only catches changes that take place while the app is running. You can also save the time last run in the NSUserDefaults and check it next time you start up for significant backwards time jumps.
About all those solutions, what if the user goes to another country and the timezone changes and goes into the past or future?
we are creating a location-enabled app where users use this app to record certain events in the field.
The important part of the event data is when an event happened. This is no issue when user is online, but we also support situations when user is offline (by remembering & later syncing events).
There could be situations when users are offline and they change the time on the phone, so that event times are wrongly recorded.
So, what would be the best way to ensure we get a correct time, independent of user actions, given that device could be offline. Some ideas:
GPS time. Is it possible to acquire it?
Tracking system time changes made by user?
Any other idea?
Note: time does need second accuracy, approximately minute accuracy would be ok.
Note2: we are creating mobile apps for Android and iPhone, so I'm interested for generic solutions and also solutions that are specific to any of those two platforms.
I, personally, wouldn't worry so much about this scenario. The liklihood of someone intentionally changing the time on their Android (which periodically throughout the day syncs to a time server automatically) while offline seems low to me. That being said, the only way I could see compensating for this is to keep a service running in the background that keeps a running tally of the seconds passed since recording the location data offline. Once uploaded to your servers you could use the elapsed seconds to calculate a time offset from current UTC time. It's an awful lot to go through, but it would work.
GPS time is an interesting idea, but Android allows users of the SDK to send mock locations to their devices. I'm not sure you could reliably track changes to system time either, and even if you could you'd be capturing them after the fact without the current real time as context.
We use GPS times in our app for very similar reasons. Since our users are in different time zones and we want local times, we define from our server what time zone they are in at installation time (they don't move very far). Hadn't thought of the mock GPS locations, but you would need to be a fairly advanced user to do that.
I have an app that requires me to take an action after some period of time. For example, if an user hasn't been inside the app in few weeks, when the user eventually starts the app, I have to ask them to put in a special code that was given to them when they installed this app. (this is an in-house app and i am being required to do this due to security concerns)
I am using the [NSDate date] method to retrieve the date when the user logs in and save it into a database. I compare this saved date next time they open up the app and see how long its been since their last login. The problem is that [NSDate date] gives the time that is effected by the time settings that can be changed manually by the user in the native settings app. As you can probably tell, this causes lots of problems to my situation. If the user is suppose to be put the special code after 3 weeks of inactivity, he can cause the app to show this screen by modifying the time in the native settings app or worse, get away from it by setting the time to a previous date that will be within 3 weeks of his activity.
Is there a way to get the "system time" instead of the "user time"? I have looked into mach_absolute_time() but this gets reset after restart of the device. Since the time of inactivity I will be comparing against is pretty large, chances are device would have been restarted by then. I also thought of using network connection to get the time from servers outside the app, but lots of users won't have access to wifi where they use their iPads. That will be my last resort solution if i can't find anything else. Because of their location during usage, I am trying to use everything on the device itself.
Am I overlooking something simple here? this seems too simple of a problem to not have an answer. Please guide me toward the right direction. Thank you in advance.
Why not query a remote server for the time - lots of NTP servers about or just make a simple HTTP request to a php script on your own server. Of course if your app is likely never to be connected to the internet that could be a problem, but once you have a 3rd party time its quite easy to guess if the user has been playing with the clock.
If this is an inhouse app (so you aren't constrained by Apples approval process), you could mark your app as doing some background stuff (voip or receiving location updates), so that the app will always be active and you'd be able to update some sort of an "unused" counter. Voip app will even be restarted by the OS after device reboot.
But of course it'll drain the battery somewhat.
Either: make having the actual time an essential feature of your app. This way the users will have a need to keep the time of the device current and can't go back three weeks
Or: mark the code as expired and save this information before the app informs the user. This will stop most user from setting the time back. Most will try once or twice, see that the app stays disabled and will give up.
You can also save the timestamp of the last successful execution and if that is more than a reasonable time frame in the future (remember summer/winter time) then consider it a "hack attempt". Put a CRC check (or whatever obscure idea you come up with) on that timestamp and save it too and you will stop a large number of script kiddies.
You can never stop the diehard hacker who search actively for every trick you might have put into the app. Just focus on the "average" user.