@Grzesie1k[PHP]Status serwera Battlefield 4
[PHP]Status serwera Battlefield 4
24.02.2014 | aktual.: 25.02.2014 15:46
Gry Battlefield 4 nie trzeba nikomu przedstawiać. Ostatnio stanąłem przed problemem wyświetlenia statusu serwera serwera gry Battlefield 4 na stronie www. Wujek Google z trudem odpowiadał na jakiekolwiek pytania z związane z tym tematem. Jedyną opcją wydawał się GameTracker, lecz przecież on też musiał jakoś te informacje pobierać. Znalazłem w końcu sposób na bezpośrednie pobranie statusu z serwera. Oto moje wypociny w tym temacie:
<?php error_reporting(E_ALL); set_time_limit(1); class server { private $ip,$port,$timeout; protected $queryString=array(); public function __construct($address,$timeout=1){ list($this->ip,$this->port)=explode(':',$address); $this->timeout=$timeout; } public function query($type='status'){ if(!array_key_exists($type,$this->queryString)) return false; $fp=@fsockopen($this->ip,$this->port,$errno,$errstr,$this->timeout); if(!$fp) return array("Error $errno: $errstr"); fwrite($fp,$this->queryString[$type]); $buffer=''; while(!feof($fp)){ $buffer.=fread($fp,1024); $meta=stream_get_meta_data($fp); if($meta['unread_bytes']<=0) break; } return $this->parseBuffer($type,$buffer); } private function parseBuffer($type,$buffer){ $buffer=substr($buffer,12); $response=array(); while(!empty($buffer)){ if($buffer[0]!="\x00") $response[]=substr($buffer,4,ord($buffer[0])); $buffer=substr($buffer,ord($buffer[0])+5); } return $this->interpreteResponse($type,$response); } protected function interpreteResponse($type,$response){ return $response; } } class bf4server extends server{ protected $queryString=array( 'status' =>"\x00\x00\x00\x00\x1b\x00\x00\x00\x01\x00\x00\x00\x0a\x00\x00\x00serverInfo\x00", 'version' =>"\x00\x00\x00\x00\x18\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00version\x00", 'players' =>"\x00\x00\x00\x00\x24\x00\x00\x00\x02\x00\x00\x00\x0b\x00\x00\x00listPlayers\x00\x03\x00\x00\x00\x61ll\x00", ); protected function interpreteResponse($type,$response){ if($response[0]!='OK')return false; unset($response[0]); switch($type){ case 'status':{ $th=array('serverName','players','slots','gametype','map','round','roundTotal','scoreCount','scoreA','scoreB','scoreMatchEnd','ranked','joinQueueEnable','password','uptime','roundTime','address','pbVersion','pb','region','pingSite','country','matchMaking','state'); switch(count($response)){ case 21: unset($th[16]); case 22: unset($th[8]); unset($th[9]); break; default: return $response; } return array_combine($th,$response); } case 'version':{ return array_combine(array('game','gameversion'),$response); } case 'players':{ $n=$response[$response[1]+2]; $th=array_values(array_slice($response,1,$response[1])); unset($th[1]); //dice bug...? $response=array_values(array_slice($response,count($th)+3)); $players=array(); for($i=0;$i<$n;$i++){ $players[]=array_combine($th,array_slice($response,$i*9,9)); } return $players; } } } } $start=microtime(true); $server=new bf4server('173.199.83.95:30010'); //random server echo 'Server status '; print_r($server->query()); echo 'Server version '; print_r($server->query('version')); echo 'Players '; print_r($server->query('players')); echo 'Wygenerowano w '.Number_format(microtime(true)-$start,3)."s\n";
A oto przykładowy efekt działania tego programu na losowym serwerze:
Server status Array ( [serverName] => =NOOBS WELCOME= 24/7 Siege of Shanghai | FAST XP [players] => 64 [slots] => 64 [gametype] => ConquestLarge0 [map] => MP_Siege [round] => 0 [roundTotal] => 2 [scoreCount] => 2 [scoreA] => 745.4487 [scoreB] => 681.2927 [scoreMatchEnd] => 0 [ranked] => true [joinQueueEnable] => true [password] => false [uptime] => 544014 [roundTime] => 2006 [address] => 108.61.112.27:30100 [pbVersion] => v1.883 | A1390 C2.333 [pb] => true [region] => EU [pingSite] => ams [country] => DE [matchMaking] => 65 [state] => IN_GAME ) Server version Array ( [game] => BF4 [gameversion] => 109758 ) Players Array ( [0] => Array ( [name] => Burgher [teamId] => 1 [squadId] => 2 [kills] => 13 [deaths] => 13 [score] => 5188 [rank] => 51 [ping] => 55 [type] => 0 ) [1] => Array ( [name] => AdamJ76 [teamId] => 2 [squadId] => 8 [kills] => 24 [deaths] => 9 [score] => 11752 [rank] => 92 [ping] => 34 [type] => 0 ) [2] => Array ( [name] => MrKumar85 [teamId] => 1 [squadId] => 1 [kills] => 2 [deaths] => 4 [score] => 2349 [rank] => 16 [ping] => 35 [type] => 0 ) [3] => Array ( [name] => DanishB00y [teamId] => 1 [squadId] => 4 [kills] => 7 [deaths] => 14 [score] => 2667 [rank] => 36 [ping] => 43 [type] => 0 ) ... [63] => Array ( [name] => Akotoje [teamId] => 0 [squadId] => 0 [kills] => 0 [deaths] => 0 [score] => 0 [rank] => 38 [ping] => 156 [type] => 0 ) ) Wygenerowano w 0.427s
Mam nadzieję, że komuś się przyda. Do zobaczenia na polu bitwy ;)