Al Riddoch
alriddoch@zepler.org
James Turner
james@worldforge.org
Through solid software engineering principles, reusable code, and Open Source peer reviewed development, WorldForge have developed protocols, tools and frameworks for developing large scale on-line game worlds. The Atlas protocol provides a solid, scalable, extensible, game independent protocol for on-line games, and aims to provide for generations of on-line games to come. The STAGE server framework provides a solid base on which games can be developed using the Atlas protocol. In introduction to the Atlas protocol is given here, with an explanation of its strengths for game development and demonstrations of its use in a working game, followed by an overview of the STAGE server framework's development. The challenges of large scale game servers are discussed, including database, networking and performance issues.
An operation has an argument list which usually contains one or more high level Atlas objects i.e. entities or operations. An example of an operation with an entity argument is a move operation, sent to an in game entity to indicate that it is moving. The argument would be an entity with the id of the in game entity that is moving and the attributes necessary to describe the movement. An example of an operation with an operation as its argument is a sight operation, sent to all in game entities when the move operation above occurs. The argument would be the move operation described above, which in turn has the entity that is moving as its argument.
42 An integer 32.85 A float "foo" A string [69, 24.8, "bar"] A list {name: "foo", height: 5.4} A map
This encoding has been designed for maximum readability, and is used for examples, and human editable data. Other codecs are preferred for efficient network transport, but Bach can be used when snooping the network traffic for debugging purposes is desirable. Other codecs that have been implemented include packed ascii, xml and binary.
The following Bach represents a high level object.
{ objtype: "obj", parents: {"pig"}, id: "pig_42", loc: "world_0", pos: [0.5, 3.4, 9.7] }
The opening { indicates that this is the start of a map message. The first attribute objtype indicates that this is an entity object, the second parents attribute indicates that it inherits from an object called pig, which in this case is an entity class. This means that this entity represents a pig in the game world. It is possible for an object to be derived from more than one definition or class, but this feature is not exploited in current implementations. The id attribute is an identifier which uniquely identifies this entity on a given server, and the format of the id in the above example is one used for easy debugging in development code. The other two attributes describe the location of the entity in the game world. The loc attribute gives the id of the reference relative to which this entities position is described, and the pos attribute specifies the coordinates relative to that reference entity. The ordering of attributes is arbitrary; the order given above is chosen for clarity of explanation.
The following Bach fragment represents an operation.
{ objtype: "op", parents: ["move"], serialno: 12345, refno: 0, args: [{objtype: "obj", id: "pig_42", parents: ["pig"], loc: "world_0", pos: [0.5, 3.4, 9.7], velocity: [0.0, 1.0, 0.0] } ] }
The basic format is the same as that of the entity example however in this case the first attribute objtype indicates that this is an operation object and the second indicates that it inherits from an object called move, which in this case is an operation definition. This means that this is a move operation, the effect of which is to change the location data of an entity. The move operation definition is one of a group of definitions referred to as actions. One of the most important attributes of any operation is the args list attribute. This can be considered analogous to the arguments of a procedure or method call, and usually contains one or more Atlas objects. In the case of a move operation, the first and usually only argument is a description of the entity to be moved, with at very least the id of that entity provided. In the example above, the reference entity loc, the coordinates relative to that entity pos, and the velocity of the entity are given. In addition, the parents attribute is included, to indicate that this entity inherits from the class called pig.
The result of this operation will be that the pig indicated is moved. In order for any other entities within the game to observe this movement, a sight operation indicating that nearby entities have seen something happen is sent to appropriate entities. The sight operation may look something like this in Bach.
{objtype: "op", parents: ["sight"], serialno: 12346, refno: 12345, args: [{objtype: "op", parents: ["move"], serialno: 12345, refno: 0, args: [{objtype: "obj", id: "pig_42", parents: ["pig"], loc: "world_0", pos: [0.5, 3.4, 9.7], velocity: [0.0, 1.0, 0.0] } ] } ] }
This operation inherits from the sight operation definition, which is one of a group of operation definitions known as perceptions. The attributes are very similar to those of the move operation, with some notable exceptions. A refno attribute is provided to indicate that this operation is dispatched with reference to the move operation. The first and only argument of this sight operation is the move operation given in the previous example and this is how the information about the movement is conveyed to the other entities. Sight operations with entity data as their arguments are requested by issuing a look operation, the definition for which is one of a group of perceive operation definitions.
A look operation typically provides a minimal entity description as its argument, to specify the id of the entity it is looking at. In order to bootstrap examination of the entities in the world, a look operation with no argument is issued. The result is a sight of the top level entity in the world, which can be examined to determine the ids of the rest of the visible entities in the world.
Two remaining operation attributes are to and from, used to specify the source and destination of operations. The use of the attributes internally to systems which use Atlas varies from system to system. In general from is almost always used when sending an operation from a client to a server, to indicate what server side object the client is using to invoke this operation. to is almost always used when sending an operation from the server to a client to indicate which server side entity the operation was received by. For example, when the client sends a look operation, it sets the operation from the character which it is currently controlling and it will expect the resulting sight operation to be to that character.
Cyphesis was used as the platform for the Acorn demo game. The game required players to create a character and take on the role of a pig farmer. The pig farmer would buy piglets from a trader, fatten them up using food discovered in the game environment and sell the pigs for slaughter at a profit, while avoiding obstacles placed in their way.
Scripts were written to define the nature of the entity classes required for the game and operation definitions were created for the necessary interactions. Information about these entity classes and operation types was integrated into the client software where necessary.
Acorn gameplay relied almost entirely on features and operations supported by the server core to implement its gameplay. Players controlled pigs by the client sending touch operations which drive the pigs through the forest. Predators relied on sight operations to identify pigs and move operations to chase them. Trading of pigs in the market place relied on talk and sound operations to communicate between the players and the market traders.
The game, developed in the most part by Karsten-Olaf Laux, Uta Szymanek and Alistair Riddoch was successfully release at LinuxTag 2001, and has been WorldForge's flagship product for the past year.
The critical components of STAGE are laid out here:
In a distributed model, one OOG server and a cluster of game servers collaborate to simulate the world. The inter-server communications are also achieved via Atlas.
In Cyphesis, changes to the world are simply sent to every client within a fixed, server determined radius; this model is obviously unsuitable as the number of clients and changes to the world increases. Also, it is desirable to enable entities not associated with a client to respond to events in the world.
STAGE calls visible world changes 'events', and any object interested in receiving them an 'observer'. Clients are observers, but other code can be too (for example, a door that opens in response to a talk event). To manage the transmission of events, each container in the world hierarchy tracks the observers it contains, and it's relation to other containers. For example, two rooms (each a container) may be joined by a doorway. When the door is open, events occurring in one room will be propagated through to the other. When the door is closed, visual events will be blocked (assuming the door is not made of glass) and audible events may be dampened. In an outdoor environment, the relations between containers are more arbitrary, but the basic principle holds. Thus the container model can be considered as a graph, with relations between nodes forming the edges.
It is possible (with some additional complexity) to make this model very sophisticated, for example giving sound events a direction, and modelling propagation through doorways, windows and solid materials accurately. While this level of simulation is some way off, the underlying model is general enough to support it, and the potential for increasing realism in the world is very high (for example, hearing the foot-steps of a character walking around in a room above another). Also, there is nothing in the design limited to audible or visual events : modelling psychic or magic events in the same way is intended.
The lowest level of the cache is the database system, which can be any SQL database; presently, MySQL and PostgreSQL are used for testing, and SQLite (an in-process, file based DB) is used for development purposes. Communication with the database is handled via Echo, which manages the serialisation of entities into SQL data.
Echo is a passive layer that responds to requests from the entity caching layer built into Shepherd. This layer maintains a reference count for 'active' entities, and the primary in-memory cache of inactive but recently used entities. The caching layer also manages preload requests to normalise the cache's use of Echo, and ultimately the database. This functionality is currently not well developed but is expected to be important as the number of entities rises. Fortunately, there is a very good spatial locality of access which makes various preload schemes viable.
In a distributed model, each server has it's own local entity cache. Similar to a distributed memory model, a given cache, when fulfilling a request for a specific entity ID, can query other caches in the network in addition to the database layer. A location based 'affinity' scheme will almost certainly be necessary to ensure that spatially related entities tend to reside on the same game server. Unlike distributed memory systems, where the pattern of access cannot be determined in advance by the operating system, we have the advantage of being able to locate 'busy' areas of the world on a single server, and ensure that transitions occur in places that are seldom visited. Thus, server allocation can be placed so that a city or town never spans multiple servers.
Note that the inter-server protocol for exchanging entities is also Atlas; however, the actual objects being sent contain server-specific data in addition to the publicly visible properties the client sees.
In the longer term, there is an alternative model for dealing with worker threads, which is to turn them into worker processes. This models is akin to how CGIs are implemented in a web server, in it's simplest form. A number of possible designs exist, such as maintaining a persistent process for each rule implementation, to avoid process creation overhead every time a rule is used. The IPC between the game server and it's rule processes would initially be Atlas messages, with the option of using shared memory in the future, though this re-introduces many of the synchronisation issues we hope to avoid by not using threads.
Certainly, even the existing threading code has had a number of complex bugs, and the out-of-process model naturally gives rule developers a sand-box, whilst protecting the server core from them. At present, the trade-offs in isolation, data-copying overhead and so on have not been investigated enough to decide whether an in-process solution based on threads is better or worse than an out-of-process one.
STAGE is currently developed by a core team of five developers, with various contributions from many more.
This document was generated using the LaTeX2HTML translator Version 2002 (1.62)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html -split 0 -nosubdir -nonavigation -html_version 4.0 Tech4OSMMG.tex
The translation was initiated by on 2002-06-01