forked from OpenRCT2/master-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMasterServer.php
More file actions
104 lines (87 loc) · 3.05 KB
/
MasterServer.php
File metadata and controls
104 lines (87 loc) · 3.05 KB
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
<?php
error_reporting(0);
class MasterServer {
public $key;
public $port;
public $address;
function __construct($key, $port=0) {
$this->key = $key;
$this->port = +$port;
$this->address = $_SERVER['REMOTE_ADDR'];
$this->db = new SQLite3('../servers.db');
$this->db->exec("CREATE TABLE IF NOT EXISTS servers
(key STRING, time INTEGER, address STRING,
port INTEGER, name STRING, haspassword INTEGER,
description STRING, version STRING, players INTEGER,
maxplayers INTEGER);");
$this->db->exec("CREATE UNIQUE INDEX addr_idx ON servers(address, port);");
}
public function request_gameinfo() {
$NETWORK_COMMAND_GAMEINFO = pack("nN", 4, 9);
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 5, 'usec' => 5000));
if(socket_connect($sock, $this->address, $this->port) === TRUE) {
$info_len = strlen($NETWORK_COMMAND_GAMEINFO);
if(socket_write($sock, $NETWORK_COMMAND_GAMEINFO, $info_len) == $info_len) {
if(socket_recv($sock, $size, 2, MSG_WAITALL) == 2) {
$size = unpack("n", $size)[1];
$data = '';
if(socket_recv($sock, $data, $size, MSG_WAITALL) == $size) {
socket_shutdown($sock);
// Receive all
while(socket_recv($sock, $null, 9999, MSG_WAITALL));
socket_close($sock);
return trim(substr($data, 4));
}
}
}
}
return FALSE;
}
public function update_server($data) {
if($data) {
$sql = "INSERT OR REPLACE INTO servers VALUES (:key, DATETIME('NOW'), :address, :port, :name, :haspassword, :description, :version, :players, :maxplayers);";
$stmt = $this->db->prepare($sql);
$stmt->bindValue(':key', $this->key);
$stmt->bindValue(':address', $this->address);
$stmt->bindValue(':port', $this->port);
$obj = json_decode($data);
$stmt->bindValue(':name', $obj->name);
$stmt->bindValue(':haspassword', $obj->haspassword);
$stmt->bindValue(':description', $obj->description);
$stmt->bindValue(':version', $obj->version);
$stmt->bindValue(':players', $obj->players);
$stmt->bindValue(':maxplayers', $obj->maxplayers);
$stmt->execute();
}
}
public function remove_old_servers() {
$this->db->query("DELETE FROM servers WHERE time < DATETIME('now', '-70 seconds');");
}
public function list_servers() {
$servers = array();
$result = $this->db->query("SELECT * FROM servers");
while($row = $result->fetchArray()) {
$data = array(
'address' => "{$row['address']}:{$row['port']}",
'name' => $row['name'],
'haspassword' => $row['haspassword'],
'description' => $row['description'],
'version' => $row['version'],
'players' => $row['players'],
'maxplayers' => $row['maxplayers']
);
array_push($servers, $data);
}
@header('Content-Type: application/json');
return $servers;
}
}
$server = new MasterServer($_GET['key'], +$_GET['port']);
if($server->port > 0){
$data = $server->request_gameinfo();
$server->update_server($data);
}else{
$server->remove_old_servers();
echo json_encode($server->list_servers());
}