[
  {
    "path": ".gitignore",
    "content": "composer.lock\ncomposer.phar\nvendor\n.project\n.settings\n.buildpath\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2021 Julian Spravil\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Minecraft Server Status Query [Discontinued]\n\n[![Latest Stable Version](https://poser.pugx.org/funnyitselmo/minecraftserverstatus/v/stable)](https://packagist.org/packages/funnyitselmo/minecraftserverstatus) [![Total Downloads](https://poser.pugx.org/funnyitselmo/minecraftserverstatus/downloads)](https://packagist.org/packages/funnyitselmo/minecraftserverstatus) [![Latest Unstable Version](https://poser.pugx.org/funnyitselmo/minecraftserverstatus/v/unstable)](https://packagist.org/packages/funnyitselmo/minecraftserverstatus) [![License](https://poser.pugx.org/funnyitselmo/minecraftserverstatus/license)](https://packagist.org/packages/funnyitselmo/minecraftserverstatus)\n\nMinecraft Server Status Query, written in PHP, with online players, motd, favicon and more server related informations without plugins and enable-query.\n\n*Tested with Spigot 1.9 and Bungeecord 1.9 & 1.8*\n\n### Installation\n```\ncomposer require funnyitselmo/minecraftserverstatus\n```\n### Tutorial\n```Java\nuse MinecraftServerStatus\\MinecraftServerStatus;\n\nrequire '../vendor/autoload.php';\n\n$response = MinecraftServerStatus::query('lostforce.com', 25565);\n\nif (! $response) {\n    echo \"The Server is offline!\";\n} else {\n    echo \"<img width=\\\"64\\\" height=\\\"64\\\" src=\\\"\" . $response['favicon'] . \"\\\" /> <br>\n\t\tThe Server \" . $response['hostname'] . \" is running on \" . $response['version'] . \" and is online,\n\t\tcurrently are \" . $response['players'] . \" players online\n\t\tof a maximum of \" . $response['max_players'] . \". The motd of the server is '\" . $response['description'] . \"'.\n\t\tThe server has a ping of \" . $response['ping'] . \" milliseconds.\";\n}\n```\nIf the server is offline MinecraftServerStatus::query returns false else it returns an array which contains the server informations.\n\n### Variables\nThe following table contains the available variables the response can contain. The default value of each variable is false.\n\n<table border=\"0\">\n<tr>\n<th>Array Index</th>\n<th>Description</th>\n</tr>\n<tr>\n<td><pre>'hostname'</pre></td>\n<td>Exact server address in 127.0.0.1 format</td>\n</tr>\n<tr>\n<td><pre>'port'</pre></td>\n<td>The servers port for example 25565</td>\n</tr>\n<tr>\n<td><pre>'ping'</pre></td>\n<td>The time in ms the server needs to answer</td>\n</tr>\n<tr>\n<td><pre>'version'</pre></td>\n<td>The server version <br>(for example: 1.9)</td>\n</tr>\n<tr>\n<td><pre>'protocol'</pre></td>\n<td>The server protocol <br>(for example: 107)</td>\n</tr>\n<tr>\n<td><pre>'players'</pre></td>\n<td>Amount of players who are currently online</td>\n</tr>\n<tr>\n<td><pre>'max_players'</pre></td>\n<td>Number of the slots of the server</td>\n</tr>\n<tr>\n<td><pre>'description'</pre></td>\n<td>The message of the day of the server </td>\n</tr>\n<tr>\n<td><pre>'description_raw'</pre></td>\n<td>The raw version of description <br>(contains color codes etc.)</td>\n</tr>\n<tr>\n<td><pre>'favicon'</pre></td>\n<td>The favicon of the server in a base64 string <br>(Can be displayed with the html img tag by setting the string as src)</td>\n</tr>\n<tr>\n<td><pre>'modinfo'</pre></td>\n<td>Informations about the plugins</td>\n</tr>\n</table>\n\n\n"
  },
  {
    "path": "composer.json",
    "content": "{\n\t\"name\" : \"funnyitselmo/minecraftserverstatus\",\n\t\"type\" : \"library\",\n\t\"description\" : \"Minecraft Server Status Query, written in PHP, with online players, motd, favicon and more server related informations without plugins and enable-query.\",\n\t\"keywords\" : [\n\t\t\"minecraft\",\n\t\t\"server\",\n\t\t\"status\"\n\t],\n\t\"license\" : \"BSD\",\n\t\"repositories\" : [{\n\t\t\t\"type\" : \"vcs\",\n\t\t\t\"url\" : \"https://github.com/FunnyItsElmo/PHP-Minecraft-Server-Status-Query.git\"\n\t\t}\n\t],\n\t\"autoload\" : {\n\t\t\"psr-4\" : {\n\t\t\t\"MinecraftServerStatus\\\\\" : \"src/\",\n\t\t\t\"MinecraftServerStatus\\\\Packets\\\\\" : \"src/Packets/\"\n\t\t}\n\t},\n\t\"authors\" : [{\n\t\t\t\"name\" : \"Julian Spravil\",\n\t\t\t\"email\" : \"julian.spr@t-online.de\"\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "example/index.php",
    "content": "<?php\nuse MinecraftServerStatus\\MinecraftServerStatus;\n\nrequire '../vendor/autoload.php';\n\n$response = MinecraftServerStatus::query('lostforce.com', 25565);\n\nif (! $response) {\n    echo \"The Server is offline!\";\n} else {\n    echo \"<img width=\\\"64\\\" height=\\\"64\\\" src=\\\"\" . $response['favicon'] . \"\\\" /> <br>\n\t\tThe Server \" . $response['hostname'] . \" is running on \" . $response['version'] . \" and is online,\n\t\tcurrently are \" . $response['players'] . \" players online\n\t\tof a maximum of \" . $response['max_players'] . \". The motd of the server is '\" . $response['description'] . \"'.\n\t\tThe server has a ping of \" . $response['ping'] . \" milliseconds.\";\n}\n"
  },
  {
    "path": "src/MinecraftServerStatus.php",
    "content": "<?php\nnamespace MinecraftServerStatus;\nuse MinecraftServerStatus\\Packets\\HandshakePacket;\nuse MinecraftServerStatus\\Packets\\PingPacket;\n\nclass MinecraftServerStatus {\n\n    /**\n     * Queries the server and returns the servers information\n     *\n     * @param string $host            \n     * @param number $port            \n     */\n    public static function query ($host = '127.0.0.1', $port = 25565) {\n        // check if the host is in ipv4 format\n        $host = filter_var($host, FILTER_VALIDATE_IP) ? $host : gethostbyname($host);\n        \n        $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);\n        if (! @socket_connect($socket, $host, $port)) {\n            return false;\n        }\n        \n        // create the handshake and ping packet\n        $handshakePacket = new HandshakePacket($host, $port, 107, 1);\n        $pingPacket = new PingPacket();\n        \n        $handshakePacket->send($socket);\n        \n        // high five\n        $start = microtime(true);\n        $pingPacket->send($socket);\n        $length = self::readVarInt($socket);\n        $ping = round((microtime(true) - $start) * 1000);\n        \n        // read the requested data\n        $data = socket_read($socket, $length, PHP_NORMAL_READ);\n        $data = strstr($data, '{');\n        $data = json_decode($data);\n        \n        $descriptionRaw = isset($data->description) ? $data->description : false;\n        $description = $descriptionRaw;\n        \n        // colorize the description if it is supported\n        if (gettype($descriptionRaw) == 'object') {\n            $description = '';\n            \n            if (isset($descriptionRaw->text)) {\n                $color = isset($descriptionRaw->color) ? $descriptionRaw->color : '';\n                $description = '<font color=\"' . $color . '\">' . $descriptionRaw->text . '</font>';\n            }\n            \n            if (isset($descriptionRaw->extra)) {\n                foreach ($descriptionRaw->extra as $item) {\n                    $description .= isset($item->bold) && $item->bold ? '<b>' : '';\n                    $description .= isset($item->color) ? '<font color=\"' . $item->color . '\">' . $item->text . '</font>' : '';\n                    $description .= isset($item->bold) && $item->bold ? '</b>' : '';\n                }\n            }\n        }\n        \n        return array(\n                'hostname' => $host,\n                'port' => $port,\n                'ping' => $ping,\n                'version' => isset($data->version->name) ? $data->version->name : false,\n                'protocol' => isset($data->version->protocol) ? $data->version->protocol : false,\n                'players' => isset($data->players->online) ? $data->players->online : false,\n                'max_players' => isset($data->players->max) ? $data->players->max : false,\n                'description' => $description,\n                'description_raw' => $descriptionRaw,\n                'favicon' => isset($data->favicon) ? $data->favicon : false,\n                'modinfo' => isset($data->modinfo) ? $data->modinfo : false\n        );\n    }\n\n    private static function readVarInt ($socket) {\n        $a = 0;\n        $b = 0;\n        while (true) {\n            $c = socket_read($socket, 1);\n            if (! $c) {\n                return 0;\n            }\n            $c = Ord($c);\n            $a |= ($c & 0x7F) << $b ++ * 7;\n            if ($b > 5) {\n                return false;\n            }\n            if (($c & 0x80) != 128) {\n                break;\n            }\n        }\n        return $a;\n    }\n}\n"
  },
  {
    "path": "src/Packets/HandshakePacket.php",
    "content": "<?php\nnamespace MinecraftServerStatus\\Packets;\n\nclass HandshakePacket extends Packet {\n\n    public function __construct ($host, $port, $protocol, $nextState) {\n        parent::__construct(0);\n        $this->addUnsignedChar($protocol);\n        $this->addString($host);\n        $this->addUnsignedShort($port);\n        $this->addUnsignedChar($nextState);\n    }\n}\n"
  },
  {
    "path": "src/Packets/Packet.php",
    "content": "<?php\nnamespace MinecraftServerStatus\\Packets;\n\nclass Packet {\n\n    protected $packetID;\n\n    protected $data;\n\n    public function __construct ($packetID) {\n        $this->packetID = $packetID;\n        $this->data = pack('C', $packetID);\n    }\n\n    public function addSignedChar ($data) {\n        $this->data .= pack('c', $data);\n    }\n\n    public function addUnsignedChar ($data) {\n        $this->data .= pack('C', $data);\n    }\n\n    public function addSignedShort ($data) {\n        $this->data .= pack('s', $data);\n    }\n\n    public function addUnsignedShort ($data) {\n        $this->data .= pack('S', $data);\n    }\n\n    public function addString ($data) {\n        $this->data .= pack('C', strlen($data));\n        $this->data .= $data;\n    }\n\n    public function send ($socket) {\n        $this->data = pack('C', strlen($this->data)) . $this->data;\n        socket_send($socket, $this->data, strlen($this->data), 0);\n    }\n}\n"
  },
  {
    "path": "src/Packets/PingPacket.php",
    "content": "<?php\nnamespace MinecraftServerStatus\\Packets;\n\nclass PingPacket extends Packet {\n\n    public function __construct () {\n        parent::__construct(0);\n    }\n}\n"
  }
]