Q3 Server Polling

For a time, I had a Quake 3 server running on my file and print server here, but I took it off because it ran slow on such an old machine, it ate my bandwidth, and it caused lots of spurious false positives in my firewall logs. In any case, I had written a cool PHP script to poll the server and see who was on it at any given time. There are a couple tricks involved. The raw information can be gleaned from id’s own pages about the protocol, but I’ve lost that link. The beauty of my system is that you can use the Perl script at the command line (on any system that runs Perl, which is all of them), or you can embed it in a web page, like I did.

#!/usr/bin/perluse Getopt::Std;use IO::Socket;

getopt ('ph');

$port = $opt_p;
$host = $opt_h;
$socket = IO::Socket::INET->new(Proto => "udp", PeerPort => $port, PeerAddr => $host );

# This sends an "Out of Band" UDP packet to the server, meaning the
# first 4 characters are hex FF's, followed by the command to get
# the server's status. What follows is a long string parsed by
# backslashes that yield the server settings and their values. After
# that comes a caret and at sign, then a line (terminated by another
# caret and at sign) for every player.

$socket->send("xffxffxffxffgetstatus");

# You need the buffer limit here because there is no "end of packet" # mark of any kind. This will just read up to that many characters.
$socket->recv($status, 2048);

# So this gets the xxxxstatusResponse from the server in @status_array[0], # and the server variables into @status_array[1], and the players in# @status_array[2 .. LAST]. Just throw away the [0] one we don't care.
@status_array = split (/x0a/, $status);

# This is seriously cool, but seriously whacked out for understanding.
# It sorts the players in order of kills.
@players = sort ({$b <=> $a} @status_array[2 .. $#status_array]);

if ($#players == -1) {
	print ("<h5 style='text-align: center'>No one is playing right now.</h5>");
	exit;
}

print ("<h2>Current Players</h2>");
print ("<table align="center" width="80%" border=1>");
print ("<tr><th>Kills</th><th>Ping</th> <th>Nickname</th></tr>");
foreach $player (@players) {
	$_ = $player;
	m/^(d+)s(d+)s(.*)$/;
	print ("<tr><td>", $1, "</td><td>", $2, "</td><td>", $3, "</td></tr>");
}
print ("</table>");

# This is a steady stream of value pairs that must be looped over in 2's
# Upshot: don't try to sort this!
@rules = split(//, $status_array[1]);
print ("<h2>Server Rules</h2>");
print ("<table align="center" width="80%" border=1>");
print ("<tr><th>Variable</th><th>Setting</th></tr>");
for ($counter = 1; $counter <= $#rules; $counter += 2) {
	print ("<tr><td>", $rules[$counter], "</td><td>", $rules[$counter+1], "</td></tr>");
}

print ("</table>");

And then you can just include a call to the script within your web page, like so:

<?php system ("scripts/q3status.pl -p 27960 -h excelsior"); ?>
  • #1 written by david  10 years ago

    Got a good idea in the middle of the day. I know I shouldn’t have, but I updated the format of the output.

  • #2 written by david  10 years ago

    Whew! Finally finished the Quake3 server status page. Perl must be the goofiest language in the world, but in the hands of a pro, would easily be the most powerful, and hardest to read.

  • #3 written by david  9 years ago

    New page where I show how to poll a Quake 3 server to see who’s on it and what rules its using.

  • You may use these HTML tags: <a> <abbr> <acronym> <b> <blockquote> <cite> <code> <del> <em> <i> <q> <strike> <strong>

  • Comment Feed for this Post
Go to Top