Launcher protocol

Revision as of 20:28, 12 December 2021 by DrinkyBird (talk | contribs) (3.1 is released, so Devfeature templates have been removed)

This launcher protocol lets you to talk to servers and get information from them, allowing you to make your own custom programs like browsers, stat tools, and so on.

Protocol information

See "article history" to look up the protocol for prior versions.

The basics

All Zandronum servers use UDP as their network protocol. Additionally, all traffic is compressed using the Huffman algorithm to save bandwidth. Therefore, you'll need a copy of huffman.cpp or huffman.java to encode and decode your traffic appropriately.

There is also an implementation of the Huffman codec written in Python here. Also in Python 3 here.

Definition of data types used in this article:

  • Byte: 8 bit integer
  • Short: 16 bit integer
  • Long: 32 bit integer
  • Float: Long representation of a float
  • String: null-terminated series of Bytes

Traffic is encoded in little-endian.

Getting the list of servers

This is very easy, accomplished by sending a long and a short to the master server:

Type Value Description
Long 5660028 LAUNCHER_MASTER_CHALLENGE
Short 2 MASTER_SERVER_VERSION

If your request is denied, the server will respond with one of the following:

Type Value Description
Long 3 Denied; your IP is banned (MSC_IPISBANNED)
Long 4 Denied; your IP has made a request in the past 3 seconds (MSC_REQUESTIGNORED)
Long 5 Denied; you're using an older version of the master protocol (MSC_WRONGVERSION)

If you are accepted, you will receive multiple packets, each starting with:

Type Value Description
Long 6 Beginning of list (MSC_BEGINSERVERLISTPART)
Byte 0-255 Packet number (starting with 0)
Byte 8 Beginning of server block (MSC_SERVERBLOCK)

Then you will get this next block, which is repeated for every IP with servers on it.

Type Value Description
Byte 0-255 n = Number of servers with this IP address
Byte 0-255 IP address octet
Byte 0-255 IP address octet
Byte 0-255 IP address octet
Byte 0-255 IP address octet
Short 0-65535 IP port (sent 'n' times)

Once the packet is full or all servers are transferred, you will receive 0 as number of servers on the next IP.

Type Value Description
Byte 0 There are no ports for the next server, i.e. no more servers in this packet.

Finally, the response should end with either

Type Value Description
Byte 2 End of list, you got the full server list now (MSC_ENDSERVERLIST)

or

Type Value Description
Byte 7 End of current part of the list, you'll get more packets (MSC_ENDSERVERLISTPART)

Querying individual servers

You need to choose what data you'd like. To do so, bitshift the combination of flags with a boolean OR.

The flags are:

Name Value Description
SQF_NAME 0x00000001 The name of the server
SQF_URL 0x00000002 The associated website
SQF_EMAIL 0x00000004 Contact address
SQF_MAPNAME 0x00000008 Current map being played
SQF_MAXCLIENTS 0x00000010 Maximum amount of clients who can connect to the server
SQF_MAXPLAYERS 0x00000020 Maximum amount of players who can join the game (the rest must spectate)
SQF_PWADS 0x00000040 PWADs loaded by the server
SQF_GAMETYPE 0x00000080 Game type code
SQF_GAMENAME 0x00000100 Game mode name
SQF_IWAD 0x00000200 The IWAD used by the server
SQF_FORCEPASSWORD 0x00000400 Whether or not the server enforces a password
SQF_FORCEJOINPASSWORD 0x00000800 Whether or not the server enforces a join password
SQF_GAMESKILL 0x00001000 The skill level on the server
SQF_BOTSKILL 0x00002000 The skill level of any bots on the server
SQF_DMFLAGS 0x00004000 (Deprecated) The values of dmflags, dmflags2 and compatflags. Use SQF_ALL_DMFLAGS instead.
SQF_LIMITS 0x00010000 Timelimit, fraglimit, etc.
SQF_TEAMDAMAGE 0x00020000 Team damage factor.
SQF_TEAMSCORES 0x00040000 (Deprecated) The scores of the red and blue teams. Use SQF_TEAMINFO_* instead.
SQF_NUMPLAYERS 0x00080000 Amount of players currently on the server.
SQF_PLAYERDATA 0x00100000 Information of each player in the server.
SQF_TEAMINFO_NUMBER 0x00200000 Amount of teams available.
SQF_TEAMINFO_NAME 0x00400000 Names of teams.
SQF_TEAMINFO_COLOR 0x00800000 RGB colors of teams.
SQF_TEAMINFO_SCORE 0x01000000 Scores of teams.
SQF_TESTING_SERVER 0x02000000 Whether or not the server is a testing server, also the name of the testing binary.
SQF_DATA_MD5SUM 0x04000000 (Deprecated) Used to retrieve the MD5 checksum of skulltag_data.pk3, now obsolete and returns an empty string instead.
SQF_ALL_DMFLAGS 0x08000000 Values of various dmflags used by the server.
SQF_SECURITY_SETTINGS 0x10000000 Security setting values (for now only whether the server enforces the master banlist)
SQF_OPTIONAL_WADS 0x20000000 Which PWADs are optional
SQF_DEH 0x40000000 List of DEHACKED patches loaded by the server.
SQF_EXTENDED_INFO 0x80000000 Additional server information, see the table below for more information.

