Clone wiki

trosnoth / Getting Started

Getting Started with Trosnoth Development

The purpose of this page is to help new Trosnoth coders begin to understand the inner workings of Trosnoth.

Twisted Reactor

Trosnoth currently uses Twisted to provide its main loop. You don't need to understand everything about Twisted to work on Trosnoth, but there are a few things worth noting:

  • Twisted is an asynchronous framework. This means that you can start a task and say, "When this finishes, call this function." To represent long-running tasks, Twisted uses Deferred objects from twisted.internet.defer. To indicate what should happen when a task completes or fails, you use d.addCallback(callbackFunction) or d.addErrback(errorHandler) respectively.
  • Twisted doesn't use threading for its multitasking, but instead uses cooperative multitasking. The up-side of this approach is that you don't have to worry about locks and semaphores: you're always guaranteed that your code will run atomically and uninterrupted. The down-side is that chunks of code that take a long time will block the whole process. Therefore never use time.sleep(), and avoid blocking I/O calls (try to use Twisted's asynchronous alternative). If you have to perform complex calculations, try to find ways to break them up.pause
  • Twisted provides time-related functions like reactor.callLater() and twisted.internet.task.LoopingCall(). These are useful if you want your timing to be based on real time (e.g. for animations in the UI). But what you care about is game time, please use world.callLater() or world.sleep().
  • Throughout the code, you might see functions decorated with @defer.inlineCallbacks. When reading these functions, please note that:
    • defer.returnValue(...) will return from the function
    • yield d will interrupt the function and return control to the Twisted reactor until the Deferred task d has finished
    • calling a function decorated as inlineCallbacks will return a Deferred object

Glossary

Here are some terms you may come across in the Trosnoth code.

  • world or universe: this encapsulates the state of an entire Trosnoth game, including details of the current map, and locations of all units
  • unit: anything that moves, including players, shots, grenades and stars

Internal Structure

If you're planning to delve deep into the Trosnoth internals, you may come across some of the following interfaces. Here's a quick explanation.

Message classes

Because Trosnoth operates over the network, information about player actions and changes in universe state need to be able to be serialised. To do this, we use Message classes (defined in trosnoth/messages/*.py). Messages typically subclass one of:

  • AgentRequest if it represents a request being sent from a client to the server
  • ServerCommand if it represents a command being sent from the server to one or all clients
  • ClientCommand if the same message class will be used for both the client to server request, and the subsequent command that informs all clients that this event has happened
  • ServerResponse if it represents a response that is sent back to the client who send an AgentRequest, usually to inform them why their request was denied

If you create a new Message class, it is important to add it to trosnoth.network.client.clientMsg if it's ever going to be received by a client, and to trosnoth.network.server.serverMsg if it's ever going to be received by a server. This tells the client and server how to decode this message kind.

Game / Agents

A Game represents a Trosnoth game. It might be a LocalGame, which is being controlled within this process, or a RemoteGame, which is talking over the network to get its instructions.

A Game may have a number of Agents connected to it. An Agent represents something or someone who wants to receive game events, and who may want to control a player. For instance, the Trosnoth user interface is represented by a subclass of Agent, which sends requests to the game whenever the user presses a key, clicks to shoot, etc.. Trosnoth bots communicate with the the game using the AIAgent class, which is also a subclass of Agent. Within a Trosnoth server process, an Agent subclass is also used to represent players over the network.

Regardless of the class of Game or Agent, the same interface is used to send messages between them. This interface is defined in the base Game and Agent classes.

See Also

Updated