-
Notifications
You must be signed in to change notification settings - Fork 0
/
Query.php
127 lines (97 loc) · 3.22 KB
/
Query.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?php
declare(strict_types=1);
require_once('Packet.php');
require_once('Socket.php');
require_once('VO/InfoType.php');
final class Query
{
private $socket;
public function __construct(Socket $socket) {
$this->socket = $socket;
}
/**
* @throws RuntimeException
*/
public function ping(): int {
$packet = new Packet(
$this->socket->getServer(),
InfoType::fromName('ping'),
$payload = random_bytes(4)
);
$start = microtime(true);
$this->socket->send($packet);
$this->socket->readRaw(11);
if($this->socket->readRaw(4) !== $payload) {
throw new RuntimeException('Malformed response.');
}
$ping = (microtime(true) - $start) * 1000;
return (int) ceil($ping);
}
public function getServerInfo(): array {
$packet = new Packet(
$this->socket->getServer(),
InfoType::fromName('info')
);
$this->socket->send($packet);
$this->socket->readRaw(11); // strip header
return [
'password' => $this->socket->readBool(),
'players' => $this->socket->readInt16(),
'max_players' => $this->socket->readInt16(),
'hostname' => $this->socket->readString(),
'gamemode' => $this->socket->readString(),
'language' => $this->socket->readString(),
];
}
public function getRules(): array {
$packet = new Packet(
$this->socket->getServer(),
InfoType::fromName('rules')
);
$this->socket->send($packet);
$this->socket->readRaw(11);
$ruleCount = $this->socket->readInt16();
$rules = [];
for($i = 0; $i < $ruleCount; $i++) {
$rule = $this->socket->readString(1);
$value = $this->socket->readString(1);
$rules[$rule] = $value;
}
return $rules;
}
public function getBasicPlayers(): array {
$packet = new Packet(
$this->socket->getServer(),
InfoType::fromName('basic_players')
);
$this->socket->send($packet);
$this->socket->readRaw(11);
$playerCount = $this->socket->readInt16();
$players = [];
for($i = 0; $i < $playerCount; $i++) {
$name = $this->socket->readString(1);
$score = $this->socket->readInt32();
$players[$name] = $score;
}
return $players;
}
public function getDetailedPlayers(): array {
$packet = new Packet(
$this->socket->getServer(),
InfoType::fromName('detailed_players')
);
$this->socket->send($packet);
$this->socket->readRaw(11);
$playerCount = $this->socket->readInt16();
$players = [];
for($i = 0; $i < $playerCount; $i++) {
$playerId = $this->socket->readInt8(); // only 0 - 255 possible
$players[$playerId] = [
'name' => $this->socket->readString(1),
'score' => $this->socket->readInt32(),
'ping' => $this->socket->readInt32(),
];
}
return $players;
}
}