Advertisement

What is the most conventional way to handle highscores for different logins

Started by April 20, 2015 06:16 PM
5 comments, last by coffeecat 9 years, 8 months ago

So I have this game that supposedly keeps highscores and uploads them to an online leaderboard. I would also keep a local list of highscores in the device. The thing is, my game would involve a user login, of course (maybe link to Facebook, or using Swarm, I have yet to decide for that).

My plan is for the game to be playable even without an account logged in (Guest player). Highscores will be kept locally but it will never be uploaded on the leaderboards.

I can't really find the proper words to express my problem so I'll use the following scenario:

If for example, a person tries my game and played for the first time without logging in because they don't want to link their Facebook yet to a game they aren't yet familiar with. They kept on playing the game and then made good records then decided, "hell yeah I should login".

Their local scores got carried on to their account and then they instantly appear on the leaderboards (it's their scores after all).

But what if someone else borrowed the phone and linked their own account? If the local scores would get carried over, they would be technically stealing his scores.

But if I take the other approach on not carrying over the scores they made while not logged in, wouldn't it be annoying for the player to see his scores get practically reset to zero once logged in? I mean I also need to provide a motivation for the player to login, right?

So my question is, in this situations, how does an experienced developer handle these data? Or at least how is this conventionally dealt with?

This could also be applied to Achievements as I'm also planning to implement that system.

As a side question, when talking about persisting data I mostly read about using SharedPreferences. But aren't shared preferences easily editable by hand if a user finds it? is SQLite not a viable solution as well? If not then what is used to store scores that are not easily exploitable?

Btw, I'm still at the planning phase. Won't dive into coding yet until I laid all the pieces down. I'll be using LibGDX as my framework.

So it seems like you've got a few concerns.

First, since you don't want to require an always-available Internet connection, preserving scores locally until uploaded to the server is not too bad. Just save the scores in whatever format is most convenient to you. This will work in all situations, from a user without an account to a user who has no phone reception inside their building.

To keep the file reasonably sized, limit it a reasonable size for your game. Maybe a list of the top 100 scores ever, and a second list of the best 100 games that have not been uploaded. Or maybe the top 10, or top 50, or whatever makes sense for your game.

The unreported scores list can have an associated account or a null/empty account if nobody was logged in.

If someone creates an account or logs I would check the unreported scores list to see if there are unreported scores without an associated account. If so, I'd prompt if they want to take credit for the scores. If so, associate the scores, otherwise leave them as a blank account.

When you connect to your servers, upload all the unreported scores with an account associated.

Finally, your concern about users being able to detect and edit the files. Yes, that is something users will do. They'll not only hack the values in the device, they'll also hack your data streams so they can send custom data in transit, they'll also freeze your program in emulators. It will happen. Some games will actually build a special page for those detected as cheating, such as jumping too quickly up the high score list. Progress Quest has a "Wall Of Infamy" where suspected cheater high scores are placed.

Advertisement

Best bet would be to use SQLite and have a local database file I think.

This way you could have 2 different databases. one of which keeps track of users with a user_id etc, the other which keeps track of stores and contains a foreign key linking it to the user table.

If you want to keep track of what records you have uploaded to the site just add another column to the table and every time you upload a record you change this value to '1' or whatever.

With regards to detecting who's cheated that's going to be another problem altogether, SQLite has it's own synchronization so you could in theory keep the lock on the database up until the user submits a score and then acquire the lock again? Just an idea but it might add that extra bit of protection and prevent most script-kiddies.

Game Development Tutorials - My new site that tries to teach LWJGL 3.0 and OpenGL to anyone willing to learn a little.

It doesn't need to be as complex as SQLite or a local database.

A plain old-fashioned flat file would work, with each line of the form: "##score## account".

Just use whatever format is easiest for you, whatever you have on hand.

@frob: I see. Never thought of prompting, tbh. I'll try to look into that. happy.png

Anyway, yes I have a limit to the displayed highscores locally. I'll be listing just 10.

Also, I am aware of how notoriously hard it is to battle against cheating. I just don't want to make something that your average user can tap into and edit with a simple text editor. tongue.png

Can I encrypt the save file instead? If so, which path should I take?

@emforce: Well its only the script kiddies that I'm worried about. My game needs to be popular enough to attract hardcore hackers in the first place. :D

Maybe after I finished most of the game should I worry about anti-cheating? Hmm..


Can I encrypt the save file instead? If so, which path should I take?

Sure. Encrypt the file, plus keep a separate digital signature of the file that you verify.

That will take about zero seconds for a script-kiddie to work around, because their device connects through wifi, which routes through a PC and monitors your traffic. They watch the conversation between the server, replay it with some new scores, and are suddenly the top score one one billion points.

You might think you'll just encrypt it. Perhaps thinking of adding SSL or HTTPS or TLS or some other network encryption? That's also defeated by the same software. Standard encrypted connections are defeated by MitM software installed by businesses, schools, and other organizations around the globe. Most do it because they want to scan the traffic for viruses and porn and such, but really the process is trivial and part of many tools. Tools like Fiddler can breeze right through that barrier. Yes the server controls one side, but the client negotiates the other. Since they control the client side, they can do whatever they want with the traffic stream.

They watch it once, then make exactly the same network request with a different score. Achievement Unlocked: L33t H4xx0r.

Or, if they happen to not already have their network configured for that, they can break it on the device. They'll run the program in one of the mobile device emulator images that come standard with the SDK, freeze the app and run one of many simple tools to take a memory difference searching for the score value. Within about 30 seconds the skilled skript kiddie can set the score to whatever they please.

Seriously, that only takes about 30 seconds. Go get Cheat Engine, run the game, enter the score in Cheat Engine. Run some more, enter the new score, game is hacked. Enter whatever score you want, you've got it. Or download L Spiro's Memory Hacking Software if you prefer software written by an upstanding gamedev community member you know you can trust to hack your game.

Or any of hundreds of other memory editors out there, all of them will happily hack your game in a matter of seconds with no deep understanding of how your game is coded, or if you use encrypted communications, or even if you run your game inside a virtual machine. All of them trivially broken in seconds with easy to use free tools.

Again, a few seconds of effort, Achievement Unlocked: L33t H4xx0r.

Really, the best approach I've seen to cheaters in simple offline games is a "wall of infamy" as mentioned above. It is self-contained on the server and activated whenever suspicious scores are reported. Make it really easy for anyone to put their name on the board since people will try to cheat just to be there, have it clean itself every two weeks, and be done. Similarly, the high score list cleans itself regularly, with old scores expiring themselves after 30 or 60 days.

Advertisement

Alright. Seems like there are a lot of things for me to digest about anti-cheating.

In the meantime I'll deal with the handling of Guest -> Registered user scores for now.

So based on what I understood, I should:

Record scores from the unregistered player.

When someone logs in and there are uncredited scores. Or just the highest score is uncredited,

I'll prompt the player if they want to carry-over that score to their account.

OR

From the beginning (first run of the game, or when a player logs out) I'll display a warning that any scores made without a registered account will not be brought to the leaderboards and that it is recommended for them to log in to take part in the leaderboards.

I'll have to decide between those two if which is a better solution and/or which approach better pleases majority of the players.

In any case, I'll have to hit the pen and papers again and start sketching the data flow. laugh.png

This topic is closed to new replies.

Advertisement