Extended flags

Name Value Description
SQF2_PWAD_HASHES 0x00000001 The MD5 hashes of the server's loaded PWADs.
SQF2_COUNTRY 0x00000002 The server's ISO 3166-1 alpha-3 country code.

For example, to get the server's name and player count, you'd use (SQF_NAME|SQF_NUMPLAYERS). Use these flags appropriately; doing so saves your users' and server hosters' bandwidth.

Now send the server the following packet:

Type Value Description
Long 199 Launcher challenge
Long Flags Desired information
Long Time Current time, this will be sent back to you so you can determine ping.
Long Flags2 The extended information you want. Ensure you specify SQF_EXTENDED_INFO in the normal Flags field as well. This field is optional - if this field is not present, its value is inferred to be 0. Older servers will ignore this field.

The server will respond with the following:

Type Value Description
Long Response
  • 5660023: Accepted; server information follows
  • 5660024: Denied; your IP has made a request in the past sv_queryignoretime seconds
  • 5660025: Denied; your IP is banned
Long Time The time you sent to the server.

Next, assuming you were accepted, you'll get:

Type Value Description
String Version Server version string with revision number.
Long Flags The info you'll be receiving, possibly corrected (see below).

Followed by:

Type Flag Description
String SQF_NAME The server's name (sv_hostname)
String SQF_URL The server's WAD URL (sv_website)
String SQF_EMAIL The server host's e-mail (sv_hostemail)
String SQF_MAPNAME The current map's name
Byte SQF_MAXCLIENTS The max number of clients (sv_maxclients)
Byte SQF_MAXPLAYERS The max number of players (sv_maxplayers)
Byte SQF_PWADS The number of PWADs loaded
String SQF_PWADS The PWAD's name (Sent for each PWAD)
Byte SQF_GAMETYPE The current game mode. See below.
Byte SQF_GAMETYPE Instagib - true (1) / false (0)
Byte SQF_GAMETYPE Buckshot - true (1) / false (0)
String SQF_GAMENAME The base game's name ("DOOM", "DOOM II", "HERETIC", "HEXEN", "ERROR!")
String SQF_IWAD The IWAD's name
Byte SQF_FORCEPASSWORD Whether a password is required to join the server (sv_forcepassword)
Byte SQF_FORCEJOINPASSWORD Whether a password is required to join the game (sv_forcejoinpassword)
Byte SQF_GAMESKILL The game's difficulty (skill)
Byte SQF_BOTSKILL The bot difficulty (botskill)
Long SQF_DMFLAGS [Deprecated] Value of dmflags
Long SQF_DMFLAGS [Deprecated] Value of dmflags2
Long SQF_DMFLAGS [Deprecated] Value of compatflags
Short SQF_LIMITS Value of fraglimit
Short SQF_LIMITS Value of timelimit
Short SQF_LIMITS time left in minutes (only sent if timelimit > 0)
Short SQF_LIMITS duellimit
Short SQF_LIMITS pointlimit
Short SQF_LIMITS winlimit
Float SQF_TEAMDAMAGE The team damage scalar (teamdamage)
Short SQF_TEAMSCORES [Deprecated] Blue team's fragcount/wincount/score
Short SQF_TEAMSCORES [Deprecated] Red team's fragcount/wincount/score
Byte SQF_NUMPLAYERS The number of players in the server
String SQF_PLAYERDATA Player's name
Short SQF_PLAYERDATA Player's pointcount/fragcount/killcount
Short SQF_PLAYERDATA Player's ping
Byte SQF_PLAYERDATA Player is spectating - true (1) / false (0)
Byte SQF_PLAYERDATA Player is a bot - true (1) / false (0)
Byte SQF_PLAYERDATA Player's team (returned on team games, 255 is no team)
Byte SQF_PLAYERDATA Player's time on the server, in minutes. Note: SQF_PLAYERDATA information is sent once for each player on the server.
Byte SQF_TEAMINFO_NUMBER The number of teams used.
String SQF_TEAMINFO_NAME The team's name. (Sent for each team.)
Long SQF_TEAMINFO_COLOR The team's color. (Sent for each team.)
Short SQF_TEAMINFO_SCORE The team's score. (Sent for each team.)
Byte SQF_TESTING_SERVER Whether this server is running a testing binary - true (1) / false (0)
String SQF_TESTING_SERVER An empty string in case the server is running a stable binary, otherwise name of the testing binary archive found in http://www.skulltag.com/testing/files/
String SQF_DATA_MD5SUM [Deprecated] Returns an empty string.
Byte SQF_ALL_DMFLAGS The number of flags that will be sent.
Long SQF_ALL_DMFLAGS The value of the flags (Sent for each flag in the order dmflags, dmflags2, zadmflags, compatflags, zacompatflags, compatflags2)
Byte SQF_SECURITY_SETTINGS Whether the server is enforcing the master ban list - true (1) / false (0) The other bits of this byte may be used to transfer other security related settings in the future.
Byte SQF_OPTIONAL_WADS Amount of optional wad indices that follow
Byte SQF_OPTIONAL_WADS Index number int the list sent with SQF_PWADS - this wad is optional (sent for each optional Wad)
Byte SQF_DEH Amount of deh patches loaded
String SQF_DEH Deh patch name (one string for each deh patch)
Long SQF_EXTENDED_INFO The flags specifying extended server information you will receive. Check all SQF2 values against this field.
Byte SQF2_PWAD_HASHES The number of hashes sent.
String SQF2_PWAD_HASHES The hash of the PWAD, sent for each PWAD. The indices are the same as sent in SQF_PWADS
Byte[3] SQF2_COUNTRY The server's ISO 3166-1 alpha-3 country code. This is sent as a raw char array of 3 length, there is no null terminator. Zandronum also has two special values for this field, XIP and XUN. See #Country codes below for how to handle this field.

