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: 2017-2018 sel-project
25  * License: MIT
26  * Authors: Kripth
27  * Source: $(HTTP github.com/sel-project/selery/source/selery/node/info.d, selery/node/info.d)
28  */
29 module selery.node.info;
30 
31 import std.concurrency : Tid;
32 import std.conv : to;
33 import std.json : JSONValue, JSON_TYPE;
34 import std.socket : Address;
35 import std.string : toLower, startsWith;
36 import std.uuid : UUID;
37 
38 import sel.hncom.about : __BEDROCK__, __JAVA__;
39 import sel.hncom.player : Add;
40 
41 import selery.about;
42 import selery.entity.human : Skin;
43 import selery.player.player : InputMode, DeviceOS, PermissionLevel;
44 
45 /**
46  * Generic informations about a player in the server.
47  */
48 final class PlayerInfo {
49 
50 	/**
51 	 * Player's id assigned by the hub and unique for the player's session.
52 	 */
53 	public immutable uint hubId;
54 
55 	/**
56 	 * Indicates whether the player is still connected to the server.
57 	 */
58 	public bool online = true;
59 
60 	public ubyte type;
61 	public uint protocol;
62 	public string version_;
63 
64 	public string name, lname, displayName;
65 
66 	public UUID uuid;
67 
68 	public Address address;
69 	public string ip;
70 	public ushort port;
71 
72 	public Add.ServerAddress usedAddress;
73 
74 	public string language;
75 
76 	public Skin skin;
77 
78 	public PermissionLevel permissionLevel;
79 
80 	public uint latency;
81 	public float packetLoss;
82 
83 	public string gameName;
84 	public string gameVersion;
85 	public string game;
86 
87 	public bool edu = false;
88 
89 	public InputMode inputMode;
90 	public DeviceOS deviceOs = DeviceOS.unknown;
91 	public string deviceModel;
92 	public long xuid;
93 
94 	public shared WorldInfo world; // should never be null after initialised by the first Player construction
95 
96 	public this(Add add) {
97 		this.hubId = add.hubId;
98 		this.type = add.type;
99 		this.protocol = add.protocol;
100 		this.name = add.username;
101 		this.lname = add.username.toLower();
102 		this.displayName = add.displayName;
103 		this.uuid = add.uuid;
104 		this.permissionLevel = cast(PermissionLevel)add.permissionLevel;
105 		this.address = add.clientAddress;
106 		this.ip = add.clientAddress.toAddrString();
107 		this.port = to!ushort(add.clientAddress.toPortString());
108 		this.usedAddress = add.serverAddress;
109 		this.language = add.language;
110 		this.inputMode = cast(InputMode)add.inputMode;
111 		this.gameName = add.gameName;
112 		this.gameVersion = add.gameVersion;
113 		if(add.gameData.type == JSON_TYPE.OBJECT) {
114 			if(type == __BEDROCK__) {
115 				this.edu = "edu" in add.gameData && add.gameData["edu"].type == JSON_TYPE.TRUE;
116 				auto deviceOs = "DeviceOS" in add.gameData;
117 				if(deviceOs && deviceOs.type == JSON_TYPE.INTEGER && deviceOs.integer <= 9) this.deviceOs = cast(DeviceOS)deviceOs.integer;
118 				auto deviceModel = "DeviceModel" in add.gameData;
119 				if(deviceModel && deviceModel.type == JSON_TYPE.STRING) this.deviceModel = deviceModel.str;
120 			}
121 		}
122 		this.game = this.gameName ~ " " ~ this.gameVersion;
123 	}
124 
125 }
126 
127 /**
128  * Generic information about a world.
129  */
130 final class WorldInfo {
131 
132 	/**
133 	 * World's id, may be given by the server (for main worlds) or by the
134 	 * parent world (children worlds).
135 	 */
136 	public immutable uint id;
137 
138 	/**
139 	 * World's name, which is given by the user who creates the world.
140 	 * It may not be unique on the node. Children worlds have the same id
141 	 * as their parent's.
142 	 */
143 	public immutable string name;
144 
145 	/**
146 	 * Thread where the world exists.
147 	 * Children worlds inherit the tid from their parents.
148 	 */
149 	public Tid tid;
150 
151 	/**
152 	 * Number of entities (players included), players and chunks
153 	 * in the world (children's not included) for statistic purposes.
154 	 */
155 	public size_t entities, players, chunks;
156 
157 	public shared(WorldInfo) parent = null;
158 	public shared(WorldInfo)[uint] children;
159 
160 	public this(uint id, string name) {
161 		this.id = id;
162 		this.name = name;
163 	}
164 
165 }