-
-
Notifications
You must be signed in to change notification settings - Fork 6
/
state.php
87 lines (80 loc) · 2.15 KB
/
state.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
<?php
class State {
/**
* @var array<string, int> A cache of clients, so we do not need to
* look up the ID of clients that have recently connected. The array key
* is the IP:port of the client, the array value is the database ID.
*/
private array $clientIdCache;
public function __construct(
private PDO $db,
private Canvas $canvas,
) {
$this->clientIdCache = [];
$this->getData();
}
public function clientConnection(
Socket $socket,
Canvas $canvas,
callable $sendFunction,
):void {
socket_getpeername($socket, $address, $port);
$newId = $this->query("new-client", [
"ip" => $address,
"port" => $port,
"timestamp" => (int)(microtime(true) * 100),
]);
$this->clientIdCache["$address:$port"] = $newId;
call_user_func($sendFunction, $socket, (object)[
"type" => "update",
"data" => $canvas->getData(),
]);
}
public function getData(?int $timestamp = null):array {
$params = ["timestamp" => $timestamp];
foreach($this->query("get-state", $params) as $row) {
$this->canvas->setData(
$row["x"],
$row["y"],
$row["c"]
);
}
return $this->canvas->getData((bool)$timestamp);
}
public function clientData(Socket $socket, string $data):void {
$obj = json_decode($data, true);
socket_getpeername($socket, $address, $port);
$obj["id"] = $this->clientIdCache["$address:$port"];
$obj["timestamp"] = (int)(microtime(true) * 100);
if(array_key_exists("c", $obj)) {
$this->query("set-text", $obj);
}
else {
$this->query("update-cursor", $obj);
}
}
/**
* @param array<string, int|string> $data
* @return int|array<string, mixed>
*/
private function query(string $name, array $data = []):int|array {
$sql = file_get_contents("db-$name.sql");
$stmt = $this->db->prepare($sql);
$bindings = [];
foreach($data as $key => $value) {
$bindings[":" . $key] = $value;
}
try {
$stmt->execute($bindings);
}
catch(PDOException $exception) {
echo "Error " . $exception->getCode() . " " . $exception->getMessage(), PHP_EOL;
}
if($stmt->columnCount() > 0) {
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
else {
return $this->db->lastInsertId() ?: $stmt->rowCount();
}
}
}