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