3 Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 #ifndef _CLIENTIFACE_H_
20 #define _CLIENTIFACE_H_
22 #include "irr_v3d.h" // for irrlicht datatypes
24 #include "constants.h"
25 #include "serialization.h" // for SER_FMT_VER_INVALID
26 #include "jthread/jmutex.h"
27 #include "network/networkpacket.h"
35 class ServerEnvironment;
50 | depending of the incoming packet
51 +---------------------------------------
53 +-----------------------------+ +-----------------------------+
55 | TOSERVER_INIT_LEGACY |----- | TOSERVER_INIT | invalid playername,
56 +-----------------------------+ | +-----------------------------+ password (for _LEGACY),
57 | | | or denied by mod
58 | Auth ok -------------------+---------------------------------
60 +-----------------------------+ +-----------------------------+ |
62 | TOCLIENT_INIT_LEGACY | | TOCLIENT_HELLO | |
63 +-----------------------------+ +-----------------------------+ |
67 /-----------------\ /-----------------\ |
69 | AwaitingInit2 |<--------- | HelloSent | |
71 \-----------------/ | \-----------------/ |
73 +-----------------------------+ | *-----------------------------* Auth fails |
74 |IN: | | |Authentication, depending on |-----------------+
75 | TOSERVER_INIT2 | | | packet sent by client | |
76 +-----------------------------+ | *-----------------------------* |
78 | | | Authentication |
80 /-----------------\ | v |
81 | | | +-----------------------------+ |
82 | InitDone | | |OUT: | |
83 | | | | TOCLIENT_AUTH_ACCEPT | |
84 \-----------------/ | +-----------------------------+ |
86 +-----------------------------+ --------------------- |
88 | TOCLIENT_MOVEMENT | |
89 | TOCLIENT_ITEMDEF | |
90 | TOCLIENT_NODEDEF | |
91 | TOCLIENT_ANNOUNCE_MEDIA | |
92 | TOCLIENT_DETACHED_INVENTORY | |
93 | TOCLIENT_TIME_OF_DAY | |
94 +-----------------------------+ |
97 | ----------------------------- |
99 /-----------------\ v |
100 | | +-----------------------------+ |
101 | DefinitionsSent | |IN: | |
102 | | | TOSERVER_REQUEST_MEDIA | |
103 \-----------------/ | TOSERVER_RECEIVED_MEDIA | |
104 | +-----------------------------+ |
106 | ----------------------------- |
108 +-----------------------------+ --------------------------------+
110 | TOSERVER_CLIENT_READY | v |
111 +-----------------------------+ +-------------------------------+ |
113 v | TOCLIENT_ACCESS_DENIED_LEGAGY | |
114 +-----------------------------+ +-------------------------------+ |
116 | TOCLIENT_MOVE_PLAYER | v |
117 | TOCLIENT_PRIVILEGES | /-----------------\ |
118 | TOCLIENT_INVENTORY_FORMSPEC | | | |
119 | UpdateCrafting | | Denied | |
120 | TOCLIENT_INVENTORY | | | |
121 | TOCLIENT_HP (opt) | \-----------------/ |
122 | TOCLIENT_BREATH | |
123 | TOCLIENT_DEATHSCREEN | |
124 +-----------------------------+ |
127 /-----------------\ async mod action (ban, kick) |
128 | |---------------------------------------------------------------
130 | | |----------------------------------------------
131 | \-----------------/ timeout v
132 | | | +-----------------------------+
134 | | | | TOCLIENT_DISCONNECT |
135 | | | +-----------------------------+
138 | | +-----------------------------+ /-----------------\
140 | | | TOSERVER_DISCONNECT |------------------->| Disconnecting |
141 | | +-----------------------------+ | |
142 | | \-----------------/
143 | | any auth packet which was
144 | | allowed in TOCLIENT_AUTH_ACCEPT
146 | *-----------------------------* Auth +-------------------------------+
147 | |Authentication, depending on | succeeds |OUT: |
148 | | packet sent by client |---------->| TOCLIENT_ACCEPT_SUDO_MODE |
149 | *-----------------------------* +-------------------------------+
151 | | Auth fails /-----------------\
153 | +-------------------------------+ | SudoMode |
155 | | TOCLIENT_DENY_SUDO_MODE | \-----------------/
156 | +-------------------------------+ |
158 | | +-----------------------------+
159 | | sets password accordingly |IN: |
160 -------------------+-------------------------------| TOSERVER_FIRST_SRP |
161 +-----------------------------+
168 #define CI_ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
184 enum ClientStateEvent
191 CSE_SetDefinitionsSent,
199 Used for queueing and sorting block transfers in containers
201 Lower priority number means higher priority.
203 struct PrioritySortedBlockTransfer
205 PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
207 priority = a_priority;
211 bool operator < (const PrioritySortedBlockTransfer &other) const
213 return priority < other.priority;
223 // peer_id=0 means this client has no associated peer
224 // NOTE: If client is made allowed to exist while peer doesn't,
225 // this has to be set to 0 when there is no peer.
226 // Also, the client must be moved to some other container.
228 // The serialization version to use with the client
229 u8 serialization_version;
231 u16 net_proto_version;
233 /* Authentication information */
235 bool create_player_on_auth_success;
236 AuthMechanism chosen_mech;
238 u32 allowed_auth_mechs;
239 u32 allowed_sudo_mechs;
241 bool isSudoMechAllowed(AuthMechanism mech)
242 { return allowed_sudo_mechs & mech; }
243 bool isMechAllowed(AuthMechanism mech)
244 { return allowed_auth_mechs & mech; }
247 peer_id(PEER_ID_INEXISTENT),
248 serialization_version(SER_FMT_VER_INVALID),
249 net_proto_version(0),
250 create_player_on_auth_success(false),
251 chosen_mech(AUTH_MECHANISM_NONE),
253 m_time_from_building(9999),
254 m_pending_serialization_version(SER_FMT_VER_INVALID),
256 m_nearest_unsent_d(0),
257 m_nearest_unsent_reset_timer(0.0),
258 m_excess_gotblocks(0),
259 m_nothing_to_send_pause_timer(0.0),
264 m_full_version("unknown"),
265 m_deployed_compression(0),
266 m_connection_time(getTime(PRECISION_SECONDS))
274 Finds block that should be sent next to the client.
275 Environment should be locked when this is called.
276 dtime is used for resetting send radius at slow interval
278 void GetNextBlocks(ServerEnvironment *env, EmergeManager* emerge,
279 float dtime, std::vector<PrioritySortedBlockTransfer> &dest);
281 void GotBlock(v3s16 p);
283 void SentBlock(v3s16 p);
285 void SetBlockNotSent(v3s16 p);
286 void SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks);
289 * tell client about this block being modified right now.
290 * this information is required to requeue the block in case it's "on wire"
291 * while modification is processed by server
292 * @param p position of modified block
294 void ResendBlockIfOnWire(v3s16 p);
298 return m_blocks_sending.size();
301 // Increments timeouts and removes timed-out blocks from list
302 // NOTE: This doesn't fix the server-not-sending-block bug
303 // because it is related to emerging, not sending.
304 //void RunSendingTimeouts(float dtime, float timeout);
306 void PrintInfo(std::ostream &o)
308 o<<"RemoteClient "<<peer_id<<": "
309 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
310 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
311 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
312 <<", m_excess_gotblocks="<<m_excess_gotblocks
314 m_excess_gotblocks = 0;
317 // Time from last placing or removing blocks
318 float m_time_from_building;
321 List of active objects that the client knows of.
324 std::set<u16> m_known_objects;
326 ClientState getState()
329 std::string getName()
332 void setName(std::string name)
335 /* update internal client state */
336 void notifyEvent(ClientStateEvent event);
338 /* set expected serialization version */
339 void setPendingSerializationVersion(u8 version)
340 { m_pending_serialization_version = version; }
342 void setDeployedCompressionMode(u16 byteFlag)
343 { m_deployed_compression = byteFlag; }
345 void confirmSerializationVersion()
346 { serialization_version = m_pending_serialization_version; }
351 /* set version information */
352 void setVersionInfo(u8 major, u8 minor, u8 patch, std::string full) {
353 m_version_major = major;
354 m_version_minor = minor;
355 m_version_patch = patch;
356 m_full_version = full;
359 /* read version information */
360 u8 getMajor() { return m_version_major; }
361 u8 getMinor() { return m_version_minor; }
362 u8 getPatch() { return m_version_patch; }
363 std::string getVersion() { return m_full_version; }
365 // Version is stored in here after INIT before INIT2
366 u8 m_pending_serialization_version;
368 /* current state of client */
372 Blocks that have been sent to client.
373 - These don't have to be sent again.
374 - A block is cleared from here when client says it has
375 deleted it from it's memory
377 Key is position, value is dummy.
378 No MapBlock* is stored here because the blocks can get deleted.
380 std::set<v3s16> m_blocks_sent;
381 s16 m_nearest_unsent_d;
383 float m_nearest_unsent_reset_timer;
386 Blocks that are currently on the line.
387 This is used for throttling the sending of blocks.
388 - The size of this list is limited to some value
389 Block is added when it is sent with BLOCKDATA.
390 Block is removed when GOTBLOCKS is received.
391 Value is time from sending. (not used at the moment)
393 std::map<v3s16, float> m_blocks_sending;
396 Count of excess GotBlocks().
397 There is an excess amount because the client sometimes
398 gets a block so late that the server sends it again,
399 and the client then sends two GOTBLOCKs.
400 This is resetted by PrintInfo()
402 u32 m_excess_gotblocks;
404 // CPU usage optimization
405 float m_nothing_to_send_pause_timer;
408 name of player using this client
419 std::string m_full_version;
421 u16 m_deployed_compression;
424 time this client was created
426 const u32 m_connection_time;
429 class ClientInterface {
434 ClientInterface(con::Connection* con);
438 void step(float dtime);
440 /* get list of active client id's */
441 std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
443 /* get list of client player names */
444 std::vector<std::string> getPlayerNames();
446 /* send message to client */
447 void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
449 /* send to all clients */
450 void sendToAll(u16 channelnum, NetworkPacket* pkt, bool reliable);
452 /* delete a client */
453 void DeleteClient(u16 peer_id);
456 void CreateClient(u16 peer_id);
458 /* get a client by peer_id */
459 RemoteClient* getClientNoEx(u16 peer_id, ClientState state_min=CS_Active);
461 /* get client by peer_id (make sure you have list lock before!*/
462 RemoteClient* lockedGetClientNoEx(u16 peer_id, ClientState state_min=CS_Active);
464 /* get state of client by id*/
465 ClientState getClientState(u16 peer_id);
467 /* set client playername */
468 void setPlayerName(u16 peer_id,std::string name);
470 /* get protocol version of client */
471 u16 getProtocolVersion(u16 peer_id);
473 /* set client version */
474 void setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full);
476 /* event to update client state */
477 void event(u16 peer_id, ClientStateEvent event);
479 /* Set environment. Do not call this function if environment is already set */
480 void setEnv(ServerEnvironment *env)
482 assert(m_env == NULL); // pre-condition
486 static std::string state2Name(ClientState state);
489 //TODO find way to avoid this functions
491 { m_clients_mutex.Lock(); }
493 { m_clients_mutex.Unlock(); }
495 std::map<u16, RemoteClient*>& getClientList()
496 { return m_clients; }
499 /* update internal player list */
500 void UpdatePlayerList();
503 con::Connection* m_con;
504 JMutex m_clients_mutex;
505 // Connected clients (behind the con mutex)
506 std::map<u16, RemoteClient*> m_clients;
507 std::vector<std::string> m_clients_names; //for announcing masterserver
510 ServerEnvironment *m_env;
513 float m_print_info_timer;
515 static const char *statenames[];