Current mechanism
StringSize = 64
// Available game storage... JUST FOR REFERENCE!
typedef struct {
SDWORD dwSize;
SDWORD dwFlags;
char host[16]; // host ip address
SDWORD dwMaxPlayers;
SDWORD dwCurrentPlayers;
SDWORD dwUser1;
SDWORD dwUser2;
SDWORD dwUser3;
SDWORD dwUser4;
} SESSIONDESC;
// Games Storage Structures
typedef struct {
char name[StringSize];
SESSIONDESC desc;
} GAMESTRUCT;
Masterserver routine
- A player (known as host now) starts to create a new game.
- After he pressed “Click to host the game” NETregisterServer will be called with the state=1 (NETallowJoining). The GAMESTRUCT is send to the masterserver with a “addg\0” in front of it.
- Player 2 requests a gamelist with the “list\0” command. The player now receives an unsigned integer, 32bit long and big endian, with the amount of the following GAMESTRUCTS containing the gamedata.
- If the gamestate is changed (a player joined etc…) the Host will disconnect and reconnect to the masterserver and sends a new GAMESTRUCT.
Simplified shema
(”»” send from the client, ”«” send from the server) The strings “x” are terminated with a NULL “\0”.
Register a game:
TCP >> "addg" TCP >> GAMESTRUCT
Update a registered game:
TCP disconnect TCP >> "addg" TCP >> GAMESTRUCT
A registered game starts or gets deleted:
TCP disconnect
Request a gamelist:
TCP >> "list" TCP << little big 32bit unsigned int count (amount of games) TCP << GAMESTRUCT[count] TCP disconnect
Proposals for a new protocol
Custom Text Protocol
A prototype was created that could to conversations like this one ('>' == client msg, '<' == server msg):
> LIST * < COUNT 3 // ip, port, game-name, map-name, max-players, status < 85.23.10.201 9999 Banana Game :-) Sk-Bananas-T3 8 open < 72.143.141.10 9999 Tanks'n'Oil Sk-Rush 4 started < 123.67.18.90 9999 Humans vs. BP Sk-ThePit-T2 8 open > OPENGAME 9999 The Game!! Sk-Rush 4 < DONE > STARTGAME 9999 < DONE > CLOSEGAME 9999 The Winning Commander < DONE
This is a synchronous, stateless text protocol where the client has the initiative. The text encoding is UTF-8, and the protocol specifies one command per line. The first word of these command line is the actual command, and the rest of the line is the parameter string. Each part of the line is seperated by tab characters.
Binary Protocol
Because we discovered that it was quite hard to read arbitry length lines of text in C, it was suggested that we changed to a binary protocol.
DevUrandom explains:
I am currently trying to implement the clientside, but must admit that I find it rather difficult to filter a whole line (unknown size) and then parse it...
Perhaps there can be a "machine" mode with one byte commands and everything else of a known size? Perhaps like this:
- 1 byte : command - 1 byte : size - size bytes : message Where message consits of: - 1 byte : payload 1 size - size bytes : payload 1 - 1 byte : payload 2 size - size bytes : payload 2 ...
Text (JSON) Protocol
To have more flexibility to the Lobbyserver-protocol and avoid the tag-overkill from XML here a JSON (http://www.json.org/) proposal.
(Just the raw idea, the data organizing still needs the final touch)
Adding a game
{ "lobbyquery": { "version": 1, // Protocol version, not game-version. "query": { "command": "add", "name": "MyGameName", "map": "SK-Rush", "players": 4, "tech": "T1" } } }
Response on successful entry
{ "lobbyquery": { "version": 1, "query": { "command": "add-ack", "id": "kjsdNdi28asjdnck" } } }
Keep-alive signal
To tell the lobbyserver that the game is still open
{ "lobbyquery": { "version": 1, "query": { "command": "heartbeat", "id": "kjsdNdi28asjdnck" } } }
Close signal
If the host cancels the game or the game starts
{ "lobbyquery": { "version": 1, "query": { "command": "goodbye", "id": "kjsdNdi28asjdnck" } } }
Update signal
If the host changes the settings
{ "lobbyquery": { "version": 1, "query": { "command": "update", "id": "kjsdNdi28asjdnck" "map": "SomethingOther" } } }
Request list
{ "lobbyquery": { "version": 1, "query": { "command": "list", "filter": [ {"map": "SK-Rush"} {"tech": "T3"} ] } } }
