1

Topic: Retrieving Server Stats

Hi folks,
great game you are developing there. Looking forward for the next releases.

I want to create an info box for my website which shows information about my Teewars server.
So what do I have to send to the server to retrieve stats like servername, number of players, etc.
And is it possible to find out the playernames and their score, too? If not, would be a nice feature for the next version smile

Keep up the good work!
Greetings zq

2

Re: Retrieving Server Stats

I think that you must wait for the source code release!

Cheers :>

#teewars.fr @ Qnet

3

Re: Retrieving Server Stats

I don't think so, since Malcolm already developed an external server browser.

4

Re: Retrieving Server Stats

kenzfu wrote:

I think that you must wait for the source code release!

Cheers :>

BTW: It is possible to make Teewars OpenSource (GPL or BSD licence)?

5

Re: Retrieving Server Stats

It's possible to get server name, number of players etc. More info will be available in the next version. There are some that done stuff like this.
I found this snippet that someone wrote. It's written in python.

from socket import * 
from struct import * 
 
def tw_get_num_players(address, port): 
    sock = socket(AF_INET, SOCK_DGRAM) 
    sock.settimeout(5.0); 
    sock.sendto("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief", (address, port)) 
    data, addr = sock.recvfrom(1024) 
    sock.close() 
 
    data = data[14:] 
 
    server_name, map_name = data[:-2].split("\x00")[0:2] 
    data = data[-2:] 
    max_players = ord(data[0]) 
    num_players = ord(data[1]) 
 
    return num_players 
 
def tw_get_info(): 
    address = "master.teewars.com" 
    master_port = 8383 
 
    sock = socket(AF_INET, SOCK_DGRAM) 
    sock.settimeout(5.0) 
    sock.sendto("\x20\x00\x00\x00\x00\x48\xff\xff\xff\xffreqt", (address, master_port)) 
 
    data, addr = sock.recvfrom(1024) 
    sock.close() 
    data = data[14:] 
    num_servers = len(data) / 6 
    num_players = 0 
 
    for n in range(0, num_servers): 
        ip = ".".join(map(str, map(ord, data[n*6:n*6+4]))) 
        print ip 
        port = ord(data[n*6+5]) * 256 + ord(data[n*6+4]) 
        try: 
            num_players += tw_get_num_players(ip, port) 
        except: 
            num_servers -= 1 
         
    return (num_servers, num_players)

The source code will be released, but not under GPL or BSD. It will be a custom license for the game to prevent forks and other nasty stuff that could ruin the game.

6

Re: Retrieving Server Stats

Nice, thank you matricks!

If I'll get it to work, I'll post the php-snippet here later.

7

Re: Retrieving Server Stats

zq wrote:

Nice, thank you matricks!

If I'll get it to work, I'll post the php-snippet here later.

There is someone in the #teewars channel on quakenet that is working on php stuff like that.

8

Re: Retrieving Server Stats

Ok finally had time to finish this little snippet. Could still be improved but it already serves it's purposes very well.
I hope there will be a possibility to receive playernames, scores and some other information (player color? big_smile) in the future. Go matricks go! smile

Here's the baby

<?php
// Server Stats Receiving Tool for Teewars
//
// visit www.teewars.com
//
// (c) by zeeq

// Returns server information packed in an array
//
// @param string $ip: IP or URI of the server to check
// @param int $port : Port of the game server provided as integer
//
// @return array("Name", "IP", "Port", "Map", "MaxPlayers", "Players") or false if an error occured
function getServerStats($ip, $port)
{    
    // Initialize return array
    $Stats = array ( "Name" => "", "IP" => $ip, "Port" => $port, "Map" => "", "MaxPlayers" => 0, "Players" => 0 );

    // Open socket
    $fp = @fsockopen("udp://" . $Stats['IP'], $Stats['Port'], $errno, $errstr, 2);
    socket_set_timeout($fp, 2);
    
    if(!$fp)
    {
        //echo "*** ERROR $errno: $errstr";
        return false;
    }
    else
    {
        // Send query
        
        // required byte sequence in ASCII
        $query = "ÿÿÿÿÿÿÿÿÿÿgief";
        
        $i = fwrite($fp, $query);
        
        $data = fread($fp, 1024);

        // Search for the "info" string
        $index = strpos($data, "info");
        
        if ($index === false)
        {
            //echo "*** ERROR: Unknown server response";
            return false;
        }
        else
        {
            // Cut unimportant bytes until server name
            $data = substr($data, $index + 4);

            // Get server name until next nul byte
            $index = strpos($data, chr(00));
            
            $Stats['Name'] = substr($data, 0, $index);

            // Get map name
            $data = substr($data, $index + 1);

            $index = strpos($data, chr(00));

            $Stats['Map'] = substr($data, 0, $index);
            
            // Get max- and players
            $data = substr($data, $index + 1);
            
            $Stats['MaxPlayers'] = ord($data[0]);
            $Stats['Players'] = ord($data[1]);
            
            return $Stats;
        }
    }
}

This script will work as long the server name + map name is no longer than 110 characters. But I don't think this will ever be the case smile

Example use of the function:

$stats = getServerStats("192.168.1.1", 8303);

if ($stats === false)
    echo "ERROR";
else
    var_dump($stats);

9

Re: Retrieving Server Stats

If someone is interested in the structure of the involved packets:

