0 Members and 2 Guests are viewing this topic.
constPLAYERNAME_CHARS = 24;TMsg_Refresh = packed recordName : array[1..32] of string[PLAYERNAME_CHARS];Team : array[1..32] of byte;Kills : array[1..32] of word;Deaths : array[1..32] of word;Ping : array[1..32] of byte;Number : array[1..32] of byte;IP : array[1..32,1..4] of byte;TeamScore : array[1..4] of word;MapName : string[16];TimeLimit, CurrentTime : integer;KillLimit : word;GameStyle : byte;end;
typedef unsigned char byte;typedef unsigned short word;typedef unsigned long dword;#pragma pack(push, 1)struct RefreshPacket { struct { byte iLen; char cName[24]; } sName[32]; byte iTeam[32]; word iKills[32]; word iDeaths[32]; byte iPing[32]; byte iNumber[32]; union { dword iLong; byte iPiece[4]; } uIp[32]; word iTeamScore[4]; struct { byte iLen; char cMap[16]; } sMap; dword iTimeLimit; dword iCurrentTime; word iKillLimit; byte iGameStyle;};#pragma pack(pop)
Private Type RefreshPacket PlayerName(31) As String Team(31) As Byte Kills(31) As Long Deaths(31) As Long Ping(31) As Byte Number(31) As Byte IP(31, 3) As Byte TeamScore(3) As Long MapName As String TimeLimit As Double CurrentTime As Double KillLimit As Long GameStyle As ByteEnd TypePrivate Function parseRefreshPacket(packet() As Byte, Optional offset As Byte = 0) As RefreshPacket Dim i As Integer Dim k As Integer Dim j As Integer Dim length As Byte i = offset With parseRefreshPacket For k = 0 To 31 length = packet(i) i = i + 1 For j = 0 To 23 .PlayerName(k) = .PlayerName(k) + Chr(packet(i)) i = i + 1 Next j .PlayerName(k) = Left(.PlayerName(k), length) Next k For k = 0 To 31 .Team(k) = packet(i) i = i + 1 Next k For k = 0 To 31 .Kills(k) = packet(i) + (packet(i + 1) * 256&) i = i + 2 Next k For k = 0 To 31 .Deaths(k) = packet(i) + (packet(i + 1) * 256&) i = i + 2 Next k For k = 0 To 31 .Ping(k) = packet(i) i = i + 1 Next k For k = 0 To 31 .Number(k) = packet(i) i = i + 1 Next k For k = 0 To 31 For j = 0 To 3 .IP(k, j) = packet(i) i = i + 1 Next j Next k For k = 0 To 3 .TeamScore(k) = packet(i) + (packet(i + 1) * 256&) i = i + 2 Next k length = packet(i) i = i + 1 For k = 0 To 15 .MapName = .MapName + Chr(packet(i)) i = i + 1 Next k .MapName = Left(.MapName, length) For k = 0 To 3 .TimeLimit = .TimeLimit + (packet(i) * (256& ^ k)) i = i + 1 Next k For k = 0 To 3 .CurrentTime = .CurrentTime + (packet(i) * (256& ^ k)) i = i + 1 Next k .KillLimit = packet(i) + (packet(i + 1) * 256&) i = i + 2 .GameStyle = packet(i) End WithEnd FunctionPrivate Sub Winsock1_DataArrival(ByVal bytesTotal As Long) Static refresh As Boolean Dim tempstring As String Dim Buffer() As Byte dim packet as RefreshPacket Winsock1.GetData Buffer tempstring = StrConv(Buffer, vbUnicode) If Left(tempstring, 7) = "REFRESH" Then If Len(tempstring) = 9 Then refresh = True Else packet = parseRefreshPacket(Buffer, 9) End If ElseIf refresh And UBound(Buffer) = 1187 Then packet = parseRefreshPacket(Buffer) refresh = False Else Text1.Text = Text1.Text & tempstring End If Text1.SelStart = Len(Text1.Text) 'todo: output the refresh packet data somewhereEnd Sub
<?php function GetSoldatInfo(&$sock) { if (!$sock) return false; $info = array( 'gamemode' => 0, 'teammode' => false, 'pointmode' => false, 'players' => 0, 'spectators' => 0, 'map' => '', 'timelimit' => 0, 'currenttime' => 0, 'timeleft' => 0, 'limit' => 0, 'player' => array(), 'spectator' => array(), 'team' => array() ); // Temporary array for players $players = array(); for ($i = 0; $i < 32; $i++) { $players[$i] = array( 'name' => '', 'ip' => '', 'id' => 0, 'kills' => 0, 'deaths' => 0, 'team' => 0, 'ping' => 0 ); } // Get player names for ($i = 0; $i < 32; $i++) { $data = fread($sock, 25); $len = ord($data[0]); $players[$i]['name'] = substr($data, 1, $len); } // Get player teams for ($i = 0; $i < 32; $i++) { $data = fread($sock, 1); $players[$i]['team'] = ord($data); } // Get player kills for ($i = 0; $i < 32; $i++) { $data = unpack("v", fread($sock, 2)); $kills = $data[1]; $players[$i]['kills'] = $kills; } // Get player deaths for ($i = 0; $i < 32; $i++) { $data = unpack("v", fread($sock, 2)); $deaths = $data[1]; $players[$i]['deaths'] = $deaths; } // Get player pings for ($i = 0; $i < 32; $i++) { $data = fread($sock, 1); $players[$i]['ping'] = ord($data); } // Get player IDs for ($i = 0; $i < 32; $i++) { $data = fread($sock, 1); $players[$i]['id'] = ord($data); } // Get player IPs for ($i = 0; $i < 32; $i++) { $data = unpack("N", fread($sock, 4)); $players[$i]['ip'] = long2ip($data[1]); } // Get team scores for ($i = 1; $i < 5; $i++) { $data = unpack("v", fread($sock, 2)); $score = $data[1]; $info['team'][$i] = $score; } // Get map name $data = fread($sock, 17); $len = ord($data[0]); $info['map'] = substr($data, 1, $len); // Get time limit & current time, and form timeleft $data = unpack("V", fread($sock, 4)); $timelimit = $data[1]; $info['timelimit'] = $timelimit; $data = unpack("V", fread($sock, 4)); $currenttime = $data[1]; $info['currenttime'] = $timelimit - $currenttime; $timeleft = $currenttime; $temp = (floor($timeleft / 60) % 60); $info['timeleft'] = floor($timeleft / 3600) . ':' . ($temp < 10 ? '0' : '') . $temp; // Get kill limit $data = unpack("v", fread($sock, 2)); $limit = $data[1]; $info['limit'] = $limit; // Get gamestyle $data = fread($sock, 1); $gamestyle = ord($data); $info['gamemode'] = $gamestyle; if ($gamestyle == 2 || $gamestyle == 3 || $gamestyle == 5 || $gamestyle == 6) { $info['teammode'] = true; if ($gamestyle != 2) { $info['pointmode'] = true; } } if ($gamestyle != 2) { if ($gamestyle != 3 && $gamestyle != 5) { unset($info['team'][1]); unset($info['team'][2]); } unset($info['team'][3]); unset($info['team'][4]); } foreach ($players as $player) { if ($player['team'] < 5) { $info['players']++; $info['player'][] = $player; } else if ($player['team'] == 5) { $info['spectators']++; $info['spectator'][] = $player; } } return $info; }?>Example usage:<?php $s = @fsockopen("localhost", 23073); if ($s) { $info = array(); fputs($s, "password\n"); fputs($s, "REFRESH\n"); while(1) { $data = trim(fgets($s, 1024)); if (!$data) break; else if ($data == "REFRESH") { $info = GetSoldatInfo($s); break; } } fclose($s); // Make sure the REFRESH packet was received if ($info) { // You can now use the $info array to check different stuff from server, check the function for the array's elements // Remember that the gamemode value is a number, so to get the string do something like: $gamemodes = array( 0 => 'Deathmatch', 1 => 'Pointmatch', 2 => 'Teammatch', 3 => 'Capture The Flag', 4 => 'Rambomatch', 5 => 'Infiltration', 6 => 'Hold The Flag' ); $gamemode_str = $gamemodes[$info['gamemode']]; } }?>And another note, the $info['timeleft'] is actually a string, in form of mins:secs, because I only needed to use it in this form. If you need an integral value in seconds, or ticks, it's easy enough to edit to have it in that form.
alias -l SoldatRefreshEndTok return $+($1, $iif($1 != $null, $chr($3)), $2)alias SoldatRefreshSize return 1188alias SoldatRefresh { var %id = $1, %binvar = $2, %table = $3, %args = $4-, %players = $null, %kills = $null, %deaths = $null, %ips = $null, %pings = $null, %numbers = $null, %offsets = $null, %teams = $null, %i, %offset = 1, %tplayers = 0, %tspectators = 0, %teamnames = Alpha|Bravo|Charlie|Delta|Spectator if (%id == $null || %table == $null || $bvar(%binvar, 0) != $SoldatRefreshSize) { return $null } hfree -w %table $+ _* hmake %table $+ _info 7 ; Get player names %i = 1 while (%i <= 32) { var %len = $bvar(%binvar, %offset) inc %offset 1 %players = $SoldatRefreshEndTok(%players, $bvar(%binvar, %offset, %len).text, 10) %offsets = $SoldatRefreshEndTok(%offsets, $calc(%i - 1), 10) inc %offset 24 inc %i 1 } ; Get player teams %i = 1 var %deleted = 0 while (%i <= 32) { var %team = $bvar(%binvar, %offset) inc %offset 1 if (%team >= 0 && %team <= 5) { if (%team != 5) { inc %tplayers 1 } else { inc %tspectators 1 } %teams = $instok(%teams, %team, $calc($numtok(%teams, 10) + 1), 10) } else { %players = $deltok(%players, $calc(%i - %deleted), 10) %offsets = $deltok(%offsets, $calc(%i - %deleted), 10) inc %deleted 1 } inc %i 1 } var %total = %tplayers + %tspectators ; Get kills %i = 1 while (%i <= %total) { %kills = $SoldatRefreshEndTok(%kills, $bvar(%binvar, $calc(%offset + $gettok(%offsets, %i, 10) * 2)).word, 10) inc %i 1 } inc %offset $calc(32 * 2) ; Get deaths %i = 1 while (%i <= %total) { %deaths = $SoldatRefreshEndTok(%deaths, $bvar(%binvar, $calc(%offset + $gettok(%offsets, %i, 10) * 2)).word, 10) inc %i 1 } inc %offset $calc(32 * 2) ; Get ping %i = 1 while (%i <= %total) { %pings = $SoldatRefreshEndTok(%pings, $bvar(%binvar, $calc(%offset + $gettok(%offsets, %i, 10))), 10) inc %i 1 } inc %offset $calc(32) ; Get number %i = 1 while (%i <= %total) { %numbers = $SoldatRefreshEndTok(%numbers, $bvar(%binvar, $calc(%offset + $gettok(%offsets, %i, 10))), 10) inc %i 1 } inc %offset $calc(32) ; Get IPs %i = 1 while (%i <= %total) { %ips = $SoldatRefreshEndTok(%ips, $bvar(%binvar, $calc(%offset + $gettok(%offsets, %i, 10) * 4)).nlong, 10) inc %i 1 } inc %offset $calc(32 * 4) %i = 1 while (%i <= %tplayers) { hmake %table $+ _player $+ %i 7 inc %i } %i = 1 while (%i <= %tspectators) { hmake %table $+ _spectator $+ %i 7 inc %i } hadd %table $+ _info players %tplayers hadd %table $+ _info spectators %tspectators %i = 1 var %i_plr = 1, %i_spec = 1 while (%i <= %total) { var %team = $gettok(%teams, 1, 10) if (%team < 5) { hadd %table $+ _player $+ %i_plr name $gettok(%players, 1, 10) hadd %table $+ _player $+ %i_plr team $gettok(%teamnames, %team, 124) hadd %table $+ _player $+ %i_plr kills $gettok(%kills, 1, 10) hadd %table $+ _player $+ %i_plr deaths $gettok(%deaths, 1, 10) hadd %table $+ _player $+ %i_plr ping $gettok(%pings, 1, 10) hadd %table $+ _player $+ %i_plr number $gettok(%numbers, 1, 10) hadd %table $+ _player $+ %i_plr ip $gettok(%ips, 1, 10) inc %i_plr } else { hadd %table $+ _spectator $+ %i_spec name $gettok(%players, 1, 10) hadd %table $+ _spectator $+ %i_spec ping $gettok(%pings, 1, 10) hadd %table $+ _spectator $+ %i_spec number $gettok(%numbers, 1, 10) hadd %table $+ _spectator $+ %i_spec ip $gettok(%ips, 1, 10) inc %i_spec } %players = $deltok(%players, 1, 10) %teams = $deltok(%teams, 1, 10) %kills = $deltok(%kills, 1, 10) %deaths = $deltok(%deaths, 1, 10) %pings = $deltok(%pings, 1, 10) %numbers = $deltok(%numbers, 1, 10) %ips = $deltok(%ips, 1, 10) inc %i 1 } hmake %table $+ _teams 4 ; Get team scores %i = 1 while (%i <= 4) { var %team = $gettok(%teamnames, %i, 124) var %score = $bvar(%binvar, %offset).word inc %offset 2 hadd %table $+ _teams %team %score inc %i 1 } ; Get map name var %len = $bvar(%binvar, %offset) inc %offset 1 var %map = $bvar(%binvar, %offset, %len).text inc %offset 16 hadd %table $+ _info map %map ; Get time limit var %timelimit = $bvar(%binvar, %offset).long inc %offset 4 hadd %table $+ _info timelimit $calc(%timelimit / 3600) $+ :00 ; Get time left var %timeleft = $bvar(%binvar, %offset).long inc %offset 4 var %temp = $calc($floor($calc(%timeleft / 60)) % 60) hadd %table $+ _info timeleft $floor($calc(%timeleft / 3600)) $+ : $+ $iif(%temp < 10, 0 $+ %temp, %temp) ; Get kill limit var %killlimit = $bvar(%binvar, %offset).word inc %offset 2 hadd %table $+ _info killlimit %killlimit ; Get gamestyle var %gamestyle = $bvar(%binvar, %offset) hadd %table $+ _info gamestyle %gamestyle .signal %id %table %args}
<?php function GetSoldatInfo(&$sock) { if (!$sock) return false; $info = array( 'gamemode' => 0, 'teammode' => false, 'pointmode' => false, 'players' => 0, 'spectators' => 0, 'map' => '', 'timelimit' => 0, 'currenttime' => 0, 'timeleft' => 0, 'limit' => 0, 'player' => array(), 'spectator' => array(), 'team' => array() ); //Set player and spectator count to zero $info['players'] = 0; $info['spectators'] = 0; // Temporary array for players $players = array(); for ($i = 0; $i < 32; $i++) { $players[$i] = array( 'name' => '', 'ip' => '', 'id' => 0, 'kills' => 0, 'deaths' => 0, 'team' => 0, 'ping' => 0 ); } // Get player names for ($i = 0; $i < 32; $i++) { $data = fread($sock, 25); $len = ord($data[0]); $players[$i]['name'] = substr($data, 1, $len); } // Get player teams for ($i = 0; $i < 32; $i++) { $data = fread($sock, 1); $players[$i]['team'] = ord($data); } // Get player kills for ($i = 0; $i < 32; $i++) { $data = unpack("v", fread($sock, 2)); $kills = $data[1]; $players[$i]['kills'] = $kills; } // Get player deaths for ($i = 0; $i < 32; $i++) { $data = unpack("v", fread($sock, 2)); $deaths = $data[1]; $players[$i]['deaths'] = $deaths; } // Get player pings for ($i = 0; $i < 32; $i++) { $data = fread($sock, 1); $players[$i]['ping'] = ord($data); } // Get player IDs for ($i = 0; $i < 32; $i++) { $data = fread($sock, 1); $players[$i]['id'] = ord($data); } // Get player IPs for ($i = 0; $i < 32; $i++) { $data = unpack("N", fread($sock, 4)); $players[$i]['ip'] = long2ip($data[1]); } // Get team scores for ($i = 1; $i < 5; $i++) { $data = unpack("v", fread($sock, 2)); $score = $data[1]; $info['team'][$i] = $score; } // Get map name $data = fread($sock, 17); $len = ord($data[0]); $info['map'] = substr($data, 1, $len); // Get time limit & current time, and form timeleft $data = unpack("V", fread($sock, 4)); $timelimit = $data[1]; $info['timelimit'] = $timelimit; $data = unpack("V", fread($sock, 4)); $currenttime = $data[1]; $info['currenttime'] = $timelimit - $currenttime; $timeleft = $currenttime; $temp = (floor($timeleft / 60) % 60); $info['timeleft'] = floor($timeleft / 3600) . ':' . ($temp < 10 ? '0' : '') . $temp; // Get kill limit $data = unpack("v", fread($sock, 2)); $limit = $data[1]; $info['limit'] = $limit; // Get gamestyle $data = fread($sock, 1); $gamestyle = ord($data); $info['gamemode'] = $gamestyle; if ($gamestyle == 2 || $gamestyle == 3 || $gamestyle == 5 || $gamestyle == 6) { $info['teammode'] = true; if ($gamestyle != 2) { $info['pointmode'] = true; } } if ($gamestyle != 2) { if ($gamestyle != 3 && $gamestyle != 5) { unset($info['team'][1]); unset($info['team'][2]); } unset($info['team'][3]); unset($info['team'][4]); } foreach ($players as $player) { if ($player['team'] < 5) { $info['players']++; $info['player'][] = $player; } else if ($player['team'] == 5) { $info['spectators']++; $info['spectator'][] = $player; } } return $info; }?>
//Set player and spectator count to zero$info['players'] = 0;$info['spectators'] = 0;
'players' => 0, 'spectators' => 0,
socket = TCPsocket.open(server, port)socket.puts(password)while data=socket.gets.strip if data =~ /REFRESH/ refresh = "" socket.read(1188, refresh) info = refresh.unpack("CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24CA24C32S32S32C32C32C32C32C32C32S4CA16l2SC") names = Array.new(32, "") teams = Array.new(32, 0) kills = Array.new(32, 0) deaths = Array.new(32, 0) pings = Array.new(32, 0) numbers = Array.new(32, 0) ips =Array.new(32, Array.new(4, 0)) teamscore = Array.new(4, 0) mapname = "" timelimit = 0 currenttime = 0 killlimit = 0 gamestyle = 0 32.times do |i| names[i] = info[2*i+1].to_s[0, info[2*i]] teams[i] = info[i+64] kills[i] = info[i+96] deaths[i] = info[i+128] pings[i] = info[i+160] numbers[i] = info[i+192] 4.times do |j| ips[i][j] = info[(i-1)*4+j+224] end end 4.times do |i| teamscore[i] = info[i+352] end mapname = info[357][0,info[356]] timelimit = info[358] currenttime = info[359] killlimit = info[360] gamestyle = info[361] endend
proc Soldat:ParseRefresh packet { if { [string length $packet] != 1188 } { return } binary scan $packet "@800c32s32s32c32c32I32s4ca16iisc" teams kills deaths pings numbers ips scores map_len map timelimit timeleft limit gamemode set players {} set specs {} for { set i 0 } { $i < 32 } { incr i } { set team [lindex $teams $i] if {$team != -1} { binary scan $packet "@[expr $i*25]ca24" name_len name set ip [lindex $ips $i] set ip [join [list [expr ($ip >> 24) & 0xFF] [expr ($ip >> 16) & 0xFF] [expr ($ip >> 8) & 0xFF] [expr $ip & 0xFF]] .] array set player [list id [expr [lindex $numbers $i] & 0xFF] \ name [string range $name 0 [expr $name_len-1]] \ team $team \ kills [expr [lindex $kills $i] & 0xFFFF] \ deaths [expr [lindex $deaths $i] & 0xFFFF] \ ping [expr [lindex $pings $i] & 0xFF] \ ip $ip] if {$team < 5} { lappend players [array get player] } else { lappend specs [array get player] } } } for { set i 0 } { $i < 4 } { incr i } { set scores [lreplace $scores $i $i [expr [lindex $scores $i] & 0xFFFF]] } array set info [list gamemode $gamemode \ num_players [llength $players] \ num_specs [llength $specs] \ map [string range $map 0 [expr $map_len-1]] \ scores $scores \ limit $limit \ timelimit [expr $timelimit / 3600] \ timeleft [expr $timeleft / 60] \ players $players \ specs $specs] return [array get info]}
array set info [Soldat:ParseRefresh $refresh]
foreach player $info(players) { array set pinfo $player set name $pinfo(name)}
array set player [list id [expr [lindex $numbers $i] & 0xFF]]array set player [list name [string range $name 0 [expr $name_len-1]]]array set player [list team $team]array set player [list kills [expr [lindex $kills $i] & 0xFFFF]]array set player [list deaths [expr [lindex $deaths $i] & 0xFFFF]]array set player [list ping [expr [lindex $pings $i] & 0xFF]]array set player [list ip $ip]...set players [linsert $players end [array get player]]..set scores [lreplace $scores $i $i [expr [lindex $scores $i] & 0xFFFF]]
array set player [list id [expr [lindex $numbers $i] & 0xFF] \ name [string range $name 0 [expr $name_len-1]] \ team $team \ kills [expr [lindex $kills $i] & 0xFFFF] \ deaths [expr [lindex $deaths $i] & 0xFFFF] \ ping [expr [lindex $pings $i] & 0xFF] \ ip $ip]...lappend players [array get player]...lset scores $i [expr [lindex $scores $i] & 0xFFFF]
Wow, Tcl parser, nice. But there is a small mistake, for loop should go to 32. Also, instead of:
Also, instead of:Code: [Select]array set player [list id [expr [lindex $numbers $i] & 0xFF]]array set player [list name [string range $name 0 [expr $name_len-1]]]array set player [list team $team]array set player [list kills [expr [lindex $kills $i] & 0xFFFF]]array set player [list deaths [expr [lindex $deaths $i] & 0xFFFF]]array set player [list ping [expr [lindex $pings $i] & 0xFF]]array set player [list ip $ip]...set players [linsert $players end [array get player]]..set scores [lreplace $scores $i $i [expr [lindex $scores $i] & 0xFFFF]]you can useCode: [Select]array set player [list id [expr [lindex $numbers $i] & 0xFF] name [string range $name 0 [expr $name_len-1]] team $team kills [expr [lindex $kills $i] & 0xFFFF] deaths [expr [lindex $deaths $i] & 0xFFFF] ping [expr [lindex $pings $i] & 0xFF] ip $ip]...lappend players [array get player]...lset scores $i [expr [lindex $scores $i] & 0xFFFF]
array set player [list id [expr [lindex $numbers $i] & 0xFF] name [string range $name 0 [expr $name_len-1]] team $team kills [expr [lindex $kills $i] & 0xFFFF] deaths [expr [lindex $deaths $i] & 0xFFFF] ping [expr [lindex $pings $i] & 0xFF] ip $ip]...lappend players [array get player]...lset scores $i [expr [lindex $scores $i] & 0xFFFF]
<?php /** SOLDAT REFRESH AND REFRESHX PARSER* By: ramirez (c) 2007** Usage:* $info = ParseRefresh($packet);* or* $info = ParseRefreshX($packet);** Example:** <?php** include('soldat.refresh.php');** $socket = fsockopen('your.server.com', 23073);** fputs($socket, "PASSWORD\n");* fputs($socket, "REFRESH\n");* fputs($socket, "REFRESHX\n");** $version = null;* while ($data = trim(fgets($socket, 1024))) {* if (preg_match('/^Server Version: (.+)$/', $data, $match)) {* $version = $match[1];* }* else if ($data == 'REFRESH') {* $info = ParseRefresh(fread($socket, REFRESH_PACKET_SIZE), $version);* print_r($info);* }* else if ($data == 'REFRESHX') {* $info = ParseRefresh(fread($socket, RefreshXSize($version)), $version);* print_r($info);* break;* }* }** fclose($socket);** ?>**/ define('REFRESH_PACKET_SIZE', 1188); function RefreshXSize($version = '2.6.5'){ if ($version >= '2.6.5') return 1608; return 1576;} function ParseRefresh(&$packet, $version = '2.6.5') { if (strlen($packet) == REFRESH_PACKET_SIZE) { $refreshx = false; } else if (strlen($packet) == RefreshXSize($version)) { $refreshx = true; } else { return false; } $info = array( 'gamemode' => 0, 'players' => 0, 'spectators' => 0, 'map' => '', 'timelimit' => 0, 'currenttime' => 0, 'timeleft' => 0, 'limit' => 0, 'player' => array(), 'spectator' => array(), 'team' => array() ); if ($refreshx) { $info = array_merge($info, array( 'maxplayers' => 0, 'maxspecs' => 0, 'nextmap' => '', 'passworded' => false, 'redflag' => array(), 'blueflag' => array() )); } $players = array(); for ($i = 0; $i < 32; $i++) { $players[$i] = array( 'name' => '', 'ip' => '', 'id' => 0, 'kills' => 0, 'caps' => 0, 'deaths' => 0, 'team' => 0, 'ping' => 0 ); if ($refreshx) { $players[$i] = array_merge($players[$i], array( 'x' => 0, 'y' => 0 )); } } $pos = 800; $teams = unpack('C*', substr($packet, $pos, 32)); $pos += 32; $kills = unpack('v*', substr($packet, $pos, 64)); $pos += 64; if ($version >= '2.6.5') { $caps = unpack('C*', substr($packet, $pos, 32)); $pos += 32; } $deaths = unpack('v*', substr($packet, $pos, 64)); $pos += 64; if (!$refreshx) { $pings = unpack('C*', substr($packet, $pos, 32)); $pos += 32; } else { $pings = unpack('l*', substr($packet, $pos, 128)); $pos += 128; } $ids = unpack('C*', substr($packet, $pos, 32)); $pos += 32; $ips = unpack('N*', substr($packet, $pos, 128)); $pos += 128; if ($refreshx) { $locs = unpack('f*', substr($packet, $pos, 256)); $pos += 256; } for ($i = 0; $i < 32; $i++) { $players[$i]['name'] = substr($packet, $i*25+1, ord($packet[$i*25])); $players[$i]['team'] = $teams[$i+1]; $players[$i]['kills'] = $kills[$i+1]; $players[$i]['caps'] = $caps[$i+1]; $players[$i]['deaths'] = $deaths[$i+1]; $players[$i]['ping'] = $pings[$i+1]; $players[$i]['id'] = $ids[$i+1]; $players[$i]['ip'] = long2ip($ips[$i+1]); if ($refreshx) { $players[$i]['x'] = $locs[$i+1]; $players[$i]['y'] = $locs[$i+33]; } } if ($refreshx) { $data = unpack('f*', substr($packet, $pos, 16)); $pos += 16; $info['redflag'] = array('x' => $data[1], 'y' => $data[2]); $info['blueflag'] = array('x' => $data[3], 'y' => $data[4]); } $teams = unpack('v*', substr($packet, $pos, 8)); $pos += 8; $map = unpack('Clen/A16name', substr($packet, $pos, 17)); $pos += 17; $time = unpack('V*', substr($packet, $pos, 8)); $pos += 8; $limit = unpack('v', substr($packet, $pos, 2)); $pos += 2; $timelimit = $time[1]; $currenttime = $time[2]; $timeleft = $currenttime; $temp = (floor($timeleft / 60) % 60); $info['timeleft'] = floor($timeleft / 3600) . ':' . ($temp < 10 ? '0' : '') . $temp; $info['team'] = $teams; $info['map'] = substr($map['name'], 0, $map['len']); $info['timelimit'] = $timelimit; $info['currenttime'] = $timelimit - $currenttime; $info['limit'] = $limit[1]; $info['gamemode'] = ord($packet[$pos++]); if ($refreshx) { $data = unpack('C*', substr($packet, $pos, 4)); $pos += 4; $info['maxplayers'] = $data[1]; $info['maxspecs'] = $data[2]; $info['passworded'] = ($data[3] != 0 ? true : false); $info['nextmap'] = substr($packet, $pos, $data[4]); } if ($info['gamemode'] != 2) { if ($info['gamemode'] != 3 && $info['gamemode'] != 5) { unset($info['team'][1]); unset($info['team'][2]); } unset($info['team'][3]); unset($info['team'][4]); } foreach ($players as $player) { if ($player['team'] < 5) { $info['players']++; $info['player'][] = $player; } else if ($player['team'] == 5) { $info['spectators']++; $info['spectator'][] = $player; } } return $info;} ?>
align(1) struct Server{ align(1) struct Playername { byte len; char[24] name; } align(1) union IP { uint ilong; byte piece[4]; } align(1) struct Map { byte len; char[16] map; } Playername[32] name; ubyte[32] team; ushort[32] kills; ushort[32] deaths; ubyte[32] ping; ubyte[32] number; IP[32] ip; ushort teamscore[4]; Map map; uint timelimit; uint currenttime; ushort killlimit; byte gamestyle; }
Server info;stream.read(fd); // Comment this out if you don't use stream.readLinestream.readBlock(&info, info.sizeof);
info.map.map[0..info.map.len];