Skip to content

Instantly share code, notes, and snippets.

@Frago9876543210
Last active February 22, 2018 06:27
Show Gist options
  • Save Frago9876543210/e052b6fbecf66aba406e6c25905eea12 to your computer and use it in GitHub Desktop.
Save Frago9876543210/e052b6fbecf66aba406e6c25905eea12 to your computer and use it in GitHub Desktop.
Minecraft query
<?php
declare(strict_types=1);
namespace query;
class Query{
public const HANDSHAKE = 9;
public const STATISTICS = 0;
/** @var resource $socket */
protected $socket;
/** @var int $timestamp */
protected $timestamp;
/**
* Query constructor.
* @param string $host
* @param int $port
* @param int $timeout
*/
public function __construct(string $host, int $port = 19132, int $timeout = 3){
$this->socket = fsockopen("udp://" . $host, $port);
$this->timestamp = time() + rand();
stream_set_timeout($this->socket, $timeout);
stream_set_blocking($this->socket, true);
}
/**
* @param int $request
* @param string $additional
*/
private function writeData(int $request, string $additional = "") : void{
$data = pack("C3N", 0xfe, 0xfd, $request, $this->timestamp) . $additional;
fwrite($this->socket, $data, strlen($data));
}
/**
* @return bool|string
*/
private function readData(){
return substr(fread($this->socket, 4096), 5); //skip header & timestamp
}
/**
* @return null|string
*/
private function getToken() : ?string{
$this->writeData(self::HANDSHAKE);
return ($data = $this->readData()) === false ? null : $data;
}
/**
* @param string $token
* @return array|null
*/
private function getStatus(string $token) : ?array{
$this->writeData(self::STATISTICS, pack("N", $token) . "\xff\xff\xff\x01");
if(($data = $this->readData()) === false){
return null;
}
if(count(($data = explode("\x00\x00\x01player_\x00\x00", $data))) !== 2){
return null;
}
$statistics = [
'players' => array_filter($data[1] === "\x00" ? [] : explode("\x00", $data[1]), function($v){
return $v !== "";
})
];
foreach(array_chunk(explode("\x00", $data[0]), 2) as $v){
$statistics[$v[0]] = utf8_encode($v[1]);
}
return $statistics;
}
/**
* @return null|string
*/
public function getJsonResult() : ?string{
return ($token = $this->getToken()) !== null && ($status = $this->getStatus($token)) !== null ? json_encode($status) : null;
}
}
<?php
declare(strict_types=1);
class Query{
const HANDSHAKE = 9;
const STATISTICS = 0;
/** @var resource $socket */
protected $socket;
/** @var int $timestamp */
protected $timestamp;
/**
* Query constructor.
* @param string $host
* @param int $port
* @param int $timeout
*/
public function __construct(string $host, int $port = 19132, int $timeout = 3){
$this->socket = fsockopen("udp://" . $host, $port);
$this->timestamp = time() + rand();
stream_set_timeout($this->socket, $timeout);
stream_set_blocking($this->socket, true);
}
/**
* @param int $request
* @param string $additional
*/
private function writeData(int $request, string $additional = ""){
$data = pack("C3N", 0xfe, 0xfd, $request, $this->timestamp) . $additional;
fwrite($this->socket, $data, strlen($data));
}
/**
* @return bool|string
*/
private function readData(){
return substr(fread($this->socket, 4096), 5); //skip header & timestamp
}
/**
* @return null|string
*/
private function getToken(){
$this->writeData(self::HANDSHAKE);
return ($data = $this->readData()) === false ? null : $data;
}
/**
* @param string $token
* @return array|null
*/
private function getStatus(string $token){
$this->writeData(self::STATISTICS, pack("N", $token) . "\xff\xff\xff\x01");
if(($data = $this->readData()) === false){
return null;
}
if(count(($data = explode("\x00\x00\x01player_\x00\x00", $data))) !== 2){
return null;
}
$statistics = [
'players' => array_filter($data[1] === "\x00" ? [] : explode("\x00", $data[1]), function($v){
return $v !== "";
})
];
foreach(array_chunk(explode("\x00", $data[0]), 2) as $v){
$statistics[$v[0]] = utf8_encode($v[1]);
}
return $statistics;
}
/**
* @return null|string
*/
public function getJsonResult(){
return ($token = $this->getToken()) !== null && ($status = $this->getStatus($token)) !== null ? json_encode($status) : null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment