-
Notifications
You must be signed in to change notification settings - Fork 1
/
history-bin.js
113 lines (82 loc) · 2.31 KB
/
history-bin.js
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
import { BufferedWriter } from "./buffer.js";
import { HistoryStorage } from "./storage.js";
export class HistoryBin {
static #instance;
#server;
#closed = false;
#writers = {};
constructor(server) {
this.#server = server;
}
static getInstance(server) {
if (!HistoryBin.#instance) {
HistoryBin.#instance = new HistoryBin(server);
}
return HistoryBin.#instance;
}
#writer(timestamp, license) {
const writer = this.#writers[license];
if (writer) {
writer.setTimestamp(timestamp);
return writer;
}
this.#writers[license] = new BufferedWriter(this.#server, timestamp, license);
return this.#writers[license];
}
#write(storage, timestamp, player) {
const coords = player.coords,
character = player.character;
if (!character || !(character.flags & 64)) {
return false;
}
/**
* | Timestamp (ui32) | character_id (ui32) | x (f32) | y (f32) | z (f32) | heading (f32) | speed (f32) | character_flags (ui32) | user_flags (ui32) |
*/
const license = player.licenseIdentifier.replace(/^license:/m, ""),
writer = this.#writer(timestamp, license);
writer.writeUint32(timestamp);
writer.writeUint32(character.id);
writer.writeFloat32(coords.x);
writer.writeFloat32(coords.y);
writer.writeFloat32(coords.z);
writer.writeFloat32(coords.w);
writer.writeFloat32(player.speed);
writer.writeUint32(character.flags);
writer.writeUint32(player.flags);
writer.persist(storage);
return license;
}
async writeAll(players) {
if (this.#closed || !players?.length) return;
const storage = await HistoryStorage.getInstance();
if (!storage.available()) {
return;
}
const timestamp = Math.floor(Date.now() / 1000),
active = {};
for (const player of players) {
const license = this.#write(storage, timestamp, player);
if (license) {
active[license] = true;
}
}
for (const license in this.#writers) {
if (!active[license]) {
const writer = this.#writers[license];
writer.close(storage);
delete this.#writers[license];
}
}
}
async close() {
if (this.#closed) return;
this.#closed = true;
const storage = await HistoryStorage.getInstance(),
promises = [];
for (const license in this.#writers) {
const writer = this.#writers[license];
promises.push(writer.close(storage));
}
await Promise.all(promises);
}
}