1 /*
2  * Copyright (c) 2017-2018 sel-project
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  *
22  */
23 /**
24  * Copyright: Copyright (c) 2017-2018 sel-project
25  * License: MIT
26  * Authors: Kripth
27  * Source: $(HTTP github.com/sel-project/sel-hncom/sel/hncom/status.d, sel/hncom/status.d)
28  */
29 module sel.hncom.status;
30 
31 import std.json : JSONValue;
32 import std.socket : Address;
33 import std.typecons : Tuple;
34 import std.uuid : UUID;
35 
36 import sel.hncom.about;
37 import sel.hncom.io : IO;
38 
39 /**
40  * Used to calculate latency by both the hub and the node.
41  * When this packet is received it should be immeditaly sent back to the sender
42  * without any change.
43  */
44 @clientbound @serverbound struct Latency {
45 
46 	enum ubyte ID = 7;
47 
48 	/**
49 	 * Id of the ping/pong. Should be unique for the session.
50 	 */
51 	uint id;
52 
53 	mixin IO!(id);
54 
55 }
56 
57 /**
58  * Sends a logged message to the hub.
59  */
60 @serverbound struct Log {
61 
62 	enum ubyte ID = 8;
63 	
64 	alias Message = Tuple!(bool, "translation", string, "message", string[], "params");
65 
66 	enum int NO_COMMAND = -1;
67 	
68 	enum int NO_WORLD = -1;
69 
70 	/**
71 	 * Logged message or translation. It may contain Minecraft formatting codes.
72 	 */
73 	Message[] message;
74 	
75 	/**
76 	 * Unix time (in milliseconds) that indicates the exact creation time of the
77 	 * log (for ordering purposes).
78 	 */
79 	ulong timestamp;
80 
81 	/**
82 	 * Identifier of the command that has generated the log or -1 if the
83 	 * log wasn't generated by a command.
84 	 */
85 	int commandId = NO_COMMAND;
86 	
87 	/**
88 	 * Id of the world that has generated the log, if the log comes from a world, -1 otherwise.
89 	 */
90 	int worldId = NO_WORLD;
91 
92 	mixin IO!(message, timestamp, commandId, worldId);
93 
94 }
95 
96 /**
97  * Executes a command on the node.
98  */
99 @clientbound struct RemoteCommand {
100 	
101 	enum ubyte ID = 9;
102 	
103 	enum : ubyte {
104 		
105 		HUB = 0,
106 		WEB_ADMIN = 1,
107 		RCON = 2,
108 		
109 	}
110 	
111 	/**
112 	 * Origin of the command. It could be the hub itself or an external source.
113 	 */
114 	ubyte origin;
115 	
116 	/**
117 	 * Address of the sender if the command has been sent from an external source.
118 	 * It's `null` when the hub is the sender.
119 	 */
120 	Address sender;
121 	
122 	/**
123 	 * Commands and arguments that should be executed on the node.
124 	 * For example `say hello world` or `kill @a`.
125 	 */
126 	string command;
127 	
128 	/**
129 	 * Identifier of the command. It's sent back in Log's commandId field
130 	 * when the command generates output.
131 	 */
132 	uint commandId;
133 	
134 	mixin IO!(origin, sender, command, commandId);
135 	
136 }
137 
138 /**
139  * Notifies the node that another node (that is not the receiver) has connected to the hub.
140  */
141 @clientbound struct AddNode {
142 
143 	enum ubyte ID = 10;
144 
145 	/**
146 	 * Identifier given by the hub to uniquey identify the node.
147 	 */
148 	uint hubId;
149 
150 	/**
151 	 * Node's name used for displaying and identification purposes.
152 	 */
153 	string name;
154 
155 	/**
156 	 * Whether the node is a main node.
157 	 */
158 	bool main;
159 
160 	/**
161 	 * Indicates the games and protocols accepted by the node.
162 	 */
163 	uint[][ubyte] acceptedGames;
164 
165 	mixin IO!(hubId, name, main, acceptedGames);
166 
167 }
168 
169 /**
170  * Notifies the node that another node, previously added with AddNode,
171  * has disconnected from the hub.
172  */
173 @clientbound struct RemoveNode {
174 
175 	enum ubyte ID = 11;
176 
177 	/**
178 	 * Node's id given by the hub.
179 	 */
180 	uint hubId;
181 
182 	mixin IO!(hubId);
183 
184 }
185 
186 /**
187  * Receives a binary message sent by another node using SendMessage.
188  */
189 @clientbound struct ReceiveMessage {
190 
191 	enum ubyte ID = 12;
192 
193 	/**
194 	 * Id of the node that has sent the message.
195 	 */
196 	uint sender;
197 
198 	/**
199 	 * Indicates whether the message was broadcasted to every connected node.
200 	 */
201 	bool broadcasted;
202 
203 	/**
204 	 * Bytes received. It could be serialised data or a plugin-defined packet.
205 	 */
206 	ubyte[] payload;
207 
208 	mixin IO!(sender, payload);
209 
210 }
211 
212 /**
213  * Sends a binary message to some selected nodes or broadcast it.
214  */
215 @serverbound struct SendMessage {
216 	
217 	enum ubyte ID = 13;
218 
219 	/**
220 	 * Addressees of the message. If the array is empty the message is
221 	 * broadcasted to every connected node but the sender.
222 	 */
223 	uint[] addressees;
224 
225 	/**
226 	 * Bytes to be sent/broadcasted. It may be serialised data or a plugin-defined packet.
227 	 */
228 	ubyte[] payload;
229 
230 	mixin IO!(addressees, payload);
231 	
232 }
233 
234 /**
235  * Updates the server's display name.
236  */
237 @clientbound struct UpdateDisplayName {
238 
239 	enum ubyte ID = 14;
240 
241 	string displayName;
242 
243 	mixin IO!(displayName);
244 
245 }
246 
247 /**
248  * Updates the MOTD of one of the supported games.
249  */
250 @clientbound struct UpdateMOTD {
251 
252 	enum ubyte ID = 15;
253 
254 	ubyte type;
255 
256 	string motd;
257 
258 	mixin IO!(type, motd);
259 
260 }
261 
262 /**
263  * Updates the number of players on the server.
264  */
265 @clientbound struct UpdatePlayers {
266 
267 	enum ubyte ID = 16;
268 
269 	enum int UNLIMITED = -1;
270 
271 	/**
272 	 * Players currently online in the whole server (connected to a node).
273 	 */
274 	uint online;
275 
276 	/**
277 	 * Maximum number of players that can connect to server, which is the sum of
278 	 * the max players of every connected node.
279 	 */
280 	int max;
281 
282 	mixin IO!(online, max);
283 
284 }
285 
286 /**
287  * Updates the number of players that can be accepted by the node.
288  * If the given number is smaller than the players currently connected
289  * to the node no player should be kicked.
290  */
291 @serverbound struct UpdateMaxPlayers {
292 
293 	enum ubyte ID = 17;
294 
295 	enum uint UNLIMITED = 0;
296 
297 	/**
298 	 * Maximum number of players accepted by node.
299 	 */
300 	uint max;
301 
302 	mixin IO!(max);
303 
304 }
305 
306 /**
307  * Updates the accepted protocols for one of the supported games.
308  */
309 @clientbound struct UpdateSupportedProtocols {
310 
311 	enum ubyte ID = 18;
312 	
313 	ubyte game;
314 	
315 	uint[] protocols;
316 	
317 	mixin IO!(game, protocols);
318 	
319 }
320 
321 /**
322  * Updates the usage of the system's resources of the node.
323  */
324 @serverbound struct UpdateUsage {
325 
326 	enum ubyte ID = 19;
327 
328 	/**
329 	 * Kibibytes of RAM used by the node.
330 	 */
331 	uint ram;
332 
333 	/**
334 	 * Percentage of CPU used by the node. It may be higher than 100
335 	 * if the node has more than 1 CPU
336 	 */
337 	float cpu;
338 
339 	mixin IO!(ram, cpu);
340 
341 }
342 
343 /**
344  * Updates the language files. The content of this packet is usually
345  * readed from plugins' language files.
346  */
347 @serverbound struct UpdateLanguageFiles {
348 
349 	enum ubyte ID = 20;
350 
351 	string language;
352 
353 	string[string] messages;
354 
355 	mixin IO!(language, messages);
356 
357 }
358 
359 /**
360  * Adds a plugin that has been loaded at runtime.
361  */
362 @serverbound struct AddPlugin {
363 
364 	enum ubyte ID = 21;
365 
366 	/**
367 	 * Plugin's id given by the node. It must be unique.
368 	 */
369 	uint id;
370 
371 	string name;
372 
373 	string version_;
374 
375 	mixin IO!(id, name, version_);
376 
377 }
378 
379 /**
380  * Removes a plugin that has been unloaded at runtime.
381  */
382 @serverbound struct RemovePlugin {
383 
384 	enum ubyte ID = 22;
385 
386 	/**
387 	 * Plugin's id given in the NodeInfo packet or in the AddPlugin packet.
388 	 */
389 	uint id;
390 
391 	mixin IO!(id);
392 
393 }
394 
395 /**
396  * Notifies the hub that a new world has been created on the node.
397  */
398 @serverbound struct AddWorld {
399 	
400 	enum ubyte ID = 23;
401 
402 	/**
403 	 * Id of the world. Must be unique on the node.
404 	 */
405 	uint worldId;
406 
407 	/**
408 	 * World's group id. Similar worlds can be grouped together
409 	 * and removed with the RemoveWorldGroup packet.
410 	 * If the world is independent and has no group the group id must be the same
411 	 * as the world id.
412 	 */
413 	uint groupId;
414 
415 	/**
416 	 * Name of the world, it doesn't need to be unique.
417 	 */
418 	string name;
419 
420 	/**
421 	 * World's dimension in the MCPE format (0: overworld, 1: nether, 2: end).
422 	 */
423 	ubyte dimension;
424 
425 	/**
426 	 * Indicates whether the world is the node's default (the one where new players
427 	 * are spawned into if not handled by plugins).
428 	 * If the node does not support default worlds or it simply doesn't have one
429 	 * this field should be left to its default value (false).
430 	 * If the hub receives more than one default world it should consider the last
431 	 * received one as the default world.
432 	 */
433 	bool default_;
434 	
435 	mixin IO!(worldId, groupId, name, dimension);
436 	
437 }
438 
439 /**
440  * Notifies the hub that a world has been removed from the node.
441  */
442 @serverbound struct RemoveWorld {
443 	
444 	enum ubyte ID = 24;
445 
446 	/**
447 	 * Id of the world that has been removed, previosly added using the
448 	 * AddWorld packet.
449 	 */
450 	uint worldId;
451 	
452 	mixin IO!(worldId);
453 	
454 }
455 
456 /**
457  * Removes a group of worlds.
458  */
459 @serverbound struct RemoveWorldGroup {
460 
461 	enum ubyte ID = 25;
462 
463 	uint groupId;
464 
465 	mixin IO!(groupId);
466 
467 }
468 
469 /**
470  * Gives the node the credentials that will be used by a remote panel
471  * client to connect to a world.
472  */
473 @clientbound struct WebAdminCredentials {
474 
475 	enum ubyte ID = 26;
476 
477 	/**
478 	 * Id of the request, generated by the hub. To the request are associated the
479 	 * login credentials and the world to track.
480 	 */
481 	uint requestId;
482 
483 	/**
484 	 * Address used by the client to connect. May be a represantion of
485 	 * an ipv4 (`134.56.1.55`), ipv6 (`44:5:12::9`) or unix address (`~/tmp/rc`).
486 	 */
487 	string address;
488 
489 	/**
490 	 * Hash generated by the hub that will be used by the remote panel to
491 	 * perform authentication.
492 	 */
493 	ubyte[32] hash;
494 
495 	/**
496 	 * World group that the remote panel client will connect to.
497 	 */
498 	uint groupId;
499 
500 	mixin IO!(requestId, address, hash, groupId);
501 
502 }