Version: 0.4.0 class
Type: Class
Category: Games
License: GNU General Public License
Description: gQuery// is a game server query tool for PHP. It works in many ways
in the same manner as qStat but by using PHP instead of C it allows
much easyer intergration into the web along with overall flexibility.
It supports Quake2, Quake3, Half-Life and Unreal Tournament servers & more.
Visit the homepage at http://gdome.sourceforge.net/
<?php /* +------------------------------------------------------------------------+ | gQuery// version 0.4.0 beta | | Copyright (c) 2001 Jon Gretar Borgthorsson. All rights reserved. | +------------------------------------------------------------------------+ | gQuery// is a part of the gDome// project. Find more information | | about gDome// and related projects at http://gdome.sourcefoge.net/ | +------------------------------------------------------------------------+ | | | This program is free software; you can redistribute it and/or | | modify it under the terms of the GNU General Public License version 2 | | as published by the Free Software Foundation | | | | Software distributed under the License is distributed on an "AS IS" | | basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. | | See the GNU General Public License in License.html for more details. | | | +------------------------------------------------------------------------+ | Website: http://gdome.sourceforge.net/ | +------------------------------------------------------------------------+ | Authors: | | Jon Gretar Borgthorsson <[email protected]> | +------------------------------------------------------------------------+ */ class gQuery { // gQuery system variables var $errors = array(); // Errors in the script var $fp; // File pointer // The info you give the script var $cgametype; // Type of game var $caddress; // Connection address var $cport; // Connection port // Responders var $serverinfo; // Server info array var $playerinfo; // Player info array var $systeminfo; // System info array var $pcount = 0; // Player count // Debug variables var $DEBUG; // DEBUG var $DEBUG2; // DEBUG // Types of games var $gametypes = array( "HL" => "Half-Life", "HL2" => "Half-Life 2", "Q1" => "Quake", "Q2" => "Quake 2", "Q3" => "Quake: Arena", "QW" => "Quake World", "UT" => "Unreal Tournament", "TB2" => "Tribes 2" ); // default ports for games var $defaultports = array( "HL" => "27015", "HL2" => "27015", "Q1" => "26000", "Q2" => "27910", "Q3" => "27960", "QW" => "27500", "UT" => "7777", "TB2" => "28000" ); // Activation commands var $commands = array( "HL" => array( "Serverinfo" => "detailsx00", "Playerlist" => "playersx00" ), "Q2" => array( "Serverinfo" => "statusx00" ), "Q3" => array( "Serverinfo" => "getstatusx00" ), "UT" => array( "Serverinfo" => "status", "Playerlist" => "status", "TheEnd" => "final" ) ); /** * Function gameinfo(GAMETYPE=string, ADDRESS=string, [PORT=string]) * The main function. Loads info on the server */ function gQuery($gametype ,$address, $port = "") { // Set the user provided connection settings $this->cgametype = $gametype; $this->caddress = $address; // Set the port to default if not defined if ($ports != "") { $this->cport = $this->defaultports[$this->cgametype]; } else { $this->cport = $port; } // Make the connection $this->fp = fsockopen("udp://" . $this->caddress, $this->cport, &$errno, &$errstr, 4); if (!$this->fp) { //unable to connect to host $this->serverinfo["name"] = "Error connecting to server"; $this->serverinfo["address"] = $this->caddress; $this->addError("gQuery// had an error connecting to " . $this->caddress . ":" . $this->cport . "($errno - $errstr)"); } else { // Run the appropriate parser. eval("$this->parseServerstat" . $this->cgametype . "();"); // Close the connection fclose($this->fp); } // Put up the list of variabes so ppl can see what info is available $this->systeminfo["gamevariables_count"] = 0; while (list($key) = each ($this->serverinfo)) { if ($this->systeminfo["gamevariables_count"] != 0) $this->systeminfo["gamevariables"] .= ", "; $this->systeminfo["gamevariables"] .= $key; $this->systeminfo["gamevariables_count"]++; } $this->systeminfo["playervariables_count"] = 0; if ( $this->serverinfo["player"] != 0 ) { while (list($key) = each ($this->playerinfo[0])) { if ($this->systeminfo["playervariables_count"] != 0) $this->systeminfo["playervariables"] .= ", "; $this->systeminfo["playervariables"] .= $key; $this->systeminfo["playervariables_count"]++; } } } /** * Function about() * Displays info about this class. */ function about() { echo "<P><B>gQuery// gameserver info class. Version 0.4.0. n"; echo "<BR>© 2001 tar Borgrsson <I>([email protected])</I> n"; echo "<BR>http://gdome.sourceforge.net/</B></P> n"; } /** * Function debug() * Mostly just for debugging. Displays all kinds of info. */ function debug() { echo "<TABLE cellspacing='1' cellpadding='10'><TR><TD bgcolor='lightgreen'>"; echo "<B>Debug Info:</B><BLOCKQUOTE>"; echo "Address: " . $this->caddress . "<BR>n"; echo "Port: " . $this->cport . "<BR>n"; echo "Gametype: " . $this->cgametype . " <I>(" . $this->gametypes[$this->cgametype] . ")</I><BR>n"; echo "Server Vars: " . $this->systeminfo["gamevariables_count"] . " vars <I>(" . $this->systeminfo["gamevariables"] . ")</I><BR>n"; echo "Player Vars: " . $this->systeminfo["playervariables_count"] . " vars <I>(" . $this->systeminfo["playervariables"] . ")</I><BR>n"; echo "<B>Errors:</B><OL>"; for ($i = 0; $i <= sizeof($this->errors)-1; $i++) { echo "<LI> " . $this->errors[$i] . "n"; } echo "</OL>"; echo "</BLOCKQUOTE>"; echo "</TD></TR></TABLE>"; } /** * Function addError(ERRORMSG=string, [HALT=bool]) * Adds an error into the error array */ function addError($errorMsg, $halt = false) { // Check wether to stop the script or not if (!$halt) { $this->errors[count($this->errors)] = "WARNING: " . $errorMsg; } else { $this->errors[count($this->errors)] = "ERROR: " . $errorMsg; exit; } } /** * Function parseServerstatHL() * Requests the server info from the server and parses it down */ function parseServerstatHL() { fwrite($this->fp,$this->commands[$this->cgametype]["Serverinfo"]); // Get rid of the header $header = fread($this->fp,5); // Get server address and Port $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ($str == "x00") $do = false; } $this->serverinfo["address"] = $result; // Get server name $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ($str == "x00") $do = false; } $this->serverinfo["name"] = $result; // Get server map $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ($str == "x00") $do = false; } $this->serverinfo["map"] = $result; // Get server moddir $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ($str == "x00") $do = false; } $this->serverinfo["moddir"] = $result; // Get server modname $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ($str == "x00") $do = false; } $this->serverinfo["modname"] = $result; // Get number of players online $str = fread($this->fp,1); $this->serverinfo["players"] = ord($str); // Get maximum number of online player $str = fread($this->fp,1); $this->serverinfo["maxplayers"] = ord($str); // Get server protocol $str = fread($this->fp,1); $this->serverinfo["protocol"] = ord($str); // Get Type of server $str = fread($this->fp,1); if ($str == "l") { $this->serverinfo["typeofserver"] = "Listen"; } else if ($str == "d") { $this->serverinfo["typeofserver"] = "Deticated"; } else { $this->serverinfo["typeofserver"] = "Unknown"; } // Get server OS $str = fread($this->fp,1); if ($str == "l") { $this->serverinfo["serveros"] = "Linux"; } else if ($str == "w") { $this->serverinfo["serveros"] = "Win32"; } else { $this->serverinfo["serveros"] = "Unknown"; } // Get wether server locked or not $str = fread($this->fp,1); if (ord($str) == 1) { $this->serverinfo["locked"] = "true"; } else { $this->serverinfo["locked"] = "false"; } // Get the unknown thing // Don't know what this variable stands for // Please send me info if you find out $str = fread($this->fp,1); $this->serverinfo["unknown"] = ord($str); // Get the URL of the mod $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ($str == "x00") $do = false; } $this->serverinfo["modurl"] = $result; // Then get the Playerinfo // We will trust that the connection is ok. fclose($this->fp); $this->fp = fsockopen("udp://" . $this->caddress, $this->cport, &$errno, &$errstr, 4); fwrite($this->fp,$this->commands[$this->cgametype]["Playerlist"]); //wait till we receive a header and store it (isn't used at the moment) $str = fread($this->fp, 6); $top = ord($str[5]); $this->pcount = $top; //socket_set_blocking($this->fp,0); for($usr = 0; $usr <= ($top-1); $usr++) { $do = true; // Get player id $str = fread($this->fp, 1); $this->playerinfo[$usr]["index"] = ord($str); // Get player name $temp = ""; while($do) { $str = fread($this->fp,1); if($str == "x00") { $do = false; } else { $temp .= $str; } } $this->playerinfo[$usr]["name"] = $temp; // Get player frags $tot = 0; $str = fread($this->fp, 1); $tot += ord($str); $str = fread($this->fp, 1); $tot += ord($str) * 256; $str = fread($this->fp, 1); $tot += ord($str) * 65536; $str = fread($this->fp, 1); $tot += ord($str) * 16777216; if($tot >= 16777216) { // ie is negative $tot -= (4294967296); } $this->playerinfo[$usr]["frags"] = $tot; // Get player time $bin = ''; for($loop = 0; $loop <= 3; $loop++) { $bin = str_pad(decbin(ord(fread($this->fp, 1))), 8, '0', STR_PAD_LEFT).$bin; } // get sign $sign = bindec(substr($bin, 0, 1)); // get exponent and adjust for special case and bias $exponent = bindec(substr($bin, 1, 8)); $exponent = ($exponent)? $exponent - 127 : $exponent; if($exponent) { // get the binary number of the mantissa $int = bindec('1'.substr($bin, 9, $exponent)); $dec = bindec(substr($bin, 9 + $exponent)); $time = "$int.$dec"; $this->playerinfo[$usr]["time"] = number_format($time / 60, 2); } else { $this->playerinfo[$usr]["time"] = "0.0"; } } } /** * Function parseServerstatQ2() * Requests the server info from the server and parses it down */ function parseServerstatQ2() { fwrite($this->fp,$this->commands[$this->cgametype]["Serverinfo"]); // Get rid of the header $header = fread($this->fp,10); // Read in the info from the server. $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ( $str == "n" ) $do = false; } $this->serverinfo["allinfo"] = $result; // Now recieve the player info socket_set_blocking($this->fp,0); echo $temp; $do = true; $i = 0; while ($do) { $temp = fgets($this->fp, 100); if ($temp == "") { $do = false; } else { $tempplayers[$i] = $temp; } $i++; } $this->pcount = sizeof($tempplayers); $this->serverinfo["players"] = sizeof($tempplayers); // Now resolve the server info $temparray = explode ("", $this->serverinfo["allinfo"]); $i = 1; while($i <= sizeof($temparray)) { $this->serverinfo[$temparray[$i++]] = $temparray[$i++]; } // Resolve the player info $i = 0; while($i <= $this->pcount-1) { $this->playerinfo[$i]["index"] = "$i"; $temparray = explode (""", $tempplayers[$i]); $this->playerinfo[$i]["name"] = $temparray[1]; /* $this->playerinfo[$i]["namecolored"] = $temparray[1]; //Remove colortags $result = ""; $b = 0; while($b <= strlen($temparray[1])) { $str = substr($temparray[1], $b, 1); if ($str == "^") { $b++; } else { $result .= $str; } $b++; } $this->playerinfo[$i]["name"] = $result; */ $temparray2 = explode (" ", $temparray[0]); $this->playerinfo[$i]["frags"] = $temparray2[0]; $this->playerinfo[$i]["ping"] = $temparray2[1]; $i++; } // Standardize. For easyer info. $this->serverinfo["address"] = $this->caddress . ":" . $this->cport; $this->serverinfo["name"] = $this->serverinfo["hostname"]; $this->serverinfo["moddir"] = $this->serverinfo["gamename"]; $this->serverinfo["maxplayers"] = $this->serverinfo["maxclients"]; $this->serverinfo["map"] = $this->serverinfo["mapname"]; $this->serverinfo["typeofserver"] = "Unknown"; $this->serverinfo["serveros"] = "Unknown"; if ($this->serverinfo["needpass"] == 1) { $this->serverinfo["locked"] = "true"; } else { $this->serverinfo["locked"] = "false"; } } /** * Function parseServerstatQ3() * Requests the server info from the server and parses it down */ function parseServerstatQ3() { fwrite($this->fp,$this->commands[$this->cgametype]["Serverinfo"]); $header=fgets($this->fp, 20); //now we get the the servers statusdata in one line $this->serverinfo["allinfo"] = fgets($this->fp, 1500); // echo $returnstring; // DEBUG $temparray = explode ("", $this->serverinfo["allinfo"]); $i = 1; while($i <= sizeof($temparray)) { $this->serverinfo[$temparray[$i++]] = $temparray[$i++]; } // Now recieve the player info socket_set_blocking($this->fp,0); $do = true; $i = 0; while ($do) { $temp = fgets($this->fp, 100); if ($temp == "") { $do = false; } else { $tempplayers[$i] = $temp; } $i++; } $this->pcount = sizeof($tempplayers); // Resolve the player info $i = 0; while($i <= $this->pcount-1) { $this->playerinfo[$i]["index"] = "$i"; $temparray = explode (""", $tempplayers[$i]); $this->playerinfo[$i]["namecolored"] = $temparray[1]; //Remove colortags $result = ""; $b = 0; while($b <= strlen($temparray[1])) { $str = substr($temparray[1], $b, 1); if ($str == "^") { $b++; } else { $result .= $str; } $b++; } $this->playerinfo[$i]["name"] = $result; $temparray2 = explode (" ", $temparray[0]); $this->playerinfo[$i]["frags"] = $temparray2[0]; $this->playerinfo[$i]["ping"] = $temparray2[1]; $i++; } // Standardize. For easyer info. $this->serverinfo["address"] = $this->caddress . ":" . $this->cport; $this->serverinfo["name"] = $this->serverinfo["sv_hostname"]; $this->serverinfo["moddir"] = $this->serverinfo["gamename"]; $this->serverinfo["players"] = $this->serverinfo["sv_privateClients"]; $this->serverinfo["maxplayers"] = $this->serverinfo["sv_maxclients"]; $this->serverinfo["map"] = $this->serverinfo["mapname"]; $this->serverinfo["typeofserver"] = "Unknown"; $this->serverinfo["serveros"] = "Unknown"; $this->serverinfo["players"] = $this->pcount; if ($this->serverinfo["g_needpass"] == 1) { $this->serverinfo["locked"] = "true"; } else { $this->serverinfo["locked"] = "false"; } } /** * Function parseServerstatUT() * Requests the server info from the server and parses it down */ function parseServerstatUT() { fwrite($this->fp,$this->commands[$this->cgametype]["Serverinfo"]); // Get server address and Port $do = true; $result = ""; while($do) { $str = fread($this->fp,1); $result .= $str; if ( substr($result,strlen($result)-7) == $this->commands[$this->cgametype]["TheEnd"] ) $do = false; } $this->serverinfo["allinfo"] = $result; // Remove the final from the var list $this->serverinfo["allinfo"] = substr($this->serverinfo["allinfo"],0,strlen($this->serverinfo["allinfo"])-7); // Now resolve the info $temparray = explode ("", $this->serverinfo["allinfo"]); $i = 1; while($i <= sizeof($temparray)) { $this->serverinfo[$temparray[$i++]] = $temparray[$i++]; } // Standardize. For easyer info. $this->serverinfo["address"] = $this->caddress . ":" . $this->cport; $this->serverinfo["name"] = $this->serverinfo["hostname"]; $this->serverinfo["modname"] = $this->serverinfo["gamename"]; $this->serverinfo["players"] = $this->serverinfo["numplayers"]; $this->serverinfo["map"] = strtolower($this->serverinfo["mapname"]); $this->serverinfo["version"] = $this->serverinfo["gamever"]; $this->serverinfo["typeofserver"] = "Unknown"; $this->serverinfo["serveros"] = "Unknown"; if ($this->serverinfo["password"] != "False") { $this->serverinfo["locked"] = "true"; } else { $this->serverinfo["locked"] = "false"; } // Get those users fixed up for($i=0; $i <= $this->serverinfo["numplayers"]; $i++) { $this->playerinfo[$i]["index"] = $i; $this->playerinfo[$i]["name"] = $this->serverinfo["player_".$i]; $this->playerinfo[$i]["ping"] = $this->serverinfo["ping_".$i]; $this->playerinfo[$i]["frags"] = $this->serverinfo["frags_".$i]; $this->playerinfo[$i]["team"] = $this->serverinfo["team_".$i]; $this->playerinfo[$i]["skin"] = $this->serverinfo["skin_".$i]; $this->playerinfo[$i]["mesh"] = $this->serverinfo["mesh_".$i]; $this->playerinfo[$i]["face"] = $this->serverinfo["face_".$i]; $this->playerinfo[$i]["ngsecret"] = $this->serverinfo["ngsecret_".$i]; //Unset those variables so the will stop being in the way. unset( $this->serverinfo["player_".$i] ); unset( $this->serverinfo["ping_".$i] ); unset( $this->serverinfo["frags_".$i] ); unset( $this->serverinfo["team_".$i] ); unset( $this->serverinfo["skin_".$i] ); unset( $this->serverinfo["mesh_".$i] ); unset( $this->serverinfo["face_".$i] ); unset( $this->serverinfo["ngsecret_".$i] ); unset( $this->serverinfo[""] ); } } } ?>