PocketMine-MP 5.15.1 git-5ef247620a7c6301a849b54e5ef1009217729fc8
QueryInfo.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
25
26use pocketmine\player\GameMode;
33use function array_map;
34use function chr;
35use function count;
36use function str_replace;
37use function substr;
38
39final class QueryInfo{
40 public const GAME_ID = "MINECRAFTPE";
41
42 private string $serverName;
43 private bool $listPlugins;
45 private array $plugins;
47 private array $players;
48
49 private string $gametype;
50 private string $version;
51 private string $server_engine;
52 private string $map;
53 private int $numPlayers;
54 private int $maxPlayers;
55 private string $whitelist;
56 private int $port;
57 private string $ip;
58
63 private array $extraData = [];
64
65 private ?string $longQueryCache = null;
66 private ?string $shortQueryCache = null;
67
68 public function __construct(Server $server){
69 $this->serverName = $server->getMotd();
70 $this->listPlugins = $server->getConfigGroup()->getPropertyBool(YmlServerProperties::SETTINGS_QUERY_PLUGINS, true);
71 $this->plugins = $server->getPluginManager()->getPlugins();
72 $this->players = array_map(fn(Player $p) => $p->getName(), $server->getOnlinePlayers());
73
74 $this->gametype = ($server->getGamemode() === GameMode::SURVIVAL || $server->getGamemode() === GameMode::ADVENTURE) ? "SMP" : "CMP";
75 $this->version = $server->getVersion();
76 $this->server_engine = $server->getName() . " " . $server->getPocketMineVersion();
77 $world = $server->getWorldManager()->getDefaultWorld();
78 $this->map = $world === null ? "unknown" : $world->getDisplayName();
79 $this->numPlayers = count($this->players);
80 $this->maxPlayers = $server->getMaxPlayers();
81 $this->whitelist = $server->hasWhitelist() ? "on" : "off";
82 $this->port = $server->getPort();
83 $this->ip = $server->getIp();
84
85 }
86
87 private function destroyCache() : void{
88 $this->longQueryCache = null;
89 $this->shortQueryCache = null;
90 }
91
92 public function getServerName() : string{
93 return $this->serverName;
94 }
95
96 public function setServerName(string $serverName) : void{
97 $this->serverName = $serverName;
98 $this->destroyCache();
99 }
100
101 public function canListPlugins() : bool{
102 return $this->listPlugins;
103 }
104
105 public function setListPlugins(bool $value) : void{
106 $this->listPlugins = $value;
107 $this->destroyCache();
108 }
109
113 public function getPlugins() : array{
114 return $this->plugins;
115 }
116
120 public function setPlugins(array $plugins) : void{
121 Utils::validateArrayValueType($plugins, function(Plugin $_) : void{});
122 $this->plugins = $plugins;
123 $this->destroyCache();
124 }
125
129 public function getPlayerList() : array{
130 return $this->players;
131 }
132
136 public function setPlayerList(array $players) : void{
137 Utils::validateArrayValueType($players, function(string $_) : void{});
138 $this->players = $players;
139 $this->destroyCache();
140 }
141
142 public function getPlayerCount() : int{
143 return $this->numPlayers;
144 }
145
146 public function setPlayerCount(int $count) : void{
147 $this->numPlayers = $count;
148 $this->destroyCache();
149 }
150
151 public function getMaxPlayerCount() : int{
152 return $this->maxPlayers;
153 }
154
155 public function setMaxPlayerCount(int $count) : void{
156 $this->maxPlayers = $count;
157 $this->destroyCache();
158 }
159
160 public function getWorld() : string{
161 return $this->map;
162 }
163
164 public function setWorld(string $world) : void{
165 $this->map = $world;
166 $this->destroyCache();
167 }
168
175 public function getExtraData() : array{
176 return $this->extraData;
177 }
178
184 public function setExtraData(array $extraData) : void{
185 $this->extraData = $extraData;
186 $this->destroyCache();
187 }
188
189 public function getLongQuery() : string{
190 if($this->longQueryCache !== null){
191 return $this->longQueryCache;
192 }
193 $query = "";
194
195 $plist = $this->server_engine;
196 if(count($this->plugins) > 0 && $this->listPlugins){
197 $plist .= ":";
198 foreach($this->plugins as $p){
199 $d = $p->getDescription();
200 $plist .= " " . str_replace([";", ":", " "], ["", "", "_"], $d->getName()) . " " . str_replace([";", ":", " "], ["", "", "_"], $d->getVersion()) . ";";
201 }
202 $plist = substr($plist, 0, -1);
203 }
204
205 $KVdata = [
206 "splitnum" => chr(128),
207 "hostname" => $this->serverName,
208 "gametype" => $this->gametype,
209 "game_id" => self::GAME_ID,
210 "version" => $this->version,
211 "server_engine" => $this->server_engine,
212 "plugins" => $plist,
213 "map" => $this->map,
214 "numplayers" => $this->numPlayers,
215 "maxplayers" => $this->maxPlayers,
216 "whitelist" => $this->whitelist,
217 "hostip" => $this->ip,
218 "hostport" => $this->port
219 ];
220
221 foreach($KVdata as $key => $value){
222 $query .= $key . "\x00" . $value . "\x00";
223 }
224
225 foreach(Utils::stringifyKeys($this->extraData) as $key => $value){
226 $query .= $key . "\x00" . $value . "\x00";
227 }
228
229 $query .= "\x00\x01player_\x00\x00";
230 foreach($this->players as $player){
231 $query .= $player . "\x00";
232 }
233 $query .= "\x00";
234
235 return $this->longQueryCache = $query;
236 }
237
238 public function getShortQuery() : string{
239 return $this->shortQueryCache ?? ($this->shortQueryCache = $this->serverName . "\x00" . $this->gametype . "\x00" . $this->map . "\x00" . $this->numPlayers . "\x00" . $this->maxPlayers . "\x00" . Binary::writeLShort($this->port) . $this->ip . "\x00");
240 }
241}