|sam2 on 2D Dynamic Lighting Demo|
|Sam on 2D Dynamic Lighting Demo|
|sam on 2D Dynamic Lighting Demo|
|Nathan Beam on Web 2.0 with Haxe|
|Sam on 2D Dynamic Lighting Demo|
Flash, Haxe, Game Dev and more…
So it’s been a while since my last post. Almost a year actually. The reason behind this is largely due to school. I just finished my last year at the University of Waterloo and suffice to say I have a lot more free time now. Another reason for my lack of posting is because I have been hard at work implementing a gaming portal for html5 games. The gaming portal has been going on for over a year now and there isn’t really anything too interesting going on there besides the features of the portal itself. 😛
In the past month I have been getting back into finishing up my game Zed – a multiplayer zombie shooter. This of course makes for some more relevant and interesting posts! In particular I have been implementing the multiplayer portion of Zed and I wanted to go over how I will be making the game more or less cheat proof without the need for expensive server validation or relying too heavily on obfuscation.
First I will go over what is normally done for “complete” cheat prevention in multiplayer games. That is to basically run the game on a server and have the server perform arbitration over everything. The only thing that the client can decide on is keyboard/mouse input. The good thing about this method is it prevents most if not all ways to cheat depending on the game. Auto aim is a good example of a cheat that can still happen on first person shooters with this setup. The problem with the server-arbitrates-everything setup is that running the game simulation on the server is extremely demanding CPU-wise especially if you have a lot of complicated physics in your game. It is for this reason that a lot of smaller companies (such as mine) choose different solutions to handle cheating.
The most common approach with flash games is to use “security through obscurity”. The idea behind this approach is to make it hard to understand the underlying game mechanics given the binary swf file. Techniques such as monitoring important variables, bytecode manipulation (SWFEncrypt) and packet encryption are all methods of obfuscation. The good thing about security through obscurity is it is usually relatively easy to implement and it will deter most of the people who want to hack your game if you do it well. But for those 1% of hackers who are knowledgeable and determined it is not enough.
For these 1% of people you need guaranteed security and, if you don’t want to spend thousands of dollars on server infrastructure, you will need to verify actions on the client. So if we don’t have a central authority verifying what is correct game play and what is incorrect then what can we do? The idea rests on the assumption that given any particular game instance you can assume that the majority of the players are not cheating. This may or may not be a good assumption, but in general there are more legitimate players than illegitimate.
So what you do is make sure every player has access to all information at every game tick. IE where every other player is, what keyboard buttons are down, where the mouse is, etc. With this knowledge every player’s own version of the game should behave identically provided there is no randomness. If someone’s game is not behaving identically then the other players will be able to gang up on the player and boot him out. Hold on though, this is a multiplayer game and packets do not travel instantly. If I am player A and I am running game tick 1500 then what if I haven’t received player B’s keyboard state for tick 1500? Well I could just pause the game and wait until I get the required information, but this will be problematic because even with a very low latency system you are still looking at 50ms or so round trip time for the packet. This will cause the game to operate at 20 FPS max in IDEAL situations. Not to mention that also requires you sending 20 packets per second which for flash with a TCP socket that may be too fast.
All that being said there is a simple solution to these problems. Look into the future. No, I’m not talking about the latest and greatest in quantum technology. Obviously we cannot look into the physical future, but what we can do is make the game run in the past so that our present time is the game’s future. Confused? Let me explain. A game evolves according to the player input (keyboard, mouse, etc). Normally the input is applied during the game’s next frame. To make the game run in the past we put a delay on the input and buffer it for X number of ticks. After X game ticks have gone by we then actually apply the input. Doing this in a multiplayer game allows for input from other players to be processed in real time as we have a nice delay of X ticks to receive incoming data as illustrated below.
In the above example X = 3 ticks. This means that as long as it doesn’t take longer than 3 game ticks to receive packets from all players then the game will run smoothly. For a game at 30 FPS this means 100ms which may or may not be reasonable. You can always increase X to keep the game running smooth! If you have played StarCraft before you should notice this is the exact system they use. The X variable is controlled by the network latency setting in the game options. If you’ve seen “Player John Doe set the network for extra high latency” what they are doing is increasing X to allow for smooth gameplay. Of course if you set this to the maximum setting the delay from you telling a unit where to move and it actually moving is increased which can be annoying. For a game like StarCraft this delay may be tolerable; on the other hand, if you are building a fast paced shooter then the input delay can feel very unnatural.
To get around this unnatural control feeling we use a bit of a cheat in Zed. Due to the fact that Zed is not PvP we don’t need millisecond accuracy for the other player’s characters. We run the player’s own character as the keyboard/mouse input is received and all other players X frames behind. This seems like a bit of a paradox, and there definitely are some paradoxical time issues that come up; however, Zed’s game mechanics allow us to do this safely.
Keep in mind this particular network implementation will not work for everything. When considering a game infrastructure you will need to carefully consider your game mechanics before decided on which path to take. Another thing to keep in mind is that this setup will only prevent cheating under the assumption that the majority of players are legitimate. Do not rely on this method as a silver bullet. Layered security is always a good approach for software running on the client.