1 /*
2  * Copyright (c) 2017-2018 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 /**
16  * Copyright: 2017-2020 sel-project
17  * License: LGPL-3.0
18  * Authors: Kripth
19  * Source: $(HTTP github.com/sel-project/sel-server/sel/server/client.d, sel/server/client.d)
20  */
21 module sel.server.client;
22 
23 import core.atomic : atomicOp;
24 
25 import std.json : JSONValue;
26 import std.socket : Address;
27 import std.uuid : UUID;
28 
29 enum InputMode {
30 
31 	keyboard,
32 	touch,
33 	controller,
34 
35 }
36 
37 /**
38  * Represents a generic game client.
39  */
40 class Client {
41 
42 	// same as hncom's
43 	public enum ubyte BEDROCK = 0;
44 	public enum ubyte JAVA = 1;
45 
46 	protected enum VERSION_MINECRAFT = "Minecraft";
47 	protected enum VERSION_JAVA = "Minecraft: Java Edition";
48 	protected enum VERSION_EDU = "Minecraft: Education Edition";
49 
50 	private static shared uint _id;
51 
52 	public immutable uint id;
53 	public immutable ubyte type;
54 	public immutable uint protocol;
55 
56 	private Address _address;
57 	private string _username;
58 	private UUID _uuid;
59 	
60 	public immutable string gameName;
61 	public immutable string gameVersion;
62 	public immutable string game;
63 
64 	public string serverIp;
65 	public ushort serverPort;
66 
67 	public string skinName;
68 	public immutable(ubyte)[] skinData;
69 	public string skinGeometryName;
70 	public immutable(ubyte)[] skinGeometryData;
71 	public immutable(ubyte)[] skinCape;
72 	public InputMode inputMode = InputMode.keyboard;
73 	public string language;
74 
75 	public JSONValue gameData;
76 
77 	public void delegate(ubyte[]) handler;
78 
79 	public shared this(ubyte type, uint protocol, Address address, string username, UUID uuid, string gameName, string gameVersion) {
80 		this.id = atomicOp!"+="(_id, 1);
81 		this.type = type;
82 		this.protocol = protocol;
83 		this._address = cast(shared)address;
84 		this._username = username;
85 		this._uuid = cast(shared)uuid;
86 		this.gameName = gameName;
87 		this.gameVersion = gameVersion;
88 		this.game = gameName ~ " " ~ gameVersion;
89 		//TODO set handler
90 	}
91 
92 	/**
93 	 * Gets the client's address. May be either an ipv4 or ipv6, depending on
94 	 * the address where the server is binded to.
95 	 * Example:
96 	 * ---
97 	 * if(cast(InternetAddress)client.address) {
98 	 *    writeln(client, " is ipv6");
99 	 * }
100 	 * ---
101 	 */
102 	public shared pure nothrow @property @trusted @nogc Address address() {
103 		return cast()this._address;
104 	}
105 
106 	/**
107 	 * Gets the client's username.
108 	 */
109 	public shared pure nothrow @property @safe @nogc string username() {
110 		return this._username;
111 	}
112 
113 	/**
114 	 * Gets the client's UUID.
115 	 */
116 	public shared pure nothrow @property @safe @nogc UUID uuid() {
117 		return cast()this._uuid;
118 	}
119 
120 	public abstract shared synchronized void send(ubyte[] packet);
121 
122 	public abstract shared synchronized void directSend(ubyte[] payload);
123 
124 	public final shared void disconnect(string message, bool translation=false, string[] params=[]) {
125 		this.disconnectImpl(message, translation, params);
126 	}
127 
128 	public final shared void disconnect(string message, string[] params) {
129 		this.disconnect(message, true, params);
130 	}
131 
132 	protected abstract shared void disconnectImpl(string message, bool translation, string[] params);
133 
134 	public shared string toString() {
135 		return "Client(" ~ this.username ~ ", " ~ this.uuid.toString() ~ ")";
136 	}
137 
138 }