Web games tech for beginners

I have been recently trying to understand how multiplayer online worlds work, from the basic technical matters, to higher level game mechanics. This is a new area for me, and seems a bit of a black art so I thought I’d write some of the things I’ve discovered here for others following a similar path, or more likely, so people can tell me where I’m heading in the wrong direction.

I had to start with the complete and utter basics (as a recovering computer graphics guy) and to start with these games are split between a client and a server. The clients I’m interested in run in players browsers, and the server needs to be on a machine which is running all the time to provide the persistent world, and record the changes people make.

In terms of languages, when considering the client you are quite restricted as to what you can use. Every browser has a Javascript interpreter, and most people have flash – sidestepping the hot potato I’ve already written a bit about. Luckily for flash there is also haxe.

On the server it’s completely up to you what you use, as you can run pretty much anything in a webserver. I’m using a racket servlet so I can use Scheme.

Sending requests from the client to the server

In a game the client needs to issue requests to the server while the game is running, in order to get realtime feedback on what is going on. As far as a browser is concerned, it does this first to get the page, but as we also need a way to do this after the page has loaded. This technique is usually called AJAX, or “Asynchronous JavaScript and XML” and was a hot topic a few years ago due to the rise of Google maps and other websites that make heavy use of it. All it really means is that you can send a http request from a script running on a page, and get a result from the server. I’m skipping the XML part, but I think it’s the same idea.

In JavaScript you can do this with the popular jquery library, where a request looks something like this:

$.get("page.html", {argument1: 302, argument2: "hello"}, 
function(data) { do_something_with(data); } );

The page and arguments will result in a call to a url like this:

http://your-site.com/page.html?argument1=302&argument2=hello

When it’s returned, the result data will be passed to the function you pass in as the third argument. Notice that this function will be called “at some time in the future” – as it’s asynchronous. This means your script can do other things while it’s waiting for the data.

In Haxe you need to use a combination of things to do the same work:

// setup the loader
var Loader:URLLoader = new URLLoader();
Loader.addEventListener(Event.COMPLETE, CompleteHandler);
...
// define the callback for when the request has finished
function CompleteHandler(event:Event)
{
    DoSomethingWith(Loader.data);   
}
...
// set off the request
var request:URLRequest = new URLRequest("page.html?argument1=302&argument2=hello");
Loader.load(request);

Although I’m stuffing the parameters on the the url string myself, there is a URLVariables object which is supposed to do this cleanly – but I couldn’t get it to work.

Security issues

One thing you might notice is that we don’t specify the root of the url anywhere in the code, and this is for a very specific reason. The client code is restricted to only sending requests to the server which has served the page itself. This makes it hard to run a client from a location not controlled by the same people as the server – if this were possible, for example, a third party would be able to write a client that acted like the real one, but used your identity to do whatever it wanted. This is called the same origin policy.

A related issue crops up if it is possible for people to enter text which gets shown in the webpage of the game on other people’s computers. The problem here is that it may be possible for a third party to inject some code that gets executed into the website that gets sent to a player. This could result in all sorts of mayhem, for example inserting dialogs that look like they come from your website to extract personal information. This is called cross-site scripting (shortened to xss). There is no utterly foolproof way of preventing this, but a simple approach is to filter out special characters (such as angle brackets) from the input from your game as they come in to the server.

A third issue for security is to be careful of what you do with the requests you get – as while the users are protected from being tricked into running an altered client that looks like it comes from you, your server can still have requests sent to it from anyone.

For instance, it would be the easiest thing in the world to design an elegant and simple interface that directly ran code being sent to a server – eg a request such as:

http://mysite.com/myserver?func=display&param=hello

Could easily, even indirectly be run by some code like this:

(apply func (list param))

Which immediately opens your server up to people sending it calls such as

http://mysite.com/myserver?func=delete-file&param=server.scm

And presumably much worse.

So it’s important to use some indirection to verify that the commands you are being sent make sense, and come from a limited range of options controlled by you. Related to this, if you have command that create new objects somehow – it’s a good idea to have some limits imposed, to prevent some troublemaker writing a script that fills up the memory on your server.

Sending data from the server to the client

The data you send back as a result of requests can be of any form, but there are some useful standards here. I’ve chosen to use JSON which is another web programming four letter acronym that stands for JavaScript Object Notation. We saw a Javascript object earlier on, as part of the request being sent out, but they are just associative arrays. Here is another example that might come back from the server:

{
    player-id: 43,
    text: "destroy all humans",
    numbers: [3, 42, 32, 4, 1]
}

This can then be evaluated by the client and turned into an object that can be inspected by the game.

There is a risk from directly running eval on the text that comes from the server – as potentially this too could somehow be subverted to contain some executable data, although this is quite unlikely, it’s best to filter the text. Luckily there are lots of libraries to do this – I’ve used json2 before discovering that jquery has a getJSON call that does this for you.

Tags: , , , , , , , , , ,

Leave a Reply