GameSpy Protocol
Basics
These are the protocols used to communicate with the server using the sv.gameSpyPort port in order to retrieve one or more of the following available information type:
Server Data
- This is general information about the game in progress (i.e., the map that is being played, the type of game, and any specific game settings that would be of interest to players before they joined).
Player Data
- This is information about a specific player that is in the current game (i.e., the player's name, their current score, what team they are on, and the latency to the game server).
Team Data
- This is information about a specific team in the current game (i.e., the name of the team and the team score. If your game does not support team play you do not need to report any team information).
Data is reported in a "key-value" format: player keys always end in an "_" character (such as "score_") and team keys always end in a "_t" (such as score_t). Server keys can end in anything other than an "_" or "_t"
Almost every protocol starts the same way:
0xFE 0xFD YY XX XX XX XX
Header | uint16 | Always 0xFE 0xFD |
Protocol ID | byte | |
TimeStamp | uint32 | Always retuned in the messages, may be used as an identifier distinguish between multiple packets from the same server |
App packages sent by the server are limited to 1400 bytes and all communication is handled in UDP
Battlefield 2 uses the Gamespy SDK to handle these requests.
Protocol 00: Server information
Sub-Protocol A
Only replies with 1 message, even if means responding with incomplete information
Request
0xFE 0xFD 0x00 XX XX XX XX HH PP TT 0x00
HH, PP and TT are a individual flags to request to the server its headers, players and team information, respectively.
These flags need to set to FF to be considered enabled and multiple combinations can be made, eg: asking headers and team information will be ( FF 00 FF )
Reply
Same as "Sub-Protocol B"'s reply but limited to 1 reply, 1400 bytes and some fields might be omitted, depending on the flags.
Sub-Protocol B
The most complete protocol; it always reply all 3 information fields (server, players, team) using one or more packages (of 1400 bytes).
Request
0xFE 0xFD 0x00 XX XX XX XX HH PP TT 0x01
HH, PP and TT will be ignored not matter the value.
It's the last byte, 0x01, that matters. More specifically the last byte only needs to have the least significant bit set to 1.
Reply
The server may reply with one or more messages if the information is bigger than the 1400 bytes limit.
These messages will always start with:
00 XX XX XX XX splitnum 00 YY PAYLOAD
Protocol ID | byte | Always zero |
Timestamp | uint32 | The value sent in the request |
"splitnum" | string | Always "splitnum" |
splitnum | byte | Only seen 00 probably indicates how the strings are terminated[1] |
Message Number | byte | The most significant bit indicates if its the last message, all others are used for the message number |
The payload 1st byte indicates the type: 00, 01 and 02 for Server Headers, Player information and Team Information, respectively.
Server Headers
key/value pairs.
00 <key 1> 00 <value 1> 00 ... <key N> 00 <value N> 00 00
Example:
\00hostname\00[PR v1.4.6.0] =]H[= HARDCORE GAMING - NA\00gamename\00battlefield2\00gamever\001.5.3153-802.0\00password\000\00
Which is:
hostname: "[PR v1.4.6.0] =]H[= HARDCORE GAMING - NA" gamename: "battlefield2" gamever: "1.5.3153-802.0" password: "0" (false)
Player information and Team information
Player and Team informations are stored into <key>:<array of values>.
With the actual format being
QQ <key 1> 00 <offset> <value 1 + offset> 00 ... <value NN> 00 00 00
QQ is the type. With 0x01 indicating its Player information and 0x02 representing Team information.
Since the message may end before the array ends, the first value after each key is the <offset> that defines the index to start from.
An example of the player information's section with 3 players is:
\01 player_\00\00 =MD=shilijia\00>11< WangXi\00 a365476093\00\00score_\00\00191\00159\000\00\00ping_\00\0050\0033\0018\00\00\00
Which is:
player_: [" =MD=shilijia", ">11< WangXi", " a365476093"] score_: ["191", "159", "0"] ping_: ["50", "33", "18"]
Sub-Protocol C
The 3rd of our sub-protocols to request information about the server allows you to indicate which headers and how many you want to know about.
Request
0xFE 0xFD 0x00 XX XX XX XX YY KK0 ... KKYY-1 0x00 0x00
The 8th byte (YY) informs the server how many headers you're asking for, meaning the number of bytes that follows afterwards (plus 2 terminal ones). These following bytes, excluding the last 2, define the header's indexes that you're querying about. See next table to see the mapping between index and header.
Offset | Header |
01 | hostname |
02 | gamename |
03 | gamever |
04 | hostport |
05 | mapname |
06 | gametype |
07 | gamevariant |
08 | numplayers |
09 | ?? |
0a | maxplayers |
0b | gamemode |
0c | ?? |
0d | ?? |
0e | ?? |
0f | ?? |
10 | timelimit |
11 | roundtime? |
12 | ?? |
13 | ?? |
Reply
The sub-protocol C replies with the usual protocol ID followed by the provided timestamp, the payload and the null byte to terminate the message.
0x00 XX XX XX XX PAYLOAD 0x00
The payload consists in all header's value requested separated by 0x00. The header's values maintains the same order as in the request.
Example: Requesting the number of players and server name
0xFE 0xFD 0x00 0x20 0x21 0x21 0x20 0x02 0x08 0x01 0x00 0x00
The reply will be, 84 players and 'My Server':
0x00 0x20 0x21 0x21 0x20 0x84 0x00 [PR v1.4.17.0] My Server 0x00
Protocol 02: Echo
An echo protocol. The server always returns the data sent after the protocol ID (up to 32 bytes) prefixed with the Echo Response Identifier (0x05).
Request
FE FD 02 XX0 ... XX31
Reply
05 XX0 ... XX31
Protocol 03: PACKET_HEARTBEAT
Protocol 08: Keep Alive
Sent by the master server to the server to report it knows about it
Request
FE FD 08
Reply
No reply
Protocol 09: Echo Alternative
According to game-spy specifications this should be used to generate a 4 bytes value for us to send in the following replies as the TimeStamp, therefore allowing an IP verification.
Battlefield 2 however just returns 4 bytes of what we send with 2 more hardcoded bytes appended.
Request
FE FD 09 XX XX XX XX
Reply
09 XX XX XX XX 30 00