I'm planning on venturing on making a single player action rpg in js/html5, and I'd like to prevent cheating. I don't need 100% protection, since it's not going to be a multiplayer game, but I want some level of protection.

So what strategies you suggest beyond minify and obfuscation?

I wouldn't bother to make some server side simple checking, but I don't want to go the Diablo 3 path keeping all my game state changes on the server side.

Since it's going to be a rpg of sorts I came up with the idea of making a stats inspector that checks abrupt changes in their values, but I'm not sure how it consistent and trusty it can be.

What about variables and functions escopes? Working on smaller escopes whenever possible is safer, but it's worth the effort?

Is there anyway for the javascript to self inspect it's text, like in a checksum?

There are browser specific solutions? I wouldn't bother to restrain it for Chrome only in the early builds.

Apoc, right now I just have a proof of concept and I haven't implemented any kind of persistence - but I plan to implement some DB persistance in first builds and/or local storage so that players cant just keep playing from where they left. Yes, Valdmond I played my share of Diablo back then. But i'm not building a competitive multiplayer game, or a full flagged AAA. Byte56, I'm not concerned on stealing my code (who would want that crap anyway?)
–
Billy NinjaSep 20 '12 at 17:18

unfortunately, you have to go the diablo 3 path, if you are really concerned about hacks/cheats
–
Noob Game DeveloperSep 21 '12 at 12:23

6 Answers
6

The short answer is you can't do it. Anything that runs client side, especially from source, can be modified to defeat your tactics trivially. If you put in place a client side checker to look for abrupt changes, a user can just disable the checker.

The good news is that, generally, there is very little cheating on single-player games. The only major exception being for games that have large "youtube highscore" communities like Line Rider, where players compete with each other over YouTube.

If you are aiming for that, or are just too stubborn to accept that people might cheat in the game, or are keeping high-scores yourself (which is a form of multiplayer) then what you must do is all of the calculations server-side. Yes, everything that matters. You can't even repeat the calculation client side to try to give the user the score and then 'verify' it with the server because the user can then just disable the check and disable any system that ensures there are checks.

I wish there was a better answer to this, but there isn't.

That said, there are things you can do to make it a little harder to cheat. They will not stop anyone serious from doing it and releasing a toolkit to cheat, but it will slow them down:

Minify and Obfuscate your JS, which absolutely will make the code harder to read. You can de-minify and sort-of de-obfuscate but you can never get back the right variable and function names, nor comments.

Bake in values with a different language. In this case you can use PHP or other server side languages to handle static setup variables. If the jump distance is always supposed to be 2 spaces, normally you'd define a jump distance for the player object. Don't, handle that with PHP so that the JS source ends up with 2s plastered all over the code in a million places. This has the happy additional side effect of being able to speed up your JS too.

With some practice, you'll get proficient with the mix and you can even custom-build your JS for each player. Which is another way to prevent cheating. If each player's code is different somehow, then it is harder to write a cheat that can be part of a toolkit.

Finally, you can checksum the source based on the player's identity. Say their IP address and/or username. You know what the player-specific version of the JS will be, you can bake in a checksum and require that it be the same on the other end. Easy to disable like any client-side JS, but once again makes it a little harder to make a toolkit.

So. As you see, it is probably not worth it to go this route. It is hard. Requires a lot of really silly coding practices to do, and is ultimately still relatively easy to defeat. You'll need to do all the calculations server-side to prevent cheating. Or let go, and accept that cheating will happen.

The line rider example is actually quite trivial to do server-side, by letting the user upload the map he/she has drawn and calculate the score. But games like arcades are nigh impossible to calculate the score server-side without extensive work.
–
orlpSep 21 '12 at 12:13

@nightcracker You are correct, however even with something like Line Rider, if you only check after the game is done, the video has been made and the YouTubes already duped. You should upload the map when the user goes to hit play, calculate the path which is trivial, and then send that back. The game shouldn't be capable of calculating the path. (If we are talking about making it cheat proof, which that game is not. It is just simple enough that cheating is obvious to its fans.)
–
DampeS8NSep 21 '12 at 12:51

I had an idea for a measure you could take to prevent/reduce cheating (in addition to other answers). You could have it set up so that the client is not given all the source code at one time, rather that every time the client wants to, say, purchase a new item in the store, that the client would have to send certain information to the server, and only recieve all the information for whatever they are purchasing if the information all matches up with what it's supposed to. If it doesn't, the server blacklists their IP or something.

