Startup and Initialization¶
Startup and initialization of the server is currently poorly defined. The phases are roughly as follows:
The config and command-line arguments are loaded first, because they are required to proceed further.
The asyncio and twisted reactors are initialized. The files defining the game
pyspades/ are imported via
The way the script extension system works means that scripts can only be loaded
before the two main classes,
Protocol, are instantiated.
In this phase, the scripts defined in the config are loaded. This consists of four sub-phases:
- All scripts defined under
scriptsin the config are loaded, either from the config directory, or from
apply_scriptis called on all scripts, in the order that they are declared in the config.
- If the game mode is not
"tc"for which the logic is built-in, the game mode is imported as a script.
apply_scriptis called on the game mode script
Protocol class created in the previous step is instantiated, calling
__init__ method. This does the following:
- Configure logging
- Read configuration such as map rotation, team names, time limits, win conditions
- Load the ban list
- Import and initialize auxilliary functionality like SSH, status server, banpublish/bansubscribe, command console.
- Initialize user configuration
- Resolve the filenames of the map rotation
- Create the
enet.Hostobject, listening on the socket.
- Create the
protocol.on_advance(map_name)with the name of the map that is about to be loaded.
- Schedule future tasks such as the update check, ban vaccum, map loading, annoucements, game end, update loop and master server connection.
The configuration is validated for any errors or unused keys.
Event Loop Startup¶
Control is passed to the Twisted/AsyncIO event loop, which drives everything from here on out.
The map is loaded or generated in a background thread. This is done to prevent connections from timing out on slow hardware.
Map change is triggered by
protocol.on_advancewith the next map.
- If a message was specified, print it and wait 10 seconds.
- Load or generate the next map.
- Replace the loaded map with the new one.
Game Mode Initialization¶
Games are defined by the game mode. They usually represent a period of time where two teams compete for points and end with one team winning or losing, or some other condition such as a time limit being hit.
There is currently no hook for when the game starts. However, existing modes
assume it starts with the
When a game ends, the game mode will call
on_game_end to notify any other
scripts and possibly trigger a map change.
Players join and play the game in a number of phases and states:
An ENet connection handshake is performed.
protocol.on_connect is called
This creates a new
Connection object, on which
called. This decides if the player should be allowed to join based on
information such as the player count, IP or protocol version.
The map is generated and sent to the player. A snapshot of current player state is saved, on top of which changes occurring during map transfer will be layered. A handshake is started to identify the client version and available protocol extensions.
On map transfer completion,
connection.on_join will be called.
After map transfer, players are in the “Limbo” state. They are in this state
until the client sends an
ExistingPlayer packet containing the chosen name
and team ID.
Once a team is selected,
connection.on_team_join is called to validate the
connection.on_login is then called to validate the chosen
When a player is about to be spawned,
called to allow overriding the position.
connection.on_spawn is called when
the spawn is performed.
When a player dies,
connection.on_kill is called.