The servercode for the Forged Alliance Forever lobby
This is the source code for the
Forged Alliance Forever lobby server.
Click here to go to the
Server Python API Documentation.
The lobby server is the piece of software sitting at the very core of FAF,
enabling players to discover and play games with each other. It is a stateful
TCP server written in asyncio
and implements a custom TCP protocol for
communicating with clients.
The main responsibilities of the lobby server are:
To manage the lifecycle of joining games
(Note that Forged Alliance uses a distributed peer-to-peer networking model,
so the simulation happens entirely on the player’s machines, and NOT on
any server)
To facilitate initial connection establishment when players join a game
To maintain a list of online players
To perform rating calculations and updates
In production, the lobby server is deployed behind a websocket bridge
faforever/ws_bridge_rs.
Post a bounty on Issue Hunt. You can reward and financially help developers who
work on your issue.
The lobby server integrates with a few external services and has been tested
with the following versions:
Before opening a pull request, please take a moment to look over the
contributing guidelines.
For detailed instructions see the development guide.
This section assumes you have the necessary system dependencies installed. For
a list of what those are see the development guide.
Start up an instance of the FAF database. This is required to run the unit tests
and development server.
$ git clone https://github.com/FAForever/faf-stack.git
$ cd faf-stack
$ ./scripts/init-db.sh
Install the project dependencies with pipenv
$ pipenv sync --dev
Run the unit tests or development server
$ pipenv run tests
$ pipenv run devserver
The official FAF client code is available at
faforever/downlords-faf-client.
This can be used as a reference when implementing your own custom client.
In order to avoid having your client break unexpectedly with a new server
release, your server <-> client communication code must adhere to the following
rules:
This ensures that your client continues to function when new features are
implemented on the server side. A new feature might mean that the server will
include a new field in an existing message, or start sending an entirely new
message all together. Such changes are considered to be backwards compatible
additions to the server protocol.
You can read more about the protocol API versioning
here.
There are two layers to the server protocol:
The wire format.
This is how messages are serialized to bytes and sent over the network stream.
NOTE: in production, the client connects to the server via the websocket
bridge faforever/ws_bridge_rs
rather than connecting directly to the TCP port.
Application level messages.
Also sometimes called ‘commands’, messages are used to exchange state between
the client and server. The client will need to implement appropriate logic for
interpreting each message and reacting to it by sometimes updating UI elements,
internal state, or launching or terminating external processes.
Each message is serialized to a JSON object followed
by an ASCII newline byte (b"\n"
or b"\x0a"
). For additional information see
the server API documentation:
SimpleJsonProtocol
ask_session
command will respond with a session
command*_info
game_info
Work is ongoing to document these messages in a comprehensive way. For now, all
commands that can be sent from the client -> server can be found via the server
API documentation:
LobbyConnection
under the command_*
methods. Check the source code for what fields the message
is expected to have and any possible responses.
It may also be useful to look at the definitions in the
faf-java-commons
to see how the official client is deserializing messages from the server.
Some fields or entire message classes may become deprecated and marked for
removal over time. Actual removal is very rare as it can cause potential
breakages of outdated clients. Currently, deprecated fields and messages will
be marked with a # DEPRECATED
comment in the server code and an explanation of
how to migrate to the new functionality that is replacing the deprecated field
or message.