|
|
# 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 **``Agent``**s 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
|
|
|
|
|
|
* [[Contribute to Trosnoth]] |
|
|
\ No newline at end of file |