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/event/node/player.d, selery/event/node/player.d)
28  */
29 module selery.event.node.player;
30 
31 import std.conv : to;
32 
33 import sel.hncom.player : Add, Remove;
34 
35 import selery.about : Software;
36 import selery.event.event : Cancellable;
37 import selery.event.node.server : NodeServerEvent;
38 import selery.node.info : PlayerInfo, WorldInfo;
39 import selery.node.server : NodeServer;
40 import selery.player.player : Player;
41 import selery.world.world : World;
42 
43 class PlayerEvent : NodeServerEvent {
44 
45 	private const(PlayerInfo) _player;
46 
47 	public pure nothrow @safe @nogc this(shared NodeServer server, inout PlayerInfo player) {
48 		super(server);
49 		this._player = player;
50 	}
51 
52 	public final pure nothrow @property @safe @nogc const(PlayerInfo) player() {
53 		return this._player;
54 	}
55 
56 }
57 
58 /**
59  * Event called after the Player class for the now logged in player is created.
60  * It's the first event called after the creation of the player, before PlayerPreSpawnEvent.
61  * While this event is handled the client will see the "loading world" screen in its device,
62  * waiting for the chunks that will be sent after PlayerPreSpawnEvent (that is called by
63  * the world and every time a player changes world). That also means that this event
64  * will be called only once per player-session.
65  */
66 final class PlayerJoinEvent : PlayerEvent {
67 	
68 	enum Reason : ubyte {
69 		
70 		firstJoin = Add.FIRST_JOIN,
71 		transferred = Add.TRANSFERRED,
72 		forciblyTransferred = Add.FORCIBLY_TRANSFERRED
73 		
74 	}
75 
76 	private immutable ubyte _reason;
77 
78 	public shared(WorldInfo) world;
79 	
80 	public pure nothrow @safe @nogc this(shared NodeServer server, inout PlayerInfo player, ubyte reason) {
81 		super(server, player);
82 		this._reason = reason;
83 	}
84 
85 	public pure nothrow @property @safe @nogc ubyte reason() {
86 		return this._reason;
87 	}
88 	
89 }
90 
91 /**
92  * Event called when a player leaves the server, after PlayerDespawnEvent.
93  * It's the last event called for the player, after it lefts the server, and
94  * is only called once, like PlayerJoinEvent.
95  * Example:
96  * ---
97  * @effect playerleft(PlayerLeftEvent event) {
98  *    assert(!event.player.online);
99  * }
100  * ---
101  */
102 final class PlayerLeftEvent : PlayerEvent {
103 	
104 	enum Reason : ubyte {
105 		
106 		left = Remove.LEFT,
107 		timedOut = Remove.TIMED_OUT,
108 		kicked = Remove.KICKED,
109 		transferred = Remove.TRANSFERRED
110 		
111 	}
112 
113 	private immutable ubyte _reason;
114 	
115 	public pure nothrow @safe @nogc this(shared NodeServer server, inout PlayerInfo player, ubyte reason) {
116 		super(server, player);
117 		this._reason = reason;
118 	}
119 	
120 	public pure nothrow @property @safe @nogc ubyte reason() {
121 		return this._reason;
122 	}
123 	
124 }
125 
126 /**
127  * Event called when the player's language is updated (from the client or from
128  * a plugin). The old and the new languages will always be one in the server's accepted
129  * ones, as indicated in the hub's configuration file (accepted-languages field).
130  * Example:
131  * ---
132  * @event changeLanguage(PlayerLanguageUpdatedEvent event) {
133  *    log(event.player.name, " is changing language from ", event.currentLanguage, " to ", event.newLanguage);
134  * }
135  * ---
136  */
137 final class PlayerLanguageUpdatedEvent : PlayerEvent, Cancellable {
138 	
139 	mixin Cancellable.Implementation;
140 
141 	public immutable string oldLanguage;
142 	public immutable string newLanguage;
143 	
144 	public pure nothrow @safe @nogc this(shared NodeServer server, inout PlayerInfo player, string lang) {
145 		super(server, player);
146 		this.oldLanguage = player.language;
147 		this.newLanguage = lang;
148 	}
149 	
150 }
151 
152 /**
153  * Event called when the player's latency is updated from the hub.
154  * Example:
155  * ---
156  * @event updateLatency(PlayerLatencyUpdatedEvent event) {
157  *    event.player.title = event.latency.to!string ~ " ms";
158  * }
159  * ---
160  */
161 final class PlayerLatencyUpdatedEvent : PlayerEvent {
162 
163 	public pure nothrow @safe @nogc this(shared NodeServer server, inout PlayerInfo player) {
164 		super(server, player);
165 	}
166 
167 	/**
168 	 * Gets the player's latency.
169 	 * Example:
170 	 * ---
171 	 * assert(event.latency == event.player.latency);
172 	 * ---
173 	 */
174 	public pure nothrow @property @safe @nogc uint latency() {
175 		return this.player.latency;
176 	}
177 
178 }
179 
180 /**
181  * Event called when the player's packet loss is updated from the hub.
182  * The packet loss is only calculated for players that use a connectionless
183  * protocol like UDP (only Minecraft: Pocket Edition).
184  * Example:
185  * ---
186  * @event updatePacketLoss(PlayerPacketLossUpdatedEvent event) {
187  *    event.player.title = event.packetLoss.to!string ~ "%";
188  *    assert(event.player.pe);
189  * }
190  * ---
191  */
192 final class PlayerPacketLossUpdatedEvent : PlayerEvent {
193 
194 	public pure nothrow @safe @nogc this(shared NodeServer server, inout PlayerInfo player) {
195 		super(server, player);
196 	}
197 
198 	/**
199 	 * Gets the player's packet loss.
200 	 * Example:
201 	 * ---
202 	 * assert(event.packetLoss == event.player.packetLoss);
203 	 * ---
204 	 */
205 	public pure nothrow @property @safe @nogc float packetLoss() {
206 		return this.player.packetLoss;
207 	}
208 
209 }