You could use this in conjunction with what Dampes8n said about using different source versions, that if you can figure out a way to generate a lot of different versions, so that each user would be running an entirely different source version each time, that failing the check blacklists that source version, too, that it won't ever give out the correct item info for that source version ever again.

The main reason this would be effective is that if a hacker doesn't get the hack right the first time, this would make it much harder for them to modify the hack, because every time the hack doesn't work perfectly, they have to change their IP and write the hack all over again for the new source version.

I'd be careful. The last thing you want to do is accidentally perma-ban a paying customer.
–
John McDonaldSep 24 '12 at 19:36

@JohnMcDonald True, that. Perhaps just killing that source version. That way if they accidentally trigger the trap, they just have to refresh the browser, while still making hackers recode all their hacks.
–
AJMansfieldSep 24 '12 at 19:59

unfortunately, you have to go the diablo 3 path, if you are really concerned about hacks/cheats. if you are not, then basic checks you must do or its strongly advised to do.

buy checks - If I am buying something, I should have enough gold

sellchecks - If I am selling something, I need to have that item in my inventory trade checks - same as sell weapon

equip checks - If I am equipping a weapon, do i have/own it?

damage checks - If I am attacking something (enemy), I can't hit more than the maximum damage my weapon could(here you should not expect the client to tell which weapon he
has used because it should have been persisted earlier)

crafting checks - If I crafted something, do I have all ingredients/components required?

... and so on

1 point is little bit tricky is the hero's position, since you are not much worried about it you can leave it, but its better you do that too with a minimum check like one below

I am at place1 @ T1, I am at place2 T2, what is the minimum time it takes to travel from place1 to place2 and it matches my T2 - T1. You can have mapping of this from small to large depending on the map size. You should have list of at least major areas like, NPC - boss, NPC - enemy spawn area (not necessarily exact location)

Hope this helps, it sounds difficult but you need to learn to make real working games

Great answer! I was writing a question on how to implement server checking, just to measure roughly how hard it is to implement server checking. You see, I don't wanna waste dozens of hours implementing a MMO-like backbone and at the end of the day it's still easily cheatable just by overriding some client request parameter or something like that. Or simply overdo what was supposed to be a simply fun game -waste effort on security instead of delivering more cool features or polish things.
–
Billy NinjaSep 21 '12 at 13:12

Well, a good place to start is to use the Object.freeze function (which will enable protection against object patching).

This "prevents new properties from being added", "prevents existing properties from being removed", "prevents existing properties, or their enumerability, configurability, or writability, from being changed"; any changes to the internal state should be done through accessors. The following example works on chrome (should work on firefox, I dont know about IE though...):

Even this will only slow a determined cheater down. If nothing else he can steal the source, host it on his own machine, and remove the freeze code, and then use his hosts file to trick his browser into thinking the new page is the old one, reconnecting it with the server.
–
DampeS8NSep 20 '12 at 14:58

I already answered a question like that here, and I'm sorry to tell but:

I wouldn't bother to make some server side simple checking, but I don't want to go the Diablo 3 path keeping all my game state changes on the server side.

Is the baddest thing you could have say here.
If you wanna do an "anti-cheat" engine, you'll have to do that. You can add anything you want client-side, to facilitate the server-side work, but you must never trust the client.
All Logic you have must be at least server-side. You can reproduce it client-side if you want, but no client-side only solution will do it.

And by the way, if you wanna find the weakness of your program, don't obfuscate it, let people see your code and tell you "here, you have an issue".

That's good for you, for your code, for your users and for the community.

+1 for Server authority, it just doesn't work if you try to trust the client...
–
ValmondSep 20 '12 at 14:55

It is dangerous to reproduce things client-side. Be careful with even that, because if everything is replicated client-side, the user can cheat by disconnecting the checks with the server. They can then play the game, record a video, and become a YouTube star. This is only applicable to single-player games, which this game will be.
–
DampeS8NSep 20 '12 at 15:05

When I talk about client-side, it's for "movements calculation", "collisions" etc... This can be done both sides even for a multiplayer game. The server-side calculations must always be considered prioritary, but this can help when there is server latency to also have it client-side. But for everything that is "check cheat" logic, then I agree that everything should be server-side.
–
dievardumpSep 20 '12 at 15:14

Yeah, I got that. But I'm doing the project as a hobby in the little free-time that I have. Doing that kind of server checking would the complexity of the project by a lot, making it nonviable. Well, I'll keep moving with the project knowing that, and if it start to get bigger and serious than I could come up with some serious server side controlling, probably with Node.js.
–
Billy NinjaSep 20 '12 at 17:33