I'm writing a game in javascript, and to prevent cheating, i'm having the game be played on the server (it's a board game like a more complicated checkers). Since the game is fairly complex, I need to store the gamestate in order to validate client actions.
Is it possible to store the gamestate in memory? Is that smart? Should I do that? If so, how? I don't know how that would work.
I can also store in redis. And that sort of thing is pretty familiar to me and requires no explanation. But if I do store in redis, the problem is that on every single move, the game would need to get the data from redis and interpret and parse that data in order to recreate the gamestate from scratch. But since moves happen very frequently this seems very stupid to me.
What should I do?
If you really, really don't want the overhead of I/O then just store the game state in a global object keyed by the game id:
var global_gamesate = {}
Then on each connection check what the game id is to retrieve he game state:
var gamestate = global_gamestate[game_id];
Presumably you already have a mechanism to map client sessions to game id.
Usually, game state is small and would hardly take up much RAM. Let's be pessimistic and assume each game state takes up 500K. Then you can serve two million thousand games (four million thousand users if we assume two users per game) for each gigabyte of RAM on your server.
However, I would like to point out that databases like MySQL already implement caching (which is configurable) so loading the most frequently used data basically loads from RAM with a minor socket I/O overhead. The advantages of databases is that you can have much more data than you have RAM because they store the rest on disk.
If your program ever reaches the load where you start thinking of writing your own disk-serialization algorithm to implement a swap file then you're basically re-inventing the wheel. In which case I'd say go with databases.
Related
I have a set of data associating zipcodes to GPS coordinates (namely latitude and longitude). The very nature of the data makes it immutable, so it has no need to be updated.
What are the pro and cons of storing them in a SQL database vs directly as a JavaScript hashmap? The table resides on the server, it's Node.js, so this is not a server vs browser question.
When retrieving data, one is sync, the other async, but there is less than 10k elements, so I'm not sure whether storing these in MySQL and querying them justifies the overhead.
As there is no complex querying need, are there some points to consider that would justify having the dataset in a database?
* querying speed and CPU used for retrieving a pair,
* RAM used for a big dataset that would need to fit into working memory.
I guess that for a way bigger dataset, (like 100k, 1M or more), it would be too costly in memory and a better fit for the database.
Also, JavaScript obejects use hash tables internally, so we can infer they perform well even with non trivial datasets.
Still, would a database be more efficient at retrieving a value from an indexed key than a simple hashmap?
Anything else I'm not thinking about?
You're basically asking a scalability question... "At what point do I swap from storing things in a program to storing things in a databse?"
Concurrency, persistence, maintainability, security, etc.... are all factors.
If the data is open knowledge, only used by one instance of one program, and will never change, then just hard code it or store it in a flat file.
When you have many applications with different permissions calling a set of data and making changes, a database really shines.
Most basically, an SQL database will [probably ...] be "server side," while your JavaScript hash-table will be "client side." Does the data need to be persisted from one request to the next, and between separate invocations of the JavaScript program? If so, it must be stored ... somewhere.
The decision of whether to use "a hash table" is also up to you: hash tables are great when you are looking for explicit keys. But they're not the only data-structure available to you in JavaScript.
I'd say: carefully work out all the particulars of your exact situation, and use these to inform your decision. "An online web forum like this one" really can't step into your shoes on this. "You're the engineer ..."
I'm writing a multi chatroom application that requires persistent storage of the conversations (ie new users should be able to see old messages). I'm using socket.io if that helps.
Currently, when a user logs into a room, my node app checks to see if someone has been to that room yet (and each room has a hierarchical parent, for instance the room called Pets may belong to North America since there'd be a separate European Pets room).
If this is the first time a person has been in the room for a while, it loads all messages from redis for that room. (Eventually redis stored conversations make their way into MySQL).
So I have a multidimensional array called messages["PARENT"]["ROOM"], such that messages["North America"]["Pets"] will be an array that has all the messages for that room. Aside from misunderstanding how arrays in JS work (as explained in this question: javascript push multidimensional array), it feels like I'm over complicating the situation. My reasoning for using the MD array was that it didn't make sense to be round trips requesting all the messages from Redis for a room that was active.
What would be the most logical approach to what I'm trying to accomplish? Should I just be using Redis and forgo this? How about some message queue or maybe a pubsub server? (I'm trying to not complicate this as it's just a prototype for a friend).
Thank you,
From an architectural point of view, this is a poor design. What if tomorrow you wanted to scale this application by setting up more servers? Surely these multi-dimensional arrays would be specific to each node instance. Decoupling the storage has its own advantages, one being scaling out - the storage is now shared among several servers. It all depends on what you want to achieve. You may also run out of memory if your MD increases in size, thus hampering your applications performance.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
[I know there have been similar questions about preventing cheating on high score lists, but no answer didn't really help me for JavaScript based games, so please try to think about my question, before telling me about similar posts. I ask about best practices because the JavaScript is always visible for the user and therefore it is not possible to prevent cheating completly, I just want to make it harder.]
I'm developing a JavaScript based game that works in the browser. I want to make a high score list that contains the user name and the score of all users. To achieve that the browser sends the username and the score to my server (via AJAX).
Submitting fake scores to this list would be fairly easy: One could take a look at the AJAX requests and then make an own AJAX request with a faked score. Using something like a token that has to be send with the other data is pointless, as it will be easy to discover.
My only approach, that would prevent cheating, would be to send a description of every user action to the server and calculate the score there. But this is not really practicable as it would be too much for the server.
I accepted an answer, but in case anyone has other ideas about how to make cheating harder, please create another answer!
I like to play cheat the cheater - something like using a token to authenticate the score that changes every time the update is called... but I accept the cheat score that gets posted using a duplicate token. Then I display that cheat score to only the cheater, so it appears that it worked, but now the cheater is seeing his results in a sandbox.
You pretty much answered your own question. If you want to really make it harder for users to cheat, send game log to the server, where you'll calculate the score.
You don't have to send all the events, just ones that affect result score.
There are some techniques, though, that may help you:
include signature in your request. Something like MD5(secret_key + params). Although, "secret key" will have to be in JS source, it will effectively protect you from simple request interception (see Tamper Data and Charles)
if it's a multiplayer game, accept scores calculated by clients and compare them. Cheaters will be pretty visible (assuming that the majority of users are honest).
you can set a score cap, an "unreachable" result. Everyone who posts score higher than this is a cheater. For example, speed typing game: no one can type correct text at 1500 chars/minute, even 700 is pretty damn hard (though achievable).
On score submit:
Request some token from the server, this should be time based and only valid for about 2 seconds
Only accept submits that include a valid hash of this token, some salt and the score.
This prevents manual tampering with the request as it would timeout the score. If you want to account for high-latency give it a little more time until the timeout.
The hashing function:
Scramble the hashing function inside packed code (http://dean.edwards.name/packer/ really produces nasty to read code) if you use jQuery or some other library just drop the hashing functionality inside the library file and it gets pretty bad to find, escpecially if you use a function name like "h" :)
Handling the score-variable itself:
Well everybody with a debugging console can change the variable on runtime when doing this but if you encapsulate your whole Javascript inside a function and call it nothing is in the global namespace and it's much harder to get to the variables:
(function() {
//your js code here
})();
I have had lots of thoughts about it and, eventually, decided to only have local individual highscores, so cheating is not really beneficial for player and not harmful to others. Yet my game is just a simple minesweeper, and there were people who complained about the lack of competitive table.
Option 2, is approach taken by WebSudoku - to show your place "among the people of internet". So you will not see any other results, and people wont see your results - but you can compare yourself to crowd.
p.s: And seriously - any kid with Firebug/WebInspector can easily hack your JS game and, eventually, to be able to reach very high score.
If you are relying on the client to send the final score to the server, then there is no way (afaik) to prevent a genius from cheating. But I think you might be able to prevent stupid people (and honest people) from cheating, so that only geniuses and their friends will dominate your leaderboards.
There are two ways I can think of
1.) "security through obscurity."
Come up with an algorithm that transforms simple scores into something else (and to transform them back). Then obfuscate it. Complicate it. Write a function that multiplies it by q and divides it by ralph. Apply a bunch of functions to it, and among the 5-15 functions that do random stuff to it, include one that multiplies the number by 19 ( a prime number ). On your server, check to make sure every incoming number (or letter) is divisible by 19, and decode
You have to write a bunch of complex code that transforms simple scores into something crazy-looking. You have to write a series of functions in the least-efficient, most spaghetti-code fashion possible. Use
One thing you cold do is to have a set of disallowed values. I.e., perhaps all points awarded are even. If anyone tries to submit an odd number, they are obviously cheating (and very stupid).
2.) time
You should be able to know when the user started the game. You should have a session started and record when they requested the page. Then you should also be able to tell when they submitted their score. And you should also know what the time series is for max points. I.e. can you get 5 points per minute, 100 per minute, minute^3, etc... If user submits more points than are possible during that time, they are cheating.
You could also strike a balance between server and client processing and make the client should send progress update every x minutes by ajax. And if it fails to report, you assume it's been compromised (much like in Bond movies, when he's infiltrating the enemy's lair and he snaps some guard's neck. When the guard doesn't respond to his next 10-minutely check-in, the alarms will go off).
If you've ever played Zynga Poker, you've probably seen what happens when someone at the table has a slow internet connection.
Depending on the nature of the game, you could use other players to verify the results. In simple games this works great, on others you have to be clever and develop many aspects around this feature. E.g. sometimes is possible to replay and verify results based on logged actions. This trick works specially well for Human versus AI, as long as the model is deterministic.
Another option is redefining the score concept to be more user-centric, this is pretty easy to implement, but tends to be hard to devise, and only applies to a few categories of games.
Purely speculative approaches are also possible, it's sometimes pretty easy to know when some parameters don't fit. It would not avoid cheating, but would moderate it a lot.
The most complicated part is getting a small enough replay log, but since most data isn't random (except for player actions, which, actually aren't that random because depend on the game) it's essentially a matter of getting the design right.
Also, if gameplay is extended enough, for action games and the like you can get a lot of compression from doing some approximation, merging (e.g. motion vectors), and clipping uninteresting stuff.
Ideally you would send your entire event log to the server for checking. Perhaps you can implement a heuristic so you can easily determine if the score is within a set of bounds. For instance, if the total game time is 5 seconds you might expect a much lower score than with a much longer game time.
Alternatively, you could choose to manually check the event log for really high scores (the overall top-X, which should be fairly stable).
You will need a seeded random number generator if you're doing anything with randomness (like random events). Which might be tricky if you hadn't already thought of it.
You can find many more resources but it really just boils down to server-side checking. JavaScript is not unique in this, but likely easiest to exploit because you not only see the client-server communication but also the client-side source code!
HTML5 Multiplayer Game Security Solutions
http://lanyrd.com/2011/jsconf/sfggb/
Games like Starcraft only record the mouse clicks and key presses. The actual commands are then simulated. I expect 'Worms Armageddon' to do something similar but their random events (like the bounciness of bananas) aren't seeded properly so in the instant replay you might get a different result.
You could imagine something similar for MMORPGs. The server calculates your position based on the keypresses, the client merely tries to give a good early interpretation but you may warp around when you're lagging because the server will place you elsewhere on the map because it didn't get the keypress events timely.
If you attack something, the server will check if you're close enough and how much damage you can expect to deal with current stats and equipment.
Record key points in game, then score is submitted with these key points. When people look high scores, they can also see overview of played game, if it looks like it is impossible to play like that without cheating, then people can report these suspicious scores to admins.
I used a system using a time based request having 3 parameters
req number, curr time, score
The req number is returned from server in the response to the update score request , each time this is a new random value.
The curr time is calculated not from computer clock but from start of game and is synced with server using an ajax request.
Update score request is sent after short intervals (around 30 sec max).
Following checks are applied on the server
Time is within 10 seconds range from the server clock.
there has been not more than 40 seconds since the req number was sent.
the score change sent after 30 seconds is possible (within 2 x humanly possible range)
Score is updated only if the above checks are passed or the user gets a disconnection message :(
This is simpler than most methods and works out to eliminate all casual hackers (well, unless they read this and want to go to the trouble of updating score quickly or making a script of their own).
If not cheating is more important than the game itself, try to construct and present your game in a way that it looks like finding the solution to a math problem. So the server will give an instance of the problem to the client (example A: a chess board about to be won in 3 moves, example B: a geometry dash randomly generated level) and the user will have to solve it and post back a solution (example A: the winning moves, example b: the exact timestamps and intensity of jumps to avoid obstacles)
With this approach, it is key that the server doesn't send the same level twice, or else the cheater can plan and "design" his solution in advance. Also, the game information must be randomly generated in the server and not sent via seed, or else the cheater can fake the seed and design his solution with time.
The given time for valid submissions must be also tracked in the server so that they will only have "playing" time and no "designing" time. If the cheater is good enough to design a solution as fast as honest players can win the game, then they are talented enough to win the game honestly and deserve their points.
Back in the server, you will need to check that the submitted solution is valid for that instance.
Of course this approach requires lots of extra work: More instances of games (ideally infinite and non repeating), server side generation, server side validation of submissions, time caps, etc.
Note: I know these approach was already suggested in multiple solutions some years ago, I wanted to add my humble contribution.
First of all, I understand this question might be off topic and not in scope of stackoverflow but I still decided to ask since I don't know any other better place.
My question is, if I make an online game based on game engines written in javascript eg CreateJS. The game code is going to be run on the clients machine and since javascript is interpreted, it is viewable by the client.
So if a mutliplayer game is being made where users can compete against each other, what measure are taken to prevent cheating. I'm asking because since the game source is viewable, anyone can simple modify the game source and potentially cheat.
Edit: For the idea of the game, lets make one up which is very simple. Imagine we are making a game like FlappyBird or a game where the further you go in a linear map, the more point you stack up.
At the end of the game, your score is submited via a http request.
Now what is stopping a user from editing the game which causes the points to stack up 10x faster? causing a higher score to be submited?
Edit 2: Or what is stopping the users from submitting a request containing false scores via cURL without ever having to play the game?
Multiplayer games prevent cheating usually by simply verifying the game steps, rather than just the complete game output. Since all other players need to know what other players do, you will have to tell the server every step of the way and let the server "simulate" the game and check if these steps are actually valid or not. The only way to cheat in this case is by writing an AI in your browser that will then produce a feasible set of steps coming to a good result.
You also will have to send these player steps to everyone else. Since in a continuous environment players can perform so many actions per second (e.g. move and turn), you want to make sure to minimize the amount of updates to be sent. E.g. when walking in a straight line, World of Warcraft,for example, only sends an update every 500ms. They might also do not necessarily simulate and verify every single step you take, but only every X steps to avoid people running through walls or jumping over entire buildings etc.
Please note that any fast-paced game will not work well when using AJAX calls. Just setting up a connection can take many times as long as just sending a packet through an established connection. That is why you want to use Websockets in that case.
Of course, minifying and obfuscating your code will put some stones in the ways of a cheater, but depending on the vulnerabilities of your system, they might do very little, since it is usually very easy to find the code that takes care of sending and receiving packets or other core aspects of your game, no matter how well obfuscated it is.
Since you cannot believe your clients, you should make an authoritative server and dumb clients model;
That articles are full of gems for who want implements an multiplayer game
the game state is managed by the server alone. Clients send their
actions to the server. The server updates the game state periodically,
and then sends the new game state back to clients, who just render it
on the screen.
From your point of view, what happened is that you pressed the right
arrow but nothing happened for a tenth of a second; then your
character finally moved one square to the right. This perceived lag
between your inputs and its consequences may not sound like much, but
it’s noticeable – and of course, a lag of half a second isn’t just
noticeable, it actually makes the game unplayable.
So you must implement a Client-side prediction and a Server reconciliation
If you develop a "multiplayer" based game, than you should persist the data on a server, centralized, accessed by ajax within your game.
And you're right, someone could potentially "cheat" by overwriting your code with firebug for example or Greasemonkey before you send your data via a http request (ajax).
In order to prevent this you could load your ajax code for saving data dynamically. You can only prevent it by making it more difficult to overwrite your code. Use for example one-way-token in a virtual session, like the token used in OAuth, like a ticket for a ajax-call. Every other call without the right token should be refuted.
I'm creating a tower-defense game in javascript and want to have a high score and other multiplayer interactions. Probably have a couple of players start the game at the same time and tell them how fast the other guys are going and that kind of stuff.
I don't know how flash games send their scores or events to make sure the information that each client is sending is actually correct and not just someone sending incredible scores. I remember a couple of years ago when flash games started having high scores, it was very common to see unreal(hacked) scores and well... that's pretty weird not; so what is the secret here?
People will always be capable of cheating at games... the best you can do is make it difficult to cheat. Scores for old flash games were very easy to rig because the score would be submitted via an HTTP request. Sniffing the traffic would reveal the submission URL and what variables needed to be passed in order to update the score. I hope that it has since changed.
If I were you I would make use of some error checking code that will be passed along with the final score in order to verify that the score is legitimate. The error-checking code algorithm should be difficult to determine from a score (if the person is sniffing it). The javascript should also be arbitrarily obfuscated. This is nowhere near ideal but it should deter a good portion of the cheaters.
The best practice I have seen for this is to do sanity checks.
Record the time elapsed, enemies killed, etc... check the score with the data, and see if they add up.
Its primarily though obscurity these days. You would generally assign a unique token per game, and form some kind of hash of the score and token and validate it on submission (or continual submission, validation and token-switching throughout gameplay).
It will be a lot harder for you to do via javascript.
Use a combination of the following tools which are used to commonly prevent fake score and progress reports.
Obscurity - compress and obsfucate the logic that calculates the score string. Distribute it and make it difficult to reverse engineer.
Randomly changing keys - When your game begins, let the javascript request a key which can be used to encrypt the string containing the high scores, etc. The server should also have the private key which will allow you to decrypt the message.
Sanity checks - While a user might change the score, make your requests also contain the number of kills, etc, which are known bounds. The server will check the hashes and make sure that the data is valid.
Consider using a comet server - Since you'll be feeding realtime data to both clients, you'll be better off using a comet server like Orbited or Jetty. This will enable streaming without crashing your server.
Make it frustrating. 'nuff said.