]> git.lizzy.rs Git - dragonfireclient.git/blob - src/clientiface.h
54b2502650c540fab28db17c1dbac0b71b066dc0
[dragonfireclient.git] / src / clientiface.h
1 /*
2 Minetest
3 Copyright (C) 2010-2014 celeron55, Perttu Ahola <celeron55@gmail.com>
4
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.
9
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.
14
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.
18 */
19 #ifndef _CLIENTIFACE_H_
20 #define _CLIENTIFACE_H_
21
22 #include "irr_v3d.h"                   // for irrlicht datatypes
23
24 #include "constants.h"
25 #include "serialization.h"             // for SER_FMT_VER_INVALID
26 #include "jthread/jmutex.h"
27 #include "network/networkpacket.h"
28
29 #include <list>
30 #include <vector>
31 #include <map>
32 #include <set>
33
34 class MapBlock;
35 class ServerEnvironment;
36 class EmergeManager;
37
38 /*
39  * State Transitions
40
41       Start
42   (peer connect)
43         |
44         v
45       /-----------------\
46       |                 |
47       |    Created      |
48       |                 |
49       \-----------------/
50                |
51                |
52 +-----------------------------+            invalid playername, password
53 |IN:                          |                    or denied by mod
54 | TOSERVER_INIT               |------------------------------
55 +-----------------------------+                             |
56                |                                            |
57                | Auth ok                                    |
58                |                                            |
59 +-----------------------------+                             |
60 |OUT:                         |                             |
61 | TOCLIENT_INIT               |                             |
62 +-----------------------------+                             |
63                |                                            |
64                v                                            |
65       /-----------------\                                   |
66       |                 |                                   |
67       |    InitSent     |                                   |
68       |                 |                                   |
69       \-----------------/                                   +------------------
70                |                                            |                 |
71 +-----------------------------+             +-----------------------------+   |
72 |IN:                          |             |OUT:                         |   |
73 | TOSERVER_INIT2              |             | TOCLIENT_ACCESS_DENIED      |   |
74 +-----------------------------+             +-----------------------------+   |
75                |                                            |                 |
76                v                                            v                 |
77       /-----------------\                           /-----------------\       |
78       |                 |                           |                 |       |
79       |    InitDone     |                           |     Denied      |       |
80       |                 |                           |                 |       |
81       \-----------------/                           \-----------------/       |
82                |                                                              |
83 +-----------------------------+                                               |
84 |OUT:                         |                                               |
85 | TOCLIENT_MOVEMENT           |                                               |
86 | TOCLIENT_ITEMDEF            |                                               |
87 | TOCLIENT_NODEDEF            |                                               |
88 | TOCLIENT_ANNOUNCE_MEDIA     |                                               |
89 | TOCLIENT_DETACHED_INVENTORY |                                               |
90 | TOCLIENT_TIME_OF_DAY        |                                               |
91 +-----------------------------+                                               |
92                |                                                              |
93                |                                                              |
94                |      -----------------------------------                     |
95                v      |                                 |                     |
96       /-----------------\                               v                     |
97       |                 |                   +-----------------------------+   |
98       | DefinitionsSent |                   |IN:                          |   |
99       |                 |                   | TOSERVER_REQUEST_MEDIA      |   |
100       \-----------------/                   | TOSERVER_RECEIVED_MEDIA     |   |
101                |                            +-----------------------------+   |
102                |      ^                                 |                     |
103                |      -----------------------------------                     |
104                |                                                              |
105 +-----------------------------+                                               |
106 |IN:                          |                                               |
107 | TOSERVER_CLIENT_READY       |                                               |
108 +-----------------------------+                                               |
109                |                                                    async     |
110                v                                                  mod action  |
111 +-----------------------------+                                   (ban,kick)  |
112 |OUT:                         |                                               |
113 | TOCLIENT_MOVE_PLAYER        |                                               |
114 | TOCLIENT_PRIVILEGES         |                                               |
115 | TOCLIENT_INVENTORY_FORMSPEC |                                               |
116 | UpdateCrafting              |                                               |
117 | TOCLIENT_INVENTORY          |                                               |
118 | TOCLIENT_HP (opt)           |                                               |
119 | TOCLIENT_BREATH             |                                               |
120 | TOCLIENT_DEATHSCREEN        |                                               |
121 +-----------------------------+                                               |
122               |                                                               |
123               v                                                               |
124       /-----------------\                                                     |
125       |                 |------------------------------------------------------
126       |     Active      |
127       |                 |----------------------------------
128       \-----------------/      timeout                    |
129                |                            +-----------------------------+
130                |                            |OUT:                         |
131                |                            | TOCLIENT_DISCONNECT         |
132                |                            +-----------------------------+
133                |                                          |
134                |                                          v
135 +-----------------------------+                    /-----------------\
136 |IN:                          |                    |                 |
137 | TOSERVER_DISCONNECT         |------------------->|  Disconnecting  |
138 +-----------------------------+                    |                 |
139                                                    \-----------------/
140 */
141 namespace con {
142         class Connection;
143 }
144
145 #define CI_ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
146
147 enum ClientState
148 {
149         CS_Invalid,
150         CS_Disconnecting,
151         CS_Denied,
152         CS_Created,
153         CS_InitSent,
154         CS_InitDone,
155         CS_DefinitionsSent,
156         CS_Active
157 };
158
159 enum ClientStateEvent
160 {
161         CSE_Init,
162         CSE_GotInit2,
163         CSE_SetDenied,
164         CSE_SetDefinitionsSent,
165         CSE_SetClientReady,
166         CSE_Disconnect
167 };
168
169 /*
170         Used for queueing and sorting block transfers in containers
171
172         Lower priority number means higher priority.
173 */
174 struct PrioritySortedBlockTransfer
175 {
176         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
177         {
178                 priority = a_priority;
179                 pos = a_pos;
180                 peer_id = a_peer_id;
181         }
182         bool operator < (const PrioritySortedBlockTransfer &other) const
183         {
184                 return priority < other.priority;
185         }
186         float priority;
187         v3s16 pos;
188         u16 peer_id;
189 };
190
191 class RemoteClient
192 {
193 public:
194         // peer_id=0 means this client has no associated peer
195         // NOTE: If client is made allowed to exist while peer doesn't,
196         //       this has to be set to 0 when there is no peer.
197         //       Also, the client must be moved to some other container.
198         u16 peer_id;
199         // The serialization version to use with the client
200         u8 serialization_version;
201         //
202         u16 net_proto_version;
203
204         RemoteClient():
205                 peer_id(PEER_ID_INEXISTENT),
206                 serialization_version(SER_FMT_VER_INVALID),
207                 net_proto_version(0),
208                 m_time_from_building(9999),
209                 m_pending_serialization_version(SER_FMT_VER_INVALID),
210                 m_state(CS_Created),
211                 m_nearest_unsent_d(0),
212                 m_nearest_unsent_reset_timer(0.0),
213                 m_excess_gotblocks(0),
214                 m_nothing_to_send_pause_timer(0.0),
215                 m_name(""),
216                 m_version_major(0),
217                 m_version_minor(0),
218                 m_version_patch(0),
219                 m_full_version("unknown"),
220                 m_supported_compressions(0),
221                 m_connection_time(getTime(PRECISION_SECONDS))
222         {
223         }
224         ~RemoteClient()
225         {
226         }
227
228         /*
229                 Finds block that should be sent next to the client.
230                 Environment should be locked when this is called.
231                 dtime is used for resetting send radius at slow interval
232         */
233         void GetNextBlocks(ServerEnvironment *env, EmergeManager* emerge,
234                         float dtime, std::vector<PrioritySortedBlockTransfer> &dest);
235
236         void GotBlock(v3s16 p);
237
238         void SentBlock(v3s16 p);
239
240         void SetBlockNotSent(v3s16 p);
241         void SetBlocksNotSent(std::map<v3s16, MapBlock*> &blocks);
242
243         /**
244          * tell client about this block being modified right now.
245          * this information is required to requeue the block in case it's "on wire"
246          * while modification is processed by server
247          * @param p position of modified block
248          */
249         void ResendBlockIfOnWire(v3s16 p);
250
251         s32 SendingCount()
252         {
253                 return m_blocks_sending.size();
254         }
255
256         // Increments timeouts and removes timed-out blocks from list
257         // NOTE: This doesn't fix the server-not-sending-block bug
258         //       because it is related to emerging, not sending.
259         //void RunSendingTimeouts(float dtime, float timeout);
260
261         void PrintInfo(std::ostream &o)
262         {
263                 o<<"RemoteClient "<<peer_id<<": "
264                                 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
265                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
266                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
267                                 <<", m_excess_gotblocks="<<m_excess_gotblocks
268                                 <<std::endl;
269                 m_excess_gotblocks = 0;
270         }
271
272         // Time from last placing or removing blocks
273         float m_time_from_building;
274
275         /*
276                 List of active objects that the client knows of.
277                 Value is dummy.
278         */
279         std::set<u16> m_known_objects;
280
281         ClientState getState()
282                 { return m_state; }
283
284         std::string getName()
285                 { return m_name; }
286
287         void setName(std::string name)
288                 { m_name = name; }
289
290         /* update internal client state */
291         void notifyEvent(ClientStateEvent event);
292
293         /* set expected serialization version */
294         void setPendingSerializationVersion(u8 version)
295                 { m_pending_serialization_version = version; }
296
297         void setSupportedCompressionModes(u8 byteFlag)
298                 { m_supported_compressions = byteFlag; }
299
300         void confirmSerializationVersion()
301                 { serialization_version = m_pending_serialization_version; }
302
303         /* get uptime */
304         u32 uptime();
305
306
307         /* set version information */
308         void setVersionInfo(u8 major, u8 minor, u8 patch, std::string full) {
309                 m_version_major = major;
310                 m_version_minor = minor;
311                 m_version_patch = patch;
312                 m_full_version = full;
313         }
314
315         /* read version information */
316         u8 getMajor() { return m_version_major; }
317         u8 getMinor() { return m_version_minor; }
318         u8 getPatch() { return m_version_patch; }
319         std::string getVersion() { return m_full_version; }
320 private:
321         // Version is stored in here after INIT before INIT2
322         u8 m_pending_serialization_version;
323
324         /* current state of client */
325         ClientState m_state;
326
327         /*
328                 Blocks that have been sent to client.
329                 - These don't have to be sent again.
330                 - A block is cleared from here when client says it has
331                   deleted it from it's memory
332
333                 Key is position, value is dummy.
334                 No MapBlock* is stored here because the blocks can get deleted.
335         */
336         std::set<v3s16> m_blocks_sent;
337         s16 m_nearest_unsent_d;
338         v3s16 m_last_center;
339         float m_nearest_unsent_reset_timer;
340
341         /*
342                 Blocks that are currently on the line.
343                 This is used for throttling the sending of blocks.
344                 - The size of this list is limited to some value
345                 Block is added when it is sent with BLOCKDATA.
346                 Block is removed when GOTBLOCKS is received.
347                 Value is time from sending. (not used at the moment)
348         */
349         std::map<v3s16, float> m_blocks_sending;
350
351         /*
352                 Count of excess GotBlocks().
353                 There is an excess amount because the client sometimes
354                 gets a block so late that the server sends it again,
355                 and the client then sends two GOTBLOCKs.
356                 This is resetted by PrintInfo()
357         */
358         u32 m_excess_gotblocks;
359
360         // CPU usage optimization
361         float m_nothing_to_send_pause_timer;
362
363         /*
364                 name of player using this client
365         */
366         std::string m_name;
367
368         /*
369                 client information
370          */
371         u8 m_version_major;
372         u8 m_version_minor;
373         u8 m_version_patch;
374
375         std::string m_full_version;
376
377         u8 m_supported_compressions;
378
379         /*
380                 time this client was created
381          */
382         const u32 m_connection_time;
383 };
384
385 class ClientInterface {
386 public:
387
388         friend class Server;
389
390         ClientInterface(con::Connection* con);
391         ~ClientInterface();
392
393         /* run sync step */
394         void step(float dtime);
395
396         /* get list of active client id's */
397         std::vector<u16> getClientIDs(ClientState min_state=CS_Active);
398
399         /* get list of client player names */
400         std::vector<std::string> getPlayerNames();
401
402         /* send message to client */
403         void send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable);
404
405         /* send to all clients */
406         void sendToAll(u16 channelnum, NetworkPacket* pkt, bool reliable);
407
408         /* delete a client */
409         void DeleteClient(u16 peer_id);
410
411         /* create client */
412         void CreateClient(u16 peer_id);
413
414         /* get a client by peer_id */
415         RemoteClient* getClientNoEx(u16 peer_id,  ClientState state_min=CS_Active);
416
417         /* get client by peer_id (make sure you have list lock before!*/
418         RemoteClient* lockedGetClientNoEx(u16 peer_id,  ClientState state_min=CS_Active);
419
420         /* get state of client by id*/
421         ClientState getClientState(u16 peer_id);
422
423         /* set client playername */
424         void setPlayerName(u16 peer_id,std::string name);
425
426         /* get protocol version of client */
427         u16 getProtocolVersion(u16 peer_id);
428
429         /* set client version */
430         void setClientVersion(u16 peer_id, u8 major, u8 minor, u8 patch, std::string full);
431
432         /* event to update client state */
433         void event(u16 peer_id, ClientStateEvent event);
434
435         /* Set environment. Do not call this function if environment is already set */
436         void setEnv(ServerEnvironment *env)
437         {
438                 assert(m_env == NULL); // pre-condition
439                 m_env = env;
440         }
441
442         static std::string state2Name(ClientState state);
443
444 protected:
445         //TODO find way to avoid this functions
446         void Lock()
447                 { m_clients_mutex.Lock(); }
448         void Unlock()
449                 { m_clients_mutex.Unlock(); }
450
451         std::map<u16, RemoteClient*>& getClientList()
452                 { return m_clients; }
453
454 private:
455         /* update internal player list */
456         void UpdatePlayerList();
457
458         // Connection
459         con::Connection* m_con;
460         JMutex m_clients_mutex;
461         // Connected clients (behind the con mutex)
462         std::map<u16, RemoteClient*> m_clients;
463         std::vector<std::string> m_clients_names; //for announcing masterserver
464
465         // Environment
466         ServerEnvironment *m_env;
467         JMutex m_env_mutex;
468
469         float m_print_info_timer;
470
471         static const char *statenames[];
472 };
473
474 #endif