Note: The server will automatically correct your request if you made a mistake (like request team scores in cooperative games), so always use the flags it sends back to you when reading your data.

And that's it!

Notes

Game modes

Game modes are defined as:

   0   GAMEMODE_COOPERATIVE
   1   GAMEMODE_SURVIVAL
   2   GAMEMODE_INVASION
   3   GAMEMODE_DEATHMATCH
   4   GAMEMODE_TEAMPLAY
   5   GAMEMODE_DUEL
   6   GAMEMODE_TERMINATOR
   7   GAMEMODE_LASTMANSTANDING
   8   GAMEMODE_TEAMLMS
   9   GAMEMODE_POSSESSION
   10  GAMEMODE_TEAMPOSSESSION
   11  GAMEMODE_TEAMGAME
   12  GAMEMODE_CTF
   13  GAMEMODE_ONEFLAGCTF
   14  GAMEMODE_SKULLTAG
   15  GAMEMODE_DOMINATION

Country codes

Zandronum 3.1 introduces the ability to server hosts to specify the country their server is located in via a new CVAR, sv_country. This was introduced to allow hosts to combat the inaccuracies of IP geolocation that launchers rely on. This value is specified to launchers via the new SQF2_COUNTRY field, which can have the following values:

  • an ISO 3166-1 alpha-3 country code. Note that Zandronum doesn't validate whether the country code supplied in sv_country is a registered country code. If the launcher does not recognise the given code, then it should display a generic "unknown" flag.
  • the value XIP, which suggests to the launcher that it should attempt IP geolocation to determine the server's country. The default value of sv_country will cause it to return this by default, to preserve existing behaviour and make it easier for casual hosts. If geolocation is unsupported, disabled, or fails, then a generic "unknown" flag should be displayed.
  • the value XUN, in which case the launcher should display a generic "unknown" flag.

Also see   Issue 3894: Allow servers to present their country to launchers.