by s0beit:
I honestly did not know where to put this.
core.php
PHP Code:
<?php
if( class_exists( 'CUDPQuery' ) == false )
{
include( 'udp.php' );
}
function Gamespy_Query( $host, $port, $si = false, $pi = false, $ti = false )
{
$ra = array();
$fp = new CUDPQuery( $host, $port, 5, UDP_MODE_SOCKET );
if( $fp->Connect() == FALSE )
{
return FALSE;
}
$GAMESPY_HEADER = "\xFE\xFD";
$GAMESPY_DELIMITER = "\x00";
$GAMESPY_PINGVALUE = "1337";
$GAMESPY_SERVERINFO = ( $si == true ) ? "\xFF" : "\x00";
$GAMESPY_PLAYERINFO = ( $pi == true ) ? "\xFF" : "\x00";
$GAMESPY_TEAMINFO = ( $ti == true ) ? "\xFF" : "\x00";
$fp->Send( $GAMESPY_HEADER . $GAMESPY_DELIMITER . $GAMESPY_PINGVALUE . $GAMESPY_SERVERINFO . $GAMESPY_PLAYERINFO . $GAMESPY_TEAMINFO );
$REPLY_RAW = $fp->Read( 2048 );
$REPLY_DELIMITER = substr( $REPLY_RAW, 0, 1 );
$REPLY_PINGVALUE = substr( $REPLY_RAW, 1, 5 );
$REPLY_BODY = substr( $REPLY_RAW, 5, strlen( $REPLY_RAW ) );
$fp->Disconnect();
if( $si )
{
$BODY_REPLY_SPLIT_DELIM = explode( chr( 0 ), $REPLY_BODY );
$i = 0;
while( !empty( $BODY_REPLY_SPLIT_DELIM[ $i ] ) )
{
$ra[ $BODY_REPLY_SPLIT_DELIM[ $i ] ] = $BODY_REPLY_SPLIT_DELIM[ $i + 1 ];
$i += 2;
}
}
if( $pi )
{
if( $si )
{
if( $ra[ 'numplayers' ] > 0 )
{
$REPLY_EXTRA_INFORMATION = explode( chr( 0 ) . chr( 0 ) . pack( "c*", $ra[ 'numplayers' ] ), $REPLY_BODY );
$REPLY_EXTRA_INFORMATION = $REPLY_EXTRA_INFORMATION[1];
$REPLY_PARAMETERS = explode( ( chr( 0 ) . chr( 0 ) ), $REPLY_EXTRA_INFORMATION );
$REPLY_PARAMETERS = $REPLY_PARAMETERS[0];
$REPLY_PARAMETERS = explode( chr( 0 ), $REPLY_PARAMETERS );
$PLAYER_INFO = explode( chr( 0 ) . chr( 0 ), $REPLY_EXTRA_INFORMATION );
$PLAYER_INFO = substr( str_replace( $PLAYER_INFO[0], '', $REPLY_EXTRA_INFORMATION ), 2, 1024 );
$ra['InfoParams'] = $REPLY_PARAMETERS;
$ra['PlayerInfo'] = array();
$PLAYER_INFO_PARAMS = explode( chr( 0 ), $PLAYER_INFO );
}
else
{
//later you can check 'isset' or 'is_array'
unset( $ra[ 'InfoParams' ] );
unset( $ra[ 'PlayerInfo' ] );
}
}
else
{
$REPLY_BODY = substr( $REPLY_RAW, 7, strlen( $REPLY_RAW ) );
$ra[ 'InfoParams' ] = explode( chr( 0 ) . chr( 0 ), $REPLY_BODY, 2 );
$PLAYER_INFO = $ra[ 'InfoParams' ][ 1 ];
$ra[ 'InfoParams' ] = $ra[ 'InfoParams' ][ 0 ];
$ra[ 'InfoParams' ] = explode( chr( 0 ), $ra[ 'InfoParams' ] );
$PLAYER_INFO_PARAMS = explode( chr( 0 ), $PLAYER_INFO );
$ra['PlayerInfo'] = array();
}
if( isset( $ra[ 'InfoParams' ] ) && isset( $ra[ 'PlayerInfo' ] ) )
{
if( empty( $PLAYER_INFO_PARAMS ) == false )
{
for( $i = 0; $i < count( $PLAYER_INFO_PARAMS ); $i += 4 )
{
$PlayerInfoNew = array();
for( $p = 0; $p < count( $ra[ 'InfoParams' ] ); $p++ )
{
$PlayerInfoNew[ $ra[ 'InfoParams' ][ $p ] ] = $PLAYER_INFO_PARAMS[ $p + $i ];
}
array_push( $ra['PlayerInfo'], $PlayerInfoNew );
if( empty( $PLAYER_INFO_PARAMS[ $i + 4 ][0] ) ) break;
}
}
}
}
return $ra;
}
?>
udp.php
PHP Code:
<?php
define( 'UDP_MODE_FSOCKOPEN', 0 );
define( 'UDP_MODE_PFSOCKOPEN', 1 );
define( 'UDP_MODE_SOCKET', 2 );
class CUDPQuery
{
var $host;
var $port;
var $timeout;
var $mode;
var $sock;
function CUDPQuery( $host, $port, $timeout = 5, $mode = UDP_MODE_FSOCKOPEN )
{
$this->host = $host;
$this->port = $port;
$this->timeout = $timeout;
$this->mode = $mode;
}
function GetModeString()
{
$r = array( "fsockopen", "pfsockopen", "socket_create" );
return $r[ $this->mode ];
}
function Connect()
{
switch( $this->mode )
{
case UDP_MODE_FSOCKOPEN:
{
$this->sock = fsockopen( 'udp://' . $this->host, $this->port, $ErrorNumber, $ErrorString, $this->timeout );
break;
}
case UDP_MODE_PFSOCKOPEN:
{
$this->sock = pfsockopen( 'udp://' . $this->host, $this->port, $ErrorNumber, $ErrorString, $this->timeout );
break;
}
case UDP_MODE_SOCKET:
{
$this->sock = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );
if( $this->sock != FALSE )
{
socket_set_option( $this->sock, SOL_SOCKET, SO_BROADCAST, 1 );
socket_connect( $this->sock, $this->host, $this->port );
}
break;
}
}
return ( $this->sock != FALSE );
}
function Send( $data )
{
$returnData = '';
switch( $this->mode )
{
case UDP_MODE_FSOCKOPEN:
case UDP_MODE_PFSOCKOPEN:
{
$returnData = fwrite( $this->sock, $data, strlen( $data ) );
break;
}
case UDP_MODE_SOCKET:
{
$returnData = socket_write( $this->sock, $data );
break;
}
}
return $returnData;
}
function Read( $length )
{
$returnData = '';
switch( $this->mode )
{
case UDP_MODE_FSOCKOPEN:
case UDP_MODE_PFSOCKOPEN:
{
$returnData = fread( $this->sock, $length );
break;
}
case UDP_MODE_SOCKET:
{
$returnData = socket_read( $this->sock, $length, PHP_BINARY_READ );
break;
}
}
return $returnData;
}
function Disconnect()
{
switch( $this->mode )
{
case UDP_MODE_FSOCKOPEN:
case UDP_MODE_PFSOCKOPEN:
{
fclose( $this->sock );
break;
}
case UDP_MODE_SOCKET:
{
socket_close( $this->sock );
break;
}
}
}
};
?>
Example.....
PHP Code:
$ARMA2_HOST_VALUE = '64.120.46.26';
$ARMA2_PORT_VALUE = '1337';
$ServerInformation =
Gamespy_Query( $ARMA2_HOST_VALUE, $ARMA2_PORT_VALUE, true, true, true );
var_dump( $ServerInformation );
Depending on the settings, it would look a little something like this on output
[Arma2] (my server)
Code:
array(28) {
["gamever"]=>
string(10) "1.05.62014"
["hostname"]=>
string(20) "RAGING WAR COOP 24/7"
["mapname"]=>
string(9) "Chernarus"
["gametype"]=>
string(4) "COOP"
["numplayers"]=>
string(2) "16"
["numteams"]=>
string(1) "0"
["maxplayers"]=>
string(2) "18"
["gamemode"]=>
string(11) "openplaying"
["timelimit"]=>
string(2) "15"
["password"]=>
string(1) "0"
["param1"]=>
string(1) "1"
["param2"]=>
string(4) "1000"
["currentVersion"]=>
string(3) "105"
["requiredVersion"]=>
string(3) "105"
["mod"]=>
string(2) "CA"
["equalModRequired"]=>
string(1) "0"
["gameState"]=>
string(1) "7"
["dedicated"]=>
string(1) "1"
["platform"]=>
string(3) "win"
["language"]=>
string(5) "65545"
["difficulty"]=>
string(1) "1"
["mission"]=>
string(21) "EVO~BLUE Revive V3.92"
["gamename"]=>
string(7) "arma2pc"
["sv_battleye"]=>
string(1) "0"
["verifySignatures"]=>
string(1) "0"
["signatures"]=>
string(0) ""
["InfoParams"]=>
array(4) {
[0]=>
string(7) "player_"
[1]=>
string(5) "team_"
[2]=>
string(6) "score_"
[3]=>
string(7) "deaths_"
}
["PlayerInfo"]=>
array(16) {
[0]=>
array(4) {
["player_"]=>
string(5) "roman"
["team_"]=>
string(0) ""
["score_"]=>
string(3) "-34"
["deaths_"]=>
string(2) "28"
}
[1]=>
array(4) {
["player_"]=>
string(5) "Radek"
["team_"]=>
string(0) ""
["score_"]=>
string(3) "163"
["deaths_"]=>
string(2) "33"
}
[2]=>
array(4) {
["player_"]=>
string(5) "disco"
["team_"]=>
string(0) ""
["score_"]=>
string(3) "115"
["deaths_"]=>
string(2) "19"
}
[3]=>
array(4) {
["player_"]=>
string(12) "Stalker(RUS)"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "84"
["deaths_"]=>
string(2) "14"
}
[4]=>
array(4) {
["player_"]=>
string(11) "Stacy's Mom"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "87"
["deaths_"]=>
string(2) "11"
}
[5]=>
array(4) {
["player_"]=>
string(6) "mischl"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "20"
["deaths_"]=>
string(1) "4"
}
[6]=>
array(4) {
["player_"]=>
string(4) "Uone"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "44"
["deaths_"]=>
string(1) "6"
}
[7]=>
array(4) {
["player_"]=>
string(16) "KuboslavXIII(cz)"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "21"
["deaths_"]=>
string(2) "10"
}
[8]=>
array(4) {
["player_"]=>
string(7) "colonyt"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "12"
["deaths_"]=>
string(1) "2"
}
[9]=>
array(4) {
["player_"]=>
string(12) "Macculloch's"
["team_"]=>
string(0) ""
["score_"]=>
string(1) "9"
["deaths_"]=>
string(1) "3"
}
[10]=>
array(4) {
["player_"]=>
string(7) "Surgeon"
["team_"]=>
string(0) ""
["score_"]=>
string(1) "0"
["deaths_"]=>
string(1) "1"
}
[11]=>
array(4) {
["player_"]=>
string(7) "Stryker"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "11"
["deaths_"]=>
string(1) "0"
}
[12]=>
array(4) {
["player_"]=>
string(9) "-=GunnY=-"
["team_"]=>
string(0) ""
["score_"]=>
string(1) "0"
["deaths_"]=>
string(1) "1"
}
[13]=>
array(4) {
["player_"]=>
string(8) "deethree"
["team_"]=>
string(0) ""
["score_"]=>
string(2) "56"
["deaths_"]=>
string(1) "5"
}
[14]=>
array(4) {
["player_"]=>
string(10) "Nitemare26"
["team_"]=>
string(0) ""
["score_"]=>
string(1) "0"
["deaths_"]=>
string(1) "0"
}
[15]=>
array(4) {
["player_"]=>
string(10) "RudyFaasse"
["team_"]=>
string(0) ""
["score_"]=>
string(1) "6"
["deaths_"]=>
string(1) "0"
}
}
}
[Halo]
Code:
array(18) {
["hostname"]=>
string(13) "AEM_MEXICANOS"
["gamever"]=>
string(13) "01.00.01.0580"
["hostport"]=>
string(0) ""
["maxplayers"]=>
string(2) "16"
["password"]=>
string(1) "0"
["mapname"]=>
string(10) "sidewinder"
["dedicated"]=>
string(1) "1"
["gamemode"]=>
string(11) "openplaying"
["game_classic"]=>
string(1) "0"
["numplayers"]=>
string(2) "16"
["gametype"]=>
string(3) "CTF"
["teamplay"]=>
string(1) "1"
["gamevariant"]=>
string(4) "Nub2"
["fraglimit"]=>
string(1) "3"
["player_flags"]=>
string(15) "2032152580,1094"
["game_flags"]=>
string(2) "65"
["InfoParams"]=>
array(4) {
[0]=>
string(7) "player_"
[1]=>
string(6) "score_"
[2]=>
string(5) "ping_"
[3]=>
string(5) "team_"
}
["PlayerInfo"]=>
array(16) {
[0]=>
array(4) {
["player_"]=>
string(6) "åndre$"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[1]=>
array(4) {
["player_"]=>
string(9) "@lej@ndr@"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[2]=>
array(4) {
["player_"]=>
string(7) "Fortune"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[3]=>
array(4) {
["player_"]=>
string(5) "SEBAS"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[4]=>
array(4) {
["player_"]=>
string(9) "G@TO MI@U"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[5]=>
array(4) {
["player_"]=>
string(6) "PANTRO"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[6]=>
array(4) {
["player_"]=>
string(11) "-AEM-AIDVEL"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[7]=>
array(4) {
["player_"]=>
string(9) "Baby Girl"
["score_"]=>
string(1) "1"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[8]=>
array(4) {
["player_"]=>
string(11) "{CO}shamwow"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[9]=>
array(4) {
["player_"]=>
string(11) "AEM´´ZONO´´"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[10]=>
array(4) {
["player_"]=>
string(3) "Mac"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[11]=>
array(4) {
["player_"]=>
string(8) "Fetichin"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[12]=>
array(4) {
["player_"]=>
string(6) "New001"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[13]=>
array(4) {
["player_"]=>
string(6) "Ali-Te"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
[14]=>
array(4) {
["player_"]=>
string(10) "»«HÅÇk£Rsµ"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "0"
}
[15]=>
array(4) {
["player_"]=>
string(5) "tesak"
["score_"]=>
string(1) "0"
["ping_"]=>
string(0) ""
["team_"]=>
string(1) "1"
}
}
}
Many other games using the gamespy 2 protocol will reply and it will get clean results.
It outputs everything almost without fail under every conditional test i have put it under, if you find any bugs please tell me.