1 /*
2  * Copyright (c) 2017 SEL
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU Lesser General Public License for more details.
13  * 
14  */
15 module sel.hncom.status;
16 
17 import std.json : JSONValue;
18 import std.socket : Address;
19 import std.typecons : Tuple;
20 import std.uuid : UUID;
21 
22 import sel.hncom.about;
23 import sel.hncom.io : IO;
24 
25 /**
26  * Used to calculate latency by both the hub and the node.
27  * When this packet is received it should be immeditaly sent back to the sender
28  * without any change.
29  */
30 @clientbound @serverbound struct Latency {
31 
32 	enum ubyte ID = 7;
33 
34 	/**
35 	 * Id of the ping/pong. Should be unique for the session.
36 	 */
37 	uint id;
38 
39 	mixin IO!(id);
40 
41 }
42 
43 /**
44  * Notifies the node that the hub's reloadeable settings have been reloaded and that
45  * the node should also reload its resources (for example plugin's settings).
46  * The fields of the packet may be empty if not updated during the reload.
47  */
48 @clientbound struct Reload {
49 
50 	enum ubyte ID = 8;
51 
52 	/**
53 	 * Display name of the server in the same format as HubInfo's displayName field.
54 	 */
55 	string displayName;
56 
57 	/**
58 	 * New MOTDs (message of the day) for the supported games.
59 	 */
60 	string[ubyte] motds;
61 
62 	/**
63 	 * Main language of the server in the same format as HubInfo's language field.
64 	 */
65 	string language;
66 
67 	/**
68 	 * 
69 	 */
70 	string[] acceptedLanguages;
71 
72 	/**
73 	 * 
74 	 */
75 	JSONValue additionalJSON;
76 
77 	mixin IO!(displayName, motds, language, acceptedLanguages, additionalJSON);
78 
79 }
80 
81 /**
82  * Sends a logged message to the hub.
83  */
84 @serverbound struct Log {
85 
86 	enum ubyte ID = 9;
87 	
88 	enum int NO_WORLD = -1;
89 
90 	/**
91 	 * Unix time (in milliseconds) that indicates the exact creation time of the
92 	 * log (for ordering purposes).
93 	 */
94 	ulong timestamp;
95 
96 	/**
97 	 * Id of the world that has generated the log, if the log comes from a world, -1 otherwise.
98 	 */
99 	int worldId = -1;
100 
101 	/**
102 	 * Name of the logger thas has generated the log, if the log doesn't come from a world.
103 	 */
104 	string logger;
105 
106 	/**
107 	 * Logged message. It may contain Minecraft formatting codes.
108 	 */
109 	string message;
110 
111 	/**
112 	 * Identifier of the command that has generated the log or -1 if the
113 	 * log wasn't generated by a command.
114 	 */
115 	int commandId = -1;
116 
117 	mixin IO!(timestamp, worldId, logger, message, commandId);
118 
119 }
120 
121 /**
122  * Notifies the node that another node (that is not the receiver) has connected to the hub.
123  */
124 @clientbound struct AddNode {
125 
126 	enum ubyte ID = 10;
127 
128 	/**
129 	 * Identifier given by the hub to uniquey identify the node.
130 	 */
131 	uint hubId;
132 
133 	/**
134 	 * Node's name used for displaying and identification purposes.
135 	 */
136 	string name;
137 
138 	/**
139 	 * Whether the node is a main node.
140 	 */
141 	bool main;
142 
143 	/**
144 	 * Indicates the games and protocols accepted by the node.
145 	 */
146 	uint[][ubyte] acceptedGames;
147 
148 	mixin IO!(hubId, name, main, acceptedGames);
149 
150 }
151 
152 /**
153  * Notifies the node that another node, previously added with AddNode,
154  * has disconnected from the hub.
155  */
156 @clientbound struct RemoveNode {
157 
158 	enum ubyte ID = 11;
159 
160 	/**
161 	 * Node's id given by the hub.
162 	 */
163 	uint hubId;
164 
165 	mixin IO!(hubId);
166 
167 }
168 
169 /**
170  * Receives a binary message sent by another node using SendMessage.
171  */
172 @clientbound struct ReceiveMessage {
173 
174 	enum ubyte ID = 12;
175 
176 	/**
177 	 * Id of the node that has sent the message.
178 	 */
179 	uint sender;
180 
181 	/**
182 	 * Indicates whether the message was broadcasted to every connected node.
183 	 */
184 	bool broadcasted;
185 
186 	/**
187 	 * Bytes received. It could be serialised data or a plugin-defined packet.
188 	 */
189 	ubyte[] payload;
190 
191 	mixin IO!(sender, payload);
192 
193 }
194 
195 /**
196  * Sends a binary message to some selected nodes or broadcast it.
197  */
198 @serverbound struct SendMessage {
199 	
200 	enum ubyte ID = 13;
201 
202 	/**
203 	 * Addressees of the message. If the array is empty the message is
204 	 * broadcasted to every connected node but the sender.
205 	 */
206 	uint[] addressees;
207 
208 	/**
209 	 * Bytes to be sent/broadcasted. It may be serialised data or a plugin-defined packet.
210 	 */
211 	ubyte[] payload;
212 
213 	mixin IO!(addressees, payload);
214 	
215 }
216 
217 /**
218  * Updates the number of players on the server.
219  */
220 @clientbound struct UpdatePlayers {
221 
222 	enum ubyte ID = 14;
223 
224 	enum int UNLIMITED = -1;
225 
226 	/**
227 	 * Players currently online in the whole server (connected to a node).
228 	 */
229 	uint online;
230 
231 	/**
232 	 * Maximum number of players that can connect to server, which is the sum of
233 	 * the max players of every connected node.
234 	 */
235 	int max;
236 
237 	mixin IO!(online, max);
238 
239 }
240 
241 /**
242  * Updates the number of players that can be accepted by the node.
243  * If the given number is smaller than the players currently connected
244  * to the node no player should be kicked.
245  */
246 @serverbound struct UpdateMaxPlayers {
247 
248 	enum ubyte ID = 15;
249 
250 	enum uint UNLIMITED = 0;
251 
252 	/**
253 	 * Maximum number of players accepted by node.
254 	 */
255 	uint max;
256 
257 	mixin IO!(max);
258 
259 }
260 
261 /**
262  * Updates the usage of the system's resources of the node.
263  */
264 @serverbound struct UpdateUsage {
265 
266 	enum ubyte ID = 16;
267 
268 	/**
269 	 * Kibibytes of RAM used by the node.
270 	 */
271 	uint ram;
272 
273 	/**
274 	 * Percentage of CPU used by the node. It may be higher than 100
275 	 * if the node has more than 1 CPU
276 	 */
277 	float cpu;
278 
279 	mixin IO!(ram, cpu);
280 
281 }
282 
283 /**
284  * Executes a command on the node.
285  */
286 @clientbound struct RemoteCommand {
287 
288 	enum ubyte ID = 17;
289 
290 	enum : ubyte {
291 
292 		HUB = 1,
293 		EXTERNAL_CONSOLE,
294 		REMOTE_PANEL,
295 		RCON,
296 
297 	}
298 
299 	/**
300 	 * Origin of the command. It could be the hub itself or an external source.
301 	 */
302 	ubyte origin;
303 
304 	/**
305 	 * Address of the sender if the command has been sent from an external source.
306 	 * It's `null` when the hub is the sender.
307 	 */
308 	Address sender;
309 
310 	/**
311 	 * Commands and arguments that should be executed on the node.
312 	 * For example `say hello world` or `kill @a`.
313 	 */
314 	string command;
315 
316 	/**
317 	 * Identifier of the command. It's sent back in Log's commandId field
318 	 * when the command generates output.
319 	 */
320 	uint commandId;
321 
322 	mixin IO!(origin, sender, command, commandId);
323 
324 }
325 
326 /**
327  * Notifies the hub that a new world has been created on the node.
328  */
329 @serverbound struct AddWorld {
330 	
331 	enum ubyte ID = 18;
332 
333 	/**
334 	 * Id of the world. It's unique on the node.
335 	 */
336 	uint worldId;
337 
338 	/**
339 	 * Name of the world, it doesn't need to be unique.
340 	 */
341 	string name;
342 
343 	/**
344 	 * World's dimension in the MCPE format (0: overworld, 1: nether, 2: end).
345 	 */
346 	ubyte dimension;
347 
348 	/**
349 	 * Id of the world's parent or -1 if the world has no parent. This is usually used
350 	 * for nether/end which are children of an overworld world.
351 	 */
352 	int parent = -1;
353 	
354 	mixin IO!(worldId, name, dimension, parent);
355 	
356 }
357 
358 /**
359  * Notifies the hub that a world has been removed from the node.
360  */
361 @serverbound struct RemoveWorld {
362 	
363 	enum ubyte ID = 19;
364 
365 	/**
366 	 * Id of the world that has been removed, previosly added using the
367 	 * AddWorld packet.
368 	 */
369 	uint worldId;
370 	
371 	mixin IO!(worldId);
372 	
373 }
374 
375 @clientbound struct ListInfo {
376 
377 	alias EntryUUID = Tuple!(ubyte, "game", UUID, "uuid");
378 
379 	alias EntryUsername = Tuple!(ubyte, "game", string, "username");
380 
381 	enum ubyte ID = 20;
382 
383 	enum : ubyte {
384 
385 		WHITELIST,
386 		BLACKLIST
387 
388 	}
389 
390 	ubyte list;
391 
392 	EntryUUID[] entriesByUUID;
393 
394 	EntryUsername[] entriesByUsername;
395 
396 	string[] entriesByIp;
397 
398 	mixin IO!(list, entriesByUUID, entriesByUsername, entriesByIp);
399 
400 }
401 
402 @clientbound @serverbound struct UpdateListByUUID {
403 
404 	enum ubyte ID = 21;
405 
406 	ubyte list;
407 
408 	ubyte game;
409 
410 	UUID uuid;
411 
412 	mixin IO!(list, game, uuid);
413 
414 }
415 
416 @clientbound @serverbound struct UpdateListByUsername {
417 
418 	enum ubyte ID = 22;
419 
420 	ubyte list;
421 
422 	ubyte game;
423 
424 	string username;
425 
426 	mixin IO!(list, game, username);
427 
428 }
429 
430 @clientbound @serverbound struct UpdateListByIp {
431 
432 	enum ubyte ID = 23;
433 
434 	ubyte list;
435 
436 	string ip;
437 
438 	mixin IO!(list, ip);
439 
440 }
441 
442 @clientbound struct PanelCredentials {
443 
444 	enum ubyte ID = 24;
445 
446 	string address;
447 	ubyte[64] hash;
448 	uint worldId;
449 
450 	mixin IO!(address, hash, worldId);
451 
452 }