Last modified 16 months ago Last modified on 01/27/11 14:45:28

New Lobby Protocol

Goals

  1. Be compatible with 2.3.x
  2. Split ingame communication from Lobby communication
  3. Let the client set the protocol while connecting
  4. New efficient and extensible protocol
    1. Version command first (if none is send use the "old" Protocol)
    2. One packet for "command" and "data"
    3. 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:

TypeGAMESTRUCT VarDescription
uint32_tGAMESTRUCT_VERSION
char[64]namegame name
int32_tdesc.dwSizesize of hostname
int32_tdesc.dwFlagsUnused
char[40]desc.hostIP Adress of the host (NOT IN USE 2.3/master!)
int32_tdesc.dwMaxPlayersMax Players (2/4/8)
int32_tdesc.dwCurrentPlayersCurrent players
int32_tdesc.dwUserFlags[0]Unused
int32_tdesc.dwUserFlags[1]Unused
int32_tdesc.dwUserFlags[2]Unused
int32_tdesc.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]extraUnused (pre 2.3.6 it size was 239 bytes)
char[40]mapnameName of the map hosted
char[40]hostnameThe hosts player name
char[64]versionstringVersion as string (2.3.4/2.3 svn/netcode xxx)
char[255]modlistList of mods (i think "," seperated)
uint32_tgame_version_major
uint32_tgame_version_minor
uint32_tprivateGame(bool) Private game?
uint32_tpureGame(bool) any mods?
uint32_tModsCount of mods
uint32_tgameIdGame ID generated at server side
uint32_tfuture2Unused
uint32_tfuture3Unused
uint32_tfuture4Unused

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

version4

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.