Untitled diff
1 removal
488 lines
491 additions
977 lines
<?php
<?php
/*
/*
LiveStats Library
LiveStats Library
version: 2.0
version: 2.0
query engines: Goldsource, Source, SA:MP
query engines: Goldsource, Source, SA:MP
protocol: 47, 48
protocol: 47, 48
author: nr913
author: nr913
visit www.freakz.ro
visit www.foxh.ro
*/
*/
define('HL_PACKET', -1);
define('HL_PACKET', -1);
define('HL_PACKET_SPLITTED', -2);
define('HL_PACKET_SPLITTED', -2);
define('SAMP_PACKET', 1347240275);
define('SAMP_PACKET', 1347240275);
class Player {
class Player {
var $ID;
var $ID;
var $Name;
var $Name;
var $Score;
var $Score;
var $TimePlayed;
var $TimePlayed;
var $Ping;
var $Ping;
}
}
class Server {
class Server {
var $Type = 0;
var $Type = 0;
var $ProtocolVersion;
var $ProtocolVersion;
var $Address;
var $Address;
var $Hostname;
var $Hostname;
var $Map;
var $Map;
var $Directory;
var $Directory;
var $Description;
var $Description;
var $AppID;
var $AppID;
var $MaxPlayers;
var $MaxPlayers;
var $PlayerCount;
var $PlayerCount;
var $BotCount;
var $BotCount;
var $Dedicated;
var $Dedicated;
var $OS;
var $OS;
var $PasswordProtected;
var $PasswordProtected;
var $Secured;
var $Secured;
var $GameMode;
var $GameMode;
var $WitnessCount;
var $WitnessCount;
var $WitnessTime;
var $WitnessTime;
var $GameVersion;
var $GameVersion;
var $Players = array();
var $Players = array();
var $Rules = array();
var $Rules = array();
}
}
class Time {
class Time {
var $Hours;
var $Hours;
var $Minutes;
var $Minutes;
var $Seconds;
var $Seconds;
function __construct($seconds) {
function __construct($seconds) {
$this->Hours = floor($seconds / 3600);
$this->Hours = floor($seconds / 3600);
$this->Minutes = floor($seconds / 60) % 60;
$this->Minutes = floor($seconds / 60) % 60;
$this->Seconds = floor($seconds) % 60;
$this->Seconds = floor($seconds) % 60;
}
}
function __toString() {
function __toString() {
$hours = ($this->Hours < 10 ? '0' . $this->Hours : $this->Hours);
$hours = ($this->Hours < 10 ? '0' . $this->Hours : $this->Hours);
$minutes = ($this->Minutes < 10 ? '0' . $this->Minutes : $this->Minutes);
$minutes = ($this->Minutes < 10 ? '0' . $this->Minutes : $this->Minutes);
$seconds = ($this->Seconds < 10 ? '0' . $this->Seconds : $this->Seconds);
$seconds = ($this->Seconds < 10 ? '0' . $this->Seconds : $this->Seconds);
return "$hours:$minutes:$seconds";
return "$hours:$minutes:$seconds";
}
}
}
}
class LSError extends Exception {
class LSError extends Exception {
var $ErrorMessage;
var $ErrorMessage;
var $ErrorCode;
var $ErrorCode;
function __construct($errcode, $errmsg) {
function __construct($errcode, $errmsg) {
$this->ErrorCode = $errcode;
$this->ErrorCode = $errcode;
$this->ErrorMessage = $errmsg;
$this->ErrorMessage = $errmsg;
}
}
}
}
class Utils {
class Utils {
static function getTime() {
static function getTime() {
list($u, $s) = explode(' ', microtime());
list($u, $s) = explode(' ', microtime());
return ((float)$u + (float)$s);
return ((float)$u + (float)$s);
}
}
static function getString($packet, &$offset, $length = -1) {
static function getString($packet, &$offset, $length = -1) {
$len = strlen($packet);
$len = strlen($packet);
$i = 0;
$i = 0;
if ($length == -1) {
if ($length == -1) {
while ($offset + $i < $len && $packet[$offset + $i] != "\x00")
while ($offset + $i < $len && $packet[$offset + $i] != "\x00")
$i++;
$i++;
$offset += $i + 1;
$offset += $i + 1;
return substr($packet, $offset - $i - 1, $i);
return substr($packet, $offset - $i - 1, $i);
} else {
} else {
$i = $length;
$i = $length;
if ($len - $offset < $length)
if ($len - $offset < $length)
$i = $len - $offset;
$i = $len - $offset;
$offset += $i;
$offset += $i;
return substr($packet, $offset - $i, $i);
return substr($packet, $offset - $i, $i);
}
}
}
}
static function getByte($packet, &$offset) {
static function getByte($packet, &$offset) {
if ($offset >= strlen($packet))
if ($offset >= strlen($packet))
return 0;
return 0;
$char = unpack('cchar', $packet[$offset]);
$char = unpack('cchar', $packet[$offset]);
$offset++;
$offset++;
return $char['char'];
return $char['char'];
}
}
static function getShort($packet, &$offset) {
static function getShort($packet, &$offset) {
if ($offset + 2 >= strlen($packet))
if ($offset + 2 >= strlen($packet))
return 0;
return 0;
$short = unpack('sshort', substr($packet, $offset, 2));
$short = unpack('sshort', substr($packet, $offset, 2));
$offset += 2;
$offset += 2;
return $short['short'];
return $short['short'];
}
}
static function getInt($packet, &$offset) {
static function getInt($packet, &$offset) {
if ($offset + 4 >= strlen($packet))
if ($offset + 4 >= strlen($packet))
return 0;
return 0;
$int = unpack('iint', substr($packet, $offset, 4));
$int = unpack('iint', substr($packet, $offset, 4));
$offset += 4;
$offset += 4;
return $int['int'];
return $int['int'];
}
}
static function getFloat($packet, &$offset) {
static function getFloat($packet, &$offset) {
if ($offset + 4 >= strlen($packet))
if ($offset + 4 >= strlen($packet))
return ((float)0.0);
return ((float)0.0);
$float = unpack('ffloat', substr($packet, $offset, 4));
$float = unpack('ffloat', substr($packet, $offset, 4));
$offset += 4;
$offset += 4;
return ((float)$float['float']);
return ((float)$float['float']);
}
}
}
}
class LiveStats {
class LiveStats {
var $IP;
var $IP;
var $Port;
var $Port;
var $Sock;
var $Sock;
var $Challenge = "\xFF\xFF\xFF\xFF";
var $Challenge = "\xFF\xFF\xFF\xFF";
var $HaveInfo = false;
var $HaveInfo = false;
var $HavePlayer = false;
var $HavePlayer = false;
var $HaveRules = false;
var $HaveRules = false;
var $ResendPlayer = false;
var $ResendPlayer = false;
var $ResendRules = false;
var $ResendRules = false;
var $SendQueue = array();
var $SendQueue = array();
var $MaxExecutionTime = 2;
var $MaxExecutionTime = 2;
var $SplittedPackets = array();
var $SplittedPackets = array();
var $SAMPHeader = "SAMP";
var $SAMPHeader = "SAMP";
var $Server;
var $Server;
public function __construct($hostname, $port = 27015) {
public function __construct($hostname, $port = 27015) {
$this->IP = gethostbyname($hostname);
$this->IP = gethostbyname($hostname);
$this->Port = $port;
$this->Port = $port;
$errno = 0; $errstr = '';
$errno = 0; $errstr = '';
$this->Sock = @stream_socket_client("udp://{$this->IP}:{$this->Port}", $errno, $errstr, 5);
$this->Sock = @stream_socket_client("udp://{$this->IP}:{$this->Port}", $errno, $errstr, 5);
if ($this->Sock === false)
if ($this->Sock === false)
throw new LSError(1, "Could not connect to specified host [$errno]: $errstr.");
throw new LSError(1, "Could not connect to specified host [$errno]: $errstr.");
if (stream_set_blocking($this->Sock, false) == false)
if (stream_set_blocking($this->Sock, false) == false)
throw new LSError(2, "Could not set to non-blocking mode.");
throw new LSError(2, "Could not set to non-blocking mode.");
if (stream_set_timeout($this->Sock, 3) == false)
if (stream_set_timeout($this->Sock, 3) == false)
throw new LSError(3, "Could not set timeout to 10 seconds.");
throw new LSError(3, "Could not set timeout to 10 seconds.");
$this->Server = new Server;
$this->Server = new Server;
$this->Server->Address = "{$this->IP}:{$this->Port}";
$this->Server->Address = "{$this->IP}:{$this->Port}";
$ip = explode('.', $this->IP);
$ip = explode('.', $this->IP);
$this->SAMPHeader .= chr($ip[0]) . chr($ip[1]) . chr($ip[2]) . chr($ip[3]) . chr($this->Port & 0xFF) . chr(($this->Port >> 8) & 0xFF);
$this->SAMPHeader .= chr($ip[0]) . chr($ip[1]) . chr($ip[2]) . chr($ip[3]) . chr($this->Port & 0xFF) . chr(($this->Port >> 8) & 0xFF);
}
}
function onSplittedPacketReceived($packet) {
function onSplittedPacketReceived($packet) {
$offset = 4;
$offset = 4;
$ReqID = Utils::getInt($packet, $offset);
$ReqID = Utils::getInt($packet, $offset);
if (!isset($this->SplittedPackets[$ReqID])) {
if (!isset($this->SplittedPackets[$ReqID])) {
$this->SplittedPackets[$ReqID] = array(
$this->SplittedPackets[$ReqID] = array(
'Data' => array(),
'Data' => array(),
'Type' => -1,
'Type' => -1,
'Packets' => -1
'Packets' => -1
);
);
}
}
$this->SplittedPackets[$ReqID]['Data'][] = $packet;
$this->SplittedPackets[$ReqID]['Data'][] = $packet;
if (count($this->SplittedPackets[$ReqID]['Data']) == 2) {
if (count($this->SplittedPackets[$ReqID]['Data']) == 2) {
$offset = 8;
$offset = 8;
$FB1 = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][0], $offset);
$FB1 = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][0], $offset);
$offset = 8;
$offset = 8;
$FB2 = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][1], $offset);
$FB2 = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][1], $offset);
if ($FB1 != $FB2) {
if ($FB1 != $FB2) {
$this->SplittedPackets[$ReqID]['Type'] = 0;
$this->SplittedPackets[$ReqID]['Type'] = 0;
$this->SplittedPackets[$ReqID]['Packets'] = ($FB1<<4)>>4;
$this->SplittedPackets[$ReqID]['Packets'] = ($FB1<<4)>>4;
} else {
} else {
$this->SplittedPackets[$ReqID]['Type'] = 1;
$this->SplittedPackets[$ReqID]['Type'] = 1;
$this->SplittedPackets[$ReqID]['Packets'] = $FB1;
$this->SplittedPackets[$ReqID]['Packets'] = $FB1;
}
}
}
}
if (count($this->SplittedPackets[$ReqID]['Data']) == $this->SplittedPackets[$ReqID]['Packets']) {
if (count($this->SplittedPackets[$ReqID]['Data']) == $this->SplittedPackets[$ReqID]['Packets']) {
if ($this->SplittedPackets[$ReqID]['Type'] == 0) {
if ($this->SplittedPackets[$ReqID]['Type'] == 0) {
for ($i = 0; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++) {
for ($i = 0; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++) {
$offset = 8;
$offset = 8;
$PckID = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][$i], $offset)>>4;
$PckID = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][$i], $offset)>>4;
if ($i != $PckID) {
if ($i != $PckID) {
$aux = $this->SplittedPackets[$ReqID]['Data'][$PckID];
$aux = $this->SplittedPackets[$ReqID]['Data'][$PckID];
$this->SplittedPackets[$ReqID]['Data'][$PckID] = $this->SplittedPackets[$ReqID]['Data'][$i];
$this->SplittedPackets[$ReqID]['Data'][$PckID] = $this->SplittedPackets[$ReqID]['Data'][$i];
$this->SplittedPackets[$ReqID]['Data'][$i] = $aux;
$this->SplittedPackets[$ReqID]['Data'][$i] = $aux;
$i--;
$i--;
}
}
}
}
$packet = "\xFF\xFF\xFF\xFF" . substr($this->SplittedPackets[$ReqID]['Data'][0], 13);
$packet = "\xFF\xFF\xFF\xFF" . substr($this->SplittedPackets[$ReqID]['Data'][0], 13);
for ($i = 1; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++)
for ($i = 1; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++)
$packet .= substr($this->SplittedPackets[$ReqID]['Data'][$i], 9);
$packet .= substr($this->SplittedPackets[$ReqID]['Data'][$i], 9);
} else {
} else {
for ($i = 0; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++) {
for ($i = 0; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++) {
$offset = 9;
$offset = 9;
$PckID = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][$i], $offset);
$PckID = Utils::getByte($this->SplittedPackets[$ReqID]['Data'][$i], $offset);
if ($i != $PckID) {
if ($i != $PckID) {
$aux = $this->SplittedPackets[$ReqID]['Data'][$PckID];
$aux = $this->SplittedPackets[$ReqID]['Data'][$PckID];
$this->SplittedPackets[$ReqID]['Data'][$PckID] = $this->SplittedPackets[$ReqID]['Data'][$i];
$this->SplittedPackets[$ReqID]['Data'][$PckID] = $this->SplittedPackets[$ReqID]['Data'][$i];
$this->SplittedPackets[$ReqID]['Data'][$i] = $aux;
$this->SplittedPackets[$ReqID]['Data'][$i] = $aux;
$i--;
$i--;
}
}
}
}
$packet = "\xFF\xFF\xFF\xFF" . substr($this->SplittedPackets[$ReqID]['Data'][0], 16);
$packet = "\xFF\xFF\xFF\xFF" . substr($this->SplittedPackets[$ReqID]['Data'][0], 16);
for ($i = 1; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++)
for ($i = 1; $i < $this->SplittedPackets[$ReqID]['Packets']; $i++)
$packet .= substr($this->SplittedPackets[$ReqID]['Data'][$i], 12);
$packet .= substr($this->SplittedPackets[$ReqID]['Data'][$i], 12);
}
}
unset($this->SplittedPackets[$ReqID]);
unset($this->SplittedPackets[$ReqID]);
$this->onPacketReceived($packet);
$this->onPacketReceived($packet);
}
}
}
}
function onPacketReceived($packet) {
function onPacketReceived($packet) {
$offset = 4;
$offset = 4;
switch (Utils::getByte($packet, $offset)) {
switch (Utils::getByte($packet, $offset)) {
case 0x41: // challenge
case 0x41: // challenge
$this->Challenge = substr($packet, 5);
$this->Challenge = substr($packet, 5);
if ($this->ResendPlayer) {
if ($this->ResendPlayer) {
$this->ResendPlayer = false;
$this->ResendPlayer = false;
$this->requestPlayer();
$this->requestPlayer();
}
}
if ($this->ResendRules) {
if ($this->ResendRules) {
$this->ResendRules = false;
$this->ResendRules = false;
$this->requestRules();
$this->requestRules();
}
}
break;
break;
case 0x44: // player
case 0x44: // player
if ($this->HavePlayer)
if ($this->HavePlayer)
break;
break;
$offset = 5;
$offset = 5;
$numplayers = Utils::getByte($packet, $offset);
$numplayers = Utils::getByte($packet, $offset);
while ($numplayers) {
while ($numplayers) {
$Player = new Player;
$Player = new Player;
$Player->ID = Utils::getByte($packet, $offset);
$Player->ID = Utils::getByte($packet, $offset);
$Player->Name = Utils::getString($packet, $offset);
$Player->Name = Utils::getString($packet, $offset);
$len = strlen($Player->Name);
$len = strlen($Player->Name);
$Player->Score = Utils::getInt($packet, $offset);
$Player->Score = Utils::getInt($packet, $offset);
$Player->TimePlayed = new Time(Utils::getFloat($packet, $offset));
$Player->TimePlayed = new Time(Utils::getFloat($packet, $offset));
$numplayers--;
$numplayers--;
array_push($this->Server->Players, $Player);
array_push($this->Server->Players, $Player);
}
}
$this->HavePlayer = true;
$this->HavePlayer = true;
$this->ResendPlayer = false;
$this->ResendPlayer = false;
break;
break;
case 0x49: // info, source
case 0x49: // info, source
if ($this->HaveInfo)
if ($this->HaveInfo)
break;
break;
$offset = 5;
$offset = 5;
$this->Server->ProtocolVersion = Utils::getByte($packet, $offset);
$this->Server->ProtocolVersion = Utils::getByte($packet, $offset);
$this->Server->Hostname = Utils::getString($packet, $offset);
$this->Server->Hostname = Utils::getString($packet, $offset);
$this->Server->Map = Utils::getString($packet, $offset);
$this->Server->Map = Utils::getString($packet, $offset);
$this->Server->Directory = Utils::getString($packet, $offset);
$this->Server->Directory = Utils::getString($packet, $offset);
$this->Server->Description = Utils::getString($packet, $offset);
$this->Server->Description = Utils::getString($packet, $offset);
$this->Server->AppID = Utils::getShort($packet, $offset);
$this->Server->AppID = Utils::getShort($packet, $offset);
$this->Server->PlayerCount = Utils::getByte($packet, $offset);
$this->Server->PlayerCount = Utils::getByte($packet, $offset);
$this->Server->MaxPlayers = Utils::getByte($packet, $offset);
$this->Server->MaxPlayers = Utils::getByte($packet, $offset);
$this->Server->BotCount = Utils::getByte($packet, $offset);
$this->Server->BotCount = Utils::getByte($packet, $offset);
$this->Server->Dedicated = (Utils::getByte($packet, $offset) == ord('d') ? true : false);
$this->Server->Dedicated = (Utils::getByte($packet, $offset) == ord('d') ? true : false);
$this->Server->OS = (Utils::getByte($packet, $offset) == 'l' ? 'Linux' : 'Windows');
$this->Server->OS = (Utils::getByte($packet, $offset) == 'l' ? 'Linux' : 'Windows');
$this->Server->PasswordProtected = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->PasswordProtected = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->Secured = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->Secured = (Utils::getByte($packet, $offset) == 1 ? true : false);
$TheShipAppIDs = array(2400, 2401, 2402, 2412, 2430, 2406, 2405, 2403);
$TheShipAppIDs = array(2400, 2401, 2402, 2412, 2430, 2406, 2405, 2403);
if (in_array($this->Server->AppID, $TheShipAppIDs)) {
if (in_array($this->Server->AppID, $TheShipAppIDs)) {
$gm = Utils::getByte($packet, $offset);
$gm = Utils::getByte($packet, $offset);
$GameModes = array('Hunt', 'Elimination', 'Duel', 'Deathmatch', 'Team VIP', 'Team Elimination');
$GameModes = array('Hunt', 'Elimination', 'Duel', 'Deathmatch', 'Team VIP', 'Team Elimination');
$this->Server->GameMode = (isset($GameModes[$gm]) ? $GameModes[$gm] : 'Unknown');
$this->Server->GameMode = (isset($GameModes[$gm]) ? $GameModes[$gm] : 'Unknown');
$this->Server->WitnessCount = Utils::getByte($packet, $offset);
$this->Server->WitnessCount = Utils::getByte($packet, $offset);
$this->Server->WitnessTime = Utils::getByte($packet, $offset);
$this->Server->WitnessTime = Utils::getByte($packet, $offset);
}
}
$this->Server->GameVersion = Utils::getString($packet, $offset);
$this->Server->GameVersion = Utils::getString($packet, $offset);
$this->HaveInfo = true;
$this->HaveInfo = true;
break;
break;
case 0x6D: // info, goldsource
case 0x6D: // info, goldsource
if ($this->HaveInfo)
if ($this->HaveInfo)
break;
break;
$offset = 5;
$offset = 5;
Utils::getString($packet, $offset);
Utils::getString($packet, $offset);
$this->Server->Hostname = Utils::getString($packet, $offset);
$this->Server->Hostname = Utils::getString($packet, $offset);
$this->Server->Map = Utils::getString($packet, $offset);
$this->Server->Map = Utils::getString($packet, $offset);
$this->Server->Directory = Utils::getString($packet, $offset);
$this->Server->Directory = Utils::getString($packet, $offset);
$this->Server->Description = Utils::getString($packet, $offset);
$this->Server->Description = Utils::getString($packet, $offset);
$this->Server->PlayerCount = Utils::getByte($packet, $offset);
$this->Server->PlayerCount = Utils::getByte($packet, $offset);
$this->Server->MaxPlayers = Utils::getByte($packet, $offset);
$this->Server->MaxPlayers = Utils::getByte($packet, $offset);
$this->Server->ProtocolVersion = Utils::getByte($packet, $offset);
$this->Server->ProtocolVersion = Utils::getByte($packet, $offset);
$this->Server->Dedicated = (Utils::getByte($packet, $offset) == ord('d') ? true : false);
$this->Server->Dedicated = (Utils::getByte($packet, $offset) == ord('d') ? true : false);
$this->Server->OS = (Utils::getByte($packet, $offset) == 'l' ? 'Linux' : 'Windows');
$this->Server->OS = (Utils::getByte($packet, $offset) == 'l' ? 'Linux' : 'Windows');
$this->Server->AppID = ($this->Server->OS == 'Linux' ? 4 : 5);
$this->Server->AppID = ($this->Server->OS == 'Linux' ? 4 : 5);
$this->Server->PasswordProtected = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->PasswordProtected = (Utils::getByte($packet, $offset) == 1 ? true : false);
$IsMod = Utils::getByte($packet, $offset);
$IsMod = Utils::getByte($packet, $offset);
if ($IsMod == 1) {
if ($IsMod == 1) {
Utils::getString($packet, $offset);
Utils::getString($packet, $offset);
Utils::getString($packet, $offset);
Utils::getString($packet, $offset);
Utils::getByte($packet, $offset);
Utils::getByte($packet, $offset);
Utils::getInt($packet, $offset);
Utils::getInt($packet, $offset);
Utils::getInt($packet, $offset);
Utils::getInt($packet, $offset);
Utils::getByte($packet, $offset);
Utils::getByte($packet, $offset);
Utils::getByte($packet, $offset);
Utils::getByte($packet, $offset);
}
}
$this->Server->Secured = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->Secured = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->BotCount = Utils::getByte($packet, $offset);
$this->Server->BotCount = Utils::getByte($packet, $offset);
$this->HaveInfo = true;
$this->HaveInfo = true;
break;
break;
case 0x45: // rules
case 0x45: // rules
if ($this->HaveRules)
if ($this->HaveRules)
break;
break;
$offset = 5;
$offset = 5;
$rulesnum = Utils::getShort($packet, $offset);
$rulesnum = Utils::getShort($packet, $offset);
while ($rulesnum) {
while ($rulesnum) {
$Name = Utils::getString($packet, $offset);
$Name = Utils::getString($packet, $offset);
$Value = Utils::getString($packet, $offset);
$Value = Utils::getString($packet, $offset);
$rulesnum--;
$rulesnum--;
$this->Server->Rules[$Name] = $Value;
$this->Server->Rules[$Name] = $Value;
}
}
$this->HaveRules = true;
$this->HaveRules = true;
$this->ResendRules = false;
$this->ResendRules = false;
break;
break;
default:
default:
break;
break;
}
}
}
}
function onSampPacketReceived($packet) {
function onSampPacketReceived($packet) {
$offset = 10;
$offset = 10;
switch (Utils::getByte($packet, $offset)) {
switch (Utils::getByte($packet, $offset)) {
case 0x69: // info
case 0x69: // info
if ($this->HaveInfo)
if ($this->HaveInfo)
break;
break;
$this->Server->PasswordProtected = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->PasswordProtected = (Utils::getByte($packet, $offset) == 1 ? true : false);
$this->Server->PlayerCount = Utils::getShort($packet, $offset);
$this->Server->PlayerCount = Utils::getShort($packet, $offset);
$this->Server->MaxPlayers = Utils::getShort($packet, $offset);
$this->Server->MaxPlayers = Utils::getShort($packet, $offset);
$len = Utils::getInt($packet, $offset);
$len = Utils::getInt($packet, $offset);
$this->Server->Hostname = Utils::getString($packet, $offset, $len);
$this->Server->Hostname = Utils::getString($packet, $offset, $len);
$len = Utils::getInt($packet, $offset);
$len = Utils::getInt($packet, $offset);
$this->Server->GameMode = Utils::getString($packet, $offset, $len);
$this->Server->GameMode = Utils::getString($packet, $offset, $len);
$len = Utils::getInt($packet, $offset);
$len = Utils::getInt($packet, $offset);
$this->Server->Map = Utils::getString($packet, $offset, $len);
$this->Server->Map = Utils::getString($packet, $offset, $len);
$this->HaveInfo = true;
$this->HaveInfo = true;
if ($this->Server->PlayerCount >= 100)
if ($this->Server->PlayerCount >= 100)
$this->HavePlayer = true;
$this->HavePlayer = true;
break;
break;
case 0x72: // rules
case 0x72: // rules
if ($this->HaveRules)
if ($this->HaveRules)
break;
break;
$rulesnum = Utils::getShort($packet, $offset);
$rulesnum = Utils::getShort($packet, $offset);
while ($rulesnum) {
while ($rulesnum) {
$len = Utils::getByte($packet, $offset);
$len = Utils::getByte($packet, $offset);
$Name = Utils::getString($packet, $offset, $len);
$Name = Utils::getString($packet, $offset, $len);
$len = Utils::getByte($packet, $offset);
$len = Utils::getByte($packet, $offset);
$Value = Utils::getString($packet, $offset, $len);
$Value = Utils::getString($packet, $offset, $len);
$rulesnum--;
$rulesnum--;
$this->Server->Rules[$Name] = $Value;
$this->Server->Rules[$Name] = $Value;
}
}
$this->HaveRules = true;
$this->HaveRules = true;
break;
break;
case 0x64: // player
case 0x64: // player
if ($this->HavePlayer)
if ($this->HavePlayer)
break;
break;
$numplayers = Utils::getShort($packet, $offset);
$numplayers = Utils::getShort($packet, $offset);
$lastID = 0;
$lastID = 0;
$plusID = 0;
$plusID = 0;
while ($numplayers) {
while ($numplayers) {
$Player = new Player;
$Player = new Player;
$Player->ID = Utils::getByte($packet, $offset) + $plusID;
$Player->ID = Utils::getByte($packet, $offset) + $plusID;
if ($Player->ID < $lastID) {
if ($Player->ID < $lastID) {
$Player->ID += 256;
$Player->ID += 256;
$plusID += 256;
$plusID += 256;
}
}
$lastID = $Player->ID;
$lastID = $Player->ID;
$len = Utils::getByte($packet, $offset);
$len = Utils::getByte($packet, $offset);
$Player->Name = Utils::getString($packet, $offset, $len);
$Player->Name = Utils::getString($packet, $offset, $len);
$len = strlen($Player->Name);
$len = strlen($Player->Name);
$Player->Score = Utils::getInt($packet, $offset);
$Player->Score = Utils::getInt($packet, $offset);
$Player->Ping = Utils::getInt($packet, $offset);
$Player->Ping = Utils::getInt($packet, $offset);
$numplayers--;
$numplayers--;
array_push($this->Server->Players, $Player);
array_push($this->Server->Players, $Player);
}
}
$this->HavePlayer = true;
$this->HavePlayer = true;
break;
break;
default:
default:
break;
break;
}
}
}
}
function requestInfo() {
function requestInfo() {
array_push($this->SendQueue, "\xFF\xFF\xFF\xFFTSource Engine Query\x00");
array_push($this->SendQueue, "\xFF\xFF\xFF\xFFTSource Engine Query\x00");
array_push($this->SendQueue, $this->SAMPHeader . "i");
array_push($this->SendQueue, $this->SAMPHeader . "i");
}
}
function requestPlayer() {
function requestPlayer() {
array_push($this->SendQueue, "\xFF\xFF\xFF\xFF\x55" . $this->Challenge);
array_push($this->SendQueue, "\xFF\xFF\xFF\xFF\x55" . $this->Challenge);
array_push($this->SendQueue, $this->SAMPHeader . "d");
array_push($this->SendQueue, $this->SAMPHeader . "d");
if ($this->Challenge == "\xFF\xFF\xFF\xFF")
if ($this->Challenge == "\xFF\xFF\xFF\xFF")
$this->ResendPlayer = true;
$this->ResendPlayer = true;
}
}
function requestRules() {
function requestRules() {
array_push($this->SendQueue, "\xFF\xFF\xFF\xFF\x56" . $this->Challenge);
array_push($this->SendQueue, "\xFF\xFF\xFF\xFF\x56" . $this->Challenge);
array_push($this->SendQueue, $this->SAMPHeader . "r");
array_push($this->SendQueue, $this->SAMPHeader . "r");
if ($this->Challenge == "\xFF\xFF\xFF\xFF")
if ($this->Challenge == "\xFF\xFF\xFF\xFF")
$this->ResendRules = true;
$this->ResendRules = true;
}
}
function GetServer() {
function GetServer() {
$start = Utils::getTime();
$start = Utils::getTime();
$this->requestInfo();
$this->requestInfo();
$this->requestPlayer();
$this->requestPlayer();
$this->requestRules();
$this->requestRules();
while (!($this->HaveRules && $this->HaveInfo && $this->HavePlayer)) {
while (!($this->HaveRules && $this->HaveInfo && $this->HavePlayer)) {
if (Utils::getTime() - $start >= $this->MaxExecutionTime) {
if (Utils::getTime() - $start >= $this->MaxExecutionTime) {
if ($this->HaveInfo && $this->HavePlayer) {
if ($this->HaveInfo && $this->HavePlayer) {
$this->HaveRules = true;
$this->HaveRules = true;
} else {
} else {
throw new LSError(4, "Timed out.");
throw new LSError(4, "Timed out.");
}
}
}
}
if (count($this->SendQueue) > 0) {
if (count($this->SendQueue) > 0) {
stream_socket_sendto($this->Sock, array_shift($this->SendQueue));
stream_socket_sendto($this->Sock, array_shift($this->SendQueue));
$meta = stream_get_meta_data($this->Sock);
$meta = stream_get_meta_data($this->Sock);
if ($meta['timed_out'])
if ($meta['timed_out'])
throw new LSError(5, "Timed out.");
throw new LSError(5, "Timed out.");
}
}
usleep(50000);
usleep(50000);
$packet = fread($this->Sock, 2048);
$packet = fread($this->Sock, 2048);
$meta = stream_get_meta_data($this->Sock);
$meta = stream_get_meta_data($this->Sock);
if ($meta['timed_out'])
if ($meta['timed_out'])
throw new LSError(6, "Timed out.");
throw new LSError(6, "Timed out.");
if (strlen($packet) > 0) {
if (strlen($packet) > 0) {
$offset = 0;
$offset = 0;
switch (Utils::getInt($packet, $offset)) {
switch (Utils::getInt($packet, $offset)) {
case HL_PACKET:
case HL_PACKET:
if (!in_array($this->Server->Type, array(0, 1)))
if (!in_array($this->Server->Type, array(0, 1)))
break;
break;
$this->Server->Type = 1;
$this->Server->Type = 1;
$this->onPacketReceived($packet);
$this->onPacketReceived($packet);
break;
break;
case HL_PACKET_SPLITTED:
case HL_PACKET_SPLITTED:
if (!in_array($this->Server->Type, array(0, 1)))
if (!in_array($this->Server->Type, array(0, 1)))
break;
break;
$this->Server->Type = 1;
$this->Server->Type = 1;
$this->onSplittedPacketReceived($packet);
$this->onSplittedPacketReceived($packet);
break;
break;
case SAMP_PACKET:
case SAMP_PACKET:
if (!in_array($this->Server->Type, array(0, 2)))
if (!in_array($this->Server->Type, array(0, 2)))
break;
break;
$this->Server->Type = 2;
$this->Server->Type = 2;
$this->onSampPacketReceived($packet);
$this->onSampPacketReceived($packet);
break;
break;
default:
default:
break;
break;
}
}
}
}
}
}
return $this->Server;
return $this->Server;
}
}
}
}
?>
?>