Wrong protocol. That's implementing the master server, which receives heartbeats from savage servers and generates a .dat file for savage clients (and webbased serverlists) to download and use to contact serverlists.
It don't do Savage server firewall tests or request queries like the original master server list, so it will not contain the implementations of the needed protocol.
The uses a TCP remote admin protocol. Technically you can do some of the webbased serverlist with that, but it will be way more difficult to do.
So now how is it actually done:Let's start with master server to Savage client:Step one: Download and read serverlist from the master server (optional in case you hard-code your server IP and port into your script)
This file contains a list of IP addresses and ports of all savage servers. The first 5 characters should be in hexadecimal values: 0x7E, 0x41, 0x03, 0x00, 0x00. This is just a header!
Each group of 6 characters after that is an IP and port of a Savage server. The first four characters are binary representation of an IPv4 address. The port is formed by taking the decimal value of character #5 plus the decimal value of character #6 multiplied by 256. In code: ( decimal value of character #5 + (decimal value of character #6 * 256) )
That should give you the list of all savage servers in the master serverlist!Savage client to Savage server:Step two: Query Savage server
Now that you have the IPs and ports, you must contact each savage server.
Using UDP: sent the hexadecimal characters: 0x9E, 0x4C, 0x23, 0x00, 0x00, 0xFF, 0xFF, 0xCE, 0xF2, 0x3B, 0x18, 0x80 to the server and if you did the well, the savage server will return you its current status. Given the nature of UDP, you might want to retry sending once or twice the packet if no response is received within a reasonable timeout. (999ms should be plenty, extra credits if you maintain statistics of response times to lower this time-out and speed up processing)Step three: Process Savage server response
The response you receive can be split with the hexadecimal character 0xFF. This splits the response into different keyvalue pair. The key and values can be split using the hexadecimal character 0xFE.Step four: Process the "player"-field.
Each playername is indeed on a different line. But not all lines are player names. For example:
^900Team 1 (human)
^900Team 2 (beast)
are lines in the player field, but not actual players.
/^(\^900Team|Team) (\d) \((.+)\)(:|)/
These 2 will detect those lines. If the line is followed by the lines:
"--empty--", "---empty---" or " --empty--" that team is empty.
If it is neither all of those special situations, then it is a player name.Step five: Further process player names.
Of course those players belong to the previously found team and race.
In the player name you can still do some further processing:
Detect referee tag "^y[R]^w".
Detect officer tag "^b[
Detect AO officer tag "^050[AO]^w"
Detect commander tag "^g[C]^w"
And if you want legacy support: Detect the old commander tag "(Commander)" at the end of the player name, but ONLY on servers which do not sent the "ver" value or the "ver" value starts with "EX2" (and ofcourse only if none of the above tags are present in any names)
Lastly you can detect using regex /\^clan (\d+)\^/ to fetch clan id of the player and get the clan icon for them using that.
There you go! All you need... You just need to do some programming.