New Lobby Protocol
Table of Contents
Goals
- Be compatible with 2.3.x
- Split ingame communication from Lobby communication
- Let the client set the protocol while connecting
- New efficient and extensible protocol
- Version command first (if none is send use the "old" Protocol)
- One packet for "command" and "data"
- Variable sized
The current implementation
Currently the Protocol is based on a fixed size Big Endian Struct, which is defined as "GAMESTRUCT" ingame.
The function NETsendGAMESTRUCT in lib/netplay/netplay.c defines it as follows:
| Type | GAMESTRUCT Var | Description |
| uint32_t | GAMESTRUCT_VERSION | |
| char[64] | name | game name |
| int32_t | desc.dwSize | size of hostname |
| int32_t | desc.dwFlags | Unused |
| char[40] | desc.host | IP Adress of the host (NOT IN USE 2.3/master!) |
| int32_t | desc.dwMaxPlayers | Max Players (2/4/8) |
| int32_t | desc.dwCurrentPlayers | Current players |
| int32_t | desc.dwUserFlags[0] | Unused |
| int32_t | desc.dwUserFlags[1] | Unused |
| int32_t | desc.dwUserFlags[2] | Unused |
| int32_t | desc.dwUserFlags[3] | Unused |
| char[40] | secondaryHosts[0] | Additional IP Address of the host (NOT IN USE 2.3/master!) |
| char[40] | secondaryHosts[1] | Additional IP Address of the host (NOT IN USE 2.3/master!) |
| char[159] | extra | Unused (pre 2.3.6 it size was 239 bytes) |
| char[40] | mapname | Name of the map hosted |
| char[40] | hostname | The hosts player name |
| char[64] | versionstring | Version as string (2.3.4/2.3 svn/netcode xxx) |
| char[255] | modlist | List of mods (i think "," seperated) |
| uint32_t | game_version_major | |
| uint32_t | game_version_minor | |
| uint32_t | privateGame | (bool) Private game? |
| uint32_t | pureGame | (bool) any mods? |
| uint32_t | Mods | Count of mods |
| uint32_t | gameId | Game ID generated at server side |
| uint32_t | future2 | Unused |
| uint32_t | future3 | Unused |
| uint32_t | future4 | Unused |
NETsendGAMESTRUCT is currently used for in game communication (when a client joins a game) and communications betweend the lobby server
NETRecvGAMESTRUCT translates a received struct back into a ingame "GAMESTRUCT"
My proposal for the new "Protocol"
It uses BSON as serializer ( http://bsonspec.org/ ) and the this format:
| <unsigned integer> | length of data |
| <BSON> | the BSON Data |
While the BSON data looks like:
--> {"method": "addGame", "params": {"description": "Fast, NTW", "maxPlayers": 8, "currentPlayers": 1}, "id": 1}
<-- {"status": 0, "result": "Welcome to Warzone! Your game is now listed in the lobby server", "id": 1}
Connecting to the Masterserver v4
1. command version
| version | 4 |
response:
connection closes on a wrong version
2. command login
--> {"method": "login", "params": {"username": "Fastdeath", "password": "mysecretpass"}, "id": 1}
response:
<-- {"status": 0, "result": {"userid": 2, "sessionid": "<long-session-id>"}, "id": 1}
or:
<-- {"status": -405, "result": "Unknown user or wrong password", "id": 1}
Creating a game
1. command addgame
--> {"method": "addGame", "params": {"description": "Fast, NTW", "maxPlayers": 8, "currentPlayers": 1}, "id": 2}
response:
<-- {"status": 0, "result": {"gameId": 1, "motd": "Welcome to Warzone! Your game is now listed in the lobby server"}, "id": 2}
or:
<-- {"status": -403, "result": "Please upgrade your Warzone to 2.3.7! See http://wz2100.net.", "id": 2}
or:
<-- {"status": -403, "result": "Game unreachable, failed to open a connection to port 2100.", "id": 2}
or:
<-- {"status": -403, "result": "Game name not acceptable. The game is NOT hosted, change the name of your game.", "id": 2}
Joining a game
1. command list
--> {"method": "list", "params": "", "id": 2}
response:
<-- {"status": 0, "result": {"count": 10, "list": {[GAMEDATA1, GAMEDATA2, ...}, "id": 2}
2. Player joins the game
The Game joins the host with the users-id and its session-id.
3. Host adds and checks the player: addPlayer
--> {"method": "addPlayer", "params": {"userid": 2, "sessionid": "<long-session-id>"}, "id": 3}
response:
<-- {"status": 0, "result": "ok", "id": 3}
or:
<-- {"status": -406, "result": "invalid", "id": 3}
4. Gamehost sends the GAMESTRUCT to all clients
Leaving a game
1. The game leaves the host as usual
2. Gamehost sends command delPlayer
--> {"method": "delPlayer", "params": {"userid": 2}, "id": 4}
response:
<-- {"status": 0, "result": "ok", "id": 4}
When the game starts or the hosts closes the game
Gamehost sends command delGame
--> {"method": "delGame", "params": {"userid": 2}, "id": 4}
response:
<-- {"status": 0, "result": "ok", "id": 4}
The lobbyserver should check any open games for theier responsibilty and close "lost" games when required.