// PACKET INFORMATION
///////////////////////
// Server Info Return Format:
// 20-00-00-00-9f-12-ff-ff-ff-ff-69-6e-66-6f-xx-xx-xx-xx-00-yy-yy-yy-00-zz-ww
// ^---------- Space followed by 3 empty bytes
//             ^---- 2 unknown bytes
//                   ^---------- 4 ff Bytes 
//                               ^---------- 4 bytes reading "info"
//                                           ^---------- Server Name (length differs)
//                                                       ^- Seperator
//                                                          ^------- Map Name (length differs)
//                                                                   ^- Seperator
//                                                                      ^- Maxplayers (no ASCII!)
//                                                                         ^- Players (no ASCII!)
//
// Conclusion: xx = server name, yy = map name, zz = maxplayers, ww = current players connected
///////////////////////
// Following byte sequence needs to be send to the server:
// ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-67-69-65-66
// in ASCII:
// ÿÿÿÿÿÿÿÿÿÿgief

10

Re: Retrieving Server Stats

I can explain the first bytes as well.

1 byte Flags ()
3 bytes Sequencing + Acknowledgment numbers (Not)
2 byte Token

NETWORK_PACKETFLAG_CONNECT=0x01, // set when a connection should be made
NETWORK_PACKETFLAG_ACCEPT=0x02, // set when a connection is accepted
NETWORK_PACKETFLAG_CLOSE=0x04, // set when a connection should be closed
NETWORK_PACKETFLAG_VITAL=0x08, // set when this packet is vital and should not get lost
NETWORK_PACKETFLAG_RESEND=0x10, // set when the peer is requesting a resend of non-acked vital packages
NETWORK_PACKETFLAG_CONNLESS=0x20, // used for stateless communication, like the server browser

So when you talk with the master server, the first 6 bytes should be 20-00-00-00-00-00 but in reality, only the first byte matter that the 0x20 bit is set because then it ignores the rest.

11 (edited by BombardieR 2007-10-31 17:56:13)

Re: Retrieving Server Stats

zq wrote:

Example use of the function:

$stats = getServerStats("192.168.1.1", 8303);

if ($stats === false)
    echo "ERROR";
else
    var_dump($stats);

I plase this piece of code in the same .php file with getServerStats function, but if i type htdocs/teewars.php in my browser, i see this:

"ERROR"

Server is online (entering the game without any problems), where the trouble? Sorry for my bad english, and php theory smile, i need some little help. Best regards.

p.s. 192.168.1.1 i replace with my 10.2.63.5

12

Re: Retrieving Server Stats

Your webserver needs to be able to use the fsockopen-function. delete the '@' in '@fsockopen' and see what happens.

<TroXx> - (Swiss) German Community Member
Currently active mods:
Ninjamod 0.3 - Improved Ugly/Q3-4 Mod

13

Re: Retrieving Server Stats

same error ((

14

Re: Retrieving Server Stats

Ehm where are you running the php script? On your local machine, in your local network or on a webserver in the internet?
IMO the problem is that you try to access your home network from the internet. Because the IPs you posted (192.168.*.* and 10.*.*.*) indicate that your server is NOT accessible via the internet.
The script terminates with the error message because the main function returns 'false', since it cannot open the required socket to the teewars server.

You use the script in the right way though, it's either an access problem or something is wrong with your webserver (like Troxxx already mentioned).

15 (edited by BombardieR 2007-11-05 18:05:47)

Re: Retrieving Server Stats

I use XAMPP, in my local machine in my local area with local teewars server (ip 10.2.63.5). Maybe fsockopen-function need to be uncommented some were in the config files from the xampp directory?

p.s. some one have a work script installed and accesible via internet?

16 (edited by zq 2007-11-05 18:29:22)

Re: Retrieving Server Stats

The script works for me with XAMPP and it's standard configuration combined with a local teewars server. Maybe some firewall or routing problem? Is the teewars server running on the same machine as XAMPP? If yes, try using "localhost" as IP in the script and doublecheck again if the port is correct. Did you mess with the Apache-Configuration of the XAMPP? Do you have an outdated version maybe?

Edit: Oh and please paste the code snippet where you are using my function!

17

Re: Retrieving Server Stats

try to debug the script:

1. put
error_reporting( E_ALL );
at the beginning of the script

2. ( if you dont have it ) put
ini_set( 'display_errors', true );
at the beginning of the script.


Any error messages?


Greets

<TroXx> - (Swiss) German Community Member
Currently active mods:
Ninjamod 0.3 - Improved Ugly/Q3-4 Mod

18 (edited by prgr 2008-02-26 16:03:26)

Re: Retrieving Server Stats

use IO::Socket;
my ($datagram,$flags,$line);
my $PlayerCount=0;
my $sock = IO::Socket::INET->new(
    Proto    => 'udp',
    PeerPort => 8303,
    PeerAddr => 'serverip',
) or die "Could not create socket: $!\n";

$sock->send("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffgief") or die "Send error: $!\n";
$sock->recv($datagram,1024,$flags);
my ($ServerName,$MapName,$PlayerList)=$datagram=~/info[^\x00]+\x00([^\x00]+)\x00([^\x00]+).+\x00\x31[^\x00]\x00(.+)/;
my @Pl=split(/\x00/,$PlayerList);
foreach $line (@Pl)
{
        $PlayerCount++;
}

print "$ServerName,$MapName,$PlayerCount\n";

It's on perl.
Blocks of a package as that have strange changed