As we started building services that talked to each other, we realized we needed to have some way of keeping track of what servers were up and available. For example, when a game is started, there needs to be one specific game server it is started on. What if there are several game servers running? How do we know what game servers are running to choose between them?
That was the original mandate of MISSIVE, our inter-service communication system. We needed a way to have services talk to each other, be aware that these services were out there, and send simple messages to each other synchronously.
A predecessor to MISSIVE was set up to use HTTP requests just like all of our other APIs, but we quickly realized that this didn't work very well -- HTTP requests only support a poll model, where information can only be learned if you choose to ask for it.
When servers are started or stopped, we needed to distribute this information throughout the existing servers, ideally immediately. Thus, MISSIVE uses a simple TCP/IP connection and a simple message format to pass messages. The primary implementation of this is done in Python, allowing our Python web services to communicate with each other.
After we built this system, we realized that something similar could be extremely useful within games. If a game can send a message whenever something important happens, this message could be received by another server and data could be recorded in a database.
Once data is in a database, it is instantly accessible to whatever web site wants to display the information. To this end, we've implemented a MISSIVE client for our game engine, so that data can be sent from within the game to whatever external server wants this data, and messages can be sent into the game from externally.
We tried to make as few assumptions about the game engine being used as possible. We started with a C++ interface that must be implemented by a game engine to be plugged into Sandstone.
Whenever Sandstone starts up a game, whether it is starting a game server or running a local game in the browser, it calls through this interface to start up the game. In fact, the implementations of this interface are themselves content packages.
So the entire game engine that is used is not pre-installed, it is downloaded and updated just like any other content. This allows us to easily push bug fixes to our engine, as well as have several games that run on different major versions of the engine all work at the same time.
The question, though, is why did we choose to build our own LOCUST game engine? Why not use one of the many existing 3D game engines there to build our games and then use our new technology to run them differently? The truth is that no engine really matched the requirements we had for a game engine. These requirements are:
It's surprising that most game engines don't work for the first two points. Most game engines assume that the working directory of the process is the location of the .exe file of the game and look up content from there. This simply does not work if the process is the browser process, and it could have done any number of things to the working directory. And this becomes a basic assumption of the entire game engine, meaning that #1 is not feasible.
The second point is often not the case either. Many game engines assume that the game is running as a top level window. Asking it to render under a parent window is not supported at all. Despite these issues, we have hacked a couple game engines to actually render in the browser using Sandstone. It was not elegant, we would never want to ship such a game, but it worked enough to show what was possible.
However, even if a game engine could render within a window, most game engines aren't built for #3 or #4. Most game content is built on a scenario or level basis, where an entire level is built as one optimized set of stuff. This does not make for any reusable chunks, and every level ends up needing to be downloaded separately. Finally, it becomes very useful to communicate data out of the game into the web services, and we needed a game engine that could do this easily.
In addition, we wanted to improve our game-building and modding capabilities, both to support Making History's lively modding community, and to provide greater development speed and power in our serious games work. We built on architecture we developed for the first Making History game, The Calm and the Storm, which allows game data to be set up from XML.
Our path to web-integrated, browser-based games has been challenging, and we are excited about the results: the upcoming release of Making History II, and the possibilities the platform provides to create and deploy new kinds of engaging, web-integrated 3D games.