]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.h
when pause menu is activated, move mouse cursor on top of the disconnect button,...
[dragonfireclient.git] / src / server.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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
20 /*
21 (c) 2010 Perttu Ahola <celeron55@gmail.com>
22 */
23
24 #ifndef SERVER_HEADER
25 #define SERVER_HEADER
26
27 #include "connection.h"
28 #include "environment.h"
29 #include "common_irrlicht.h"
30 #include <string>
31 #include "utility.h"
32 #include "porting.h"
33 #include "map.h"
34 #include "inventory.h"
35
36 /*
37         Some random functions
38 */
39 v3f findSpawnPos(ServerMap &map);
40
41 /*
42         A structure containing the data needed for queueing the fetching
43         of blocks.
44 */
45 struct QueuedBlockEmerge
46 {
47         v3s16 pos;
48         // key = peer_id, value = flags
49         core::map<u16, u8> peer_ids;
50 };
51
52 /*
53         This is a thread-safe class.
54 */
55 class BlockEmergeQueue
56 {
57 public:
58         BlockEmergeQueue()
59         {
60                 m_mutex.Init();
61         }
62
63         ~BlockEmergeQueue()
64         {
65                 JMutexAutoLock lock(m_mutex);
66
67                 core::list<QueuedBlockEmerge*>::Iterator i;
68                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
69                 {
70                         QueuedBlockEmerge *q = *i;
71                         delete q;
72                 }
73         }
74         
75         /*
76                 peer_id=0 adds with nobody to send to
77         */
78         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
79         {
80                 DSTACK(__FUNCTION_NAME);
81         
82                 JMutexAutoLock lock(m_mutex);
83
84                 if(peer_id != 0)
85                 {
86                         /*
87                                 Find if block is already in queue.
88                                 If it is, update the peer to it and quit.
89                         */
90                         core::list<QueuedBlockEmerge*>::Iterator i;
91                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
92                         {
93                                 QueuedBlockEmerge *q = *i;
94                                 if(q->pos == pos)
95                                 {
96                                         q->peer_ids[peer_id] = flags;
97                                         return;
98                                 }
99                         }
100                 }
101                 
102                 /*
103                         Add the block
104                 */
105                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
106                 q->pos = pos;
107                 if(peer_id != 0)
108                         q->peer_ids[peer_id] = flags;
109                 m_queue.push_back(q);
110         }
111
112         // Returned pointer must be deleted
113         // Returns NULL if queue is empty
114         QueuedBlockEmerge * pop()
115         {
116                 JMutexAutoLock lock(m_mutex);
117
118                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
119                 if(i == m_queue.end())
120                         return NULL;
121                 QueuedBlockEmerge *q = *i;
122                 m_queue.erase(i);
123                 return q;
124         }
125
126         u32 size()
127         {
128                 JMutexAutoLock lock(m_mutex);
129                 return m_queue.size();
130         }
131         
132         u32 peerItemCount(u16 peer_id)
133         {
134                 JMutexAutoLock lock(m_mutex);
135
136                 u32 count = 0;
137
138                 core::list<QueuedBlockEmerge*>::Iterator i;
139                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
140                 {
141                         QueuedBlockEmerge *q = *i;
142                         if(q->peer_ids.find(peer_id) != NULL)
143                                 count++;
144                 }
145
146                 return count;
147         }
148
149 private:
150         core::list<QueuedBlockEmerge*> m_queue;
151         JMutex m_mutex;
152 };
153
154 class Server;
155
156 class ServerThread : public SimpleThread
157 {
158         Server *m_server;
159
160 public:
161
162         ServerThread(Server *server):
163                 SimpleThread(),
164                 m_server(server)
165         {
166         }
167
168         void * Thread();
169 };
170
171 class EmergeThread : public SimpleThread
172 {
173         Server *m_server;
174
175 public:
176
177         EmergeThread(Server *server):
178                 SimpleThread(),
179                 m_server(server)
180         {
181         }
182
183         void * Thread();
184
185         void trigger()
186         {
187                 setRun(true);
188                 if(IsRunning() == false)
189                 {
190                         Start();
191                 }
192         }
193 };
194
195 struct PlayerInfo
196 {
197         u16 id;
198         char name[PLAYERNAME_SIZE];
199         v3f position;
200         Address address;
201         float avg_rtt;
202
203         PlayerInfo();
204         void PrintLine(std::ostream *s);
205 };
206
207 u32 PIChecksum(core::list<PlayerInfo> &l);
208
209 /*
210         Used for queueing and sorting block transfers in containers
211         
212         Lower priority number means higher priority.
213 */
214 struct PrioritySortedBlockTransfer
215 {
216         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
217         {
218                 priority = a_priority;
219                 pos = a_pos;
220                 peer_id = a_peer_id;
221         }
222         bool operator < (PrioritySortedBlockTransfer &other)
223         {
224                 return priority < other.priority;
225         }
226         float priority;
227         v3s16 pos;
228         u16 peer_id;
229 };
230
231 class RemoteClient
232 {
233 public:
234         // peer_id=0 means this client has no associated peer
235         // NOTE: If client is made allowed to exist while peer doesn't,
236         //       this has to be set to 0 when there is no peer.
237         //       Also, the client must be moved to some other container.
238         u16 peer_id;
239         // The serialization version to use with the client
240         u8 serialization_version;
241         // Version is stored in here after INIT before INIT2
242         u8 pending_serialization_version;
243
244         RemoteClient():
245                 m_time_from_building(9999),
246                 m_excess_gotblocks(0)
247         {
248                 peer_id = 0;
249                 serialization_version = SER_FMT_VER_INVALID;
250                 pending_serialization_version = SER_FMT_VER_INVALID;
251                 m_nearest_unsent_d = 0;
252                 m_nearest_unsent_reset_timer = 0.0;
253                 m_nothing_to_send_counter = 0;
254                 m_nothing_to_send_pause_timer = 0;
255         }
256         ~RemoteClient()
257         {
258         }
259         
260         /*
261                 Finds block that should be sent next to the client.
262                 Environment should be locked when this is called.
263                 dtime is used for resetting send radius at slow interval
264         */
265         void GetNextBlocks(Server *server, float dtime,
266                         core::array<PrioritySortedBlockTransfer> &dest);
267
268         /*
269                 Connection and environment should be locked when this is called.
270                 steps() objects of blocks not found in active_blocks, then
271                 adds those blocks to active_blocks
272         */
273         void SendObjectData(
274                         Server *server,
275                         float dtime,
276                         core::map<v3s16, bool> &stepped_blocks
277                 );
278
279         void GotBlock(v3s16 p);
280
281         void SentBlock(v3s16 p);
282
283         void SetBlockNotSent(v3s16 p);
284         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
285
286         s32 SendingCount()
287         {
288                 return m_blocks_sending.size();
289         }
290         
291         // Increments timeouts and removes timed-out blocks from list
292         // NOTE: This doesn't fix the server-not-sending-block bug
293         //       because it is related to emerging, not sending.
294         //void RunSendingTimeouts(float dtime, float timeout);
295
296         void PrintInfo(std::ostream &o)
297         {
298                 o<<"RemoteClient "<<peer_id<<": "
299                                 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
300                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
301                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
302                                 <<", m_excess_gotblocks="<<m_excess_gotblocks
303                                 <<std::endl;
304                 m_excess_gotblocks = 0;
305         }
306
307         // Time from last placing or removing blocks
308         float m_time_from_building;
309         
310         /*JMutex m_dig_mutex;
311         float m_dig_time_remaining;
312         // -1 = not digging
313         s16 m_dig_tool_item;
314         v3s16 m_dig_position;*/
315         
316         /*
317                 List of active objects that the client knows of.
318                 Value is dummy.
319         */
320         core::map<u16, bool> m_known_objects;
321
322 private:
323         /*
324                 Blocks that have been sent to client.
325                 - These don't have to be sent again.
326                 - A block is cleared from here when client says it has
327                   deleted it from it's memory
328                 
329                 Key is position, value is dummy.
330                 No MapBlock* is stored here because the blocks can get deleted.
331         */
332         core::map<v3s16, bool> m_blocks_sent;
333         s16 m_nearest_unsent_d;
334         v3s16 m_last_center;
335         float m_nearest_unsent_reset_timer;
336         
337         /*
338                 Blocks that are currently on the line.
339                 This is used for throttling the sending of blocks.
340                 - The size of this list is limited to some value
341                 Block is added when it is sent with BLOCKDATA.
342                 Block is removed when GOTBLOCKS is received.
343                 Value is time from sending. (not used at the moment)
344         */
345         core::map<v3s16, float> m_blocks_sending;
346
347         /*
348                 Count of excess GotBlocks().
349                 There is an excess amount because the client sometimes
350                 gets a block so late that the server sends it again,
351                 and the client then sends two GOTBLOCKs.
352                 This is resetted by PrintInfo()
353         */
354         u32 m_excess_gotblocks;
355         
356         // CPU usage optimization
357         u32 m_nothing_to_send_counter;
358         float m_nothing_to_send_pause_timer;
359 };
360
361 class Server : public con::PeerHandler, public MapEventReceiver,
362                 public InventoryManager
363 {
364 public:
365         /*
366                 NOTE: Every public method should be thread-safe
367         */
368
369         Server(
370                 std::string mapsavedir
371         );
372         ~Server();
373         void start(unsigned short port);
374         void stop();
375         // This is mainly a way to pass the time to the server.
376         // Actual processing is done in an another thread.
377         void step(float dtime);
378         // This is run by ServerThread and does the actual processing
379         void AsyncRunStep();
380         void Receive();
381         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
382
383         core::list<PlayerInfo> getPlayerInfo();
384
385         /*u32 getDayNightRatio()
386         {
387                 return time_to_daynight_ratio(m_time_of_day.get());
388         }*/
389         
390         // Environment must be locked when called
391         void setTimeOfDay(u32 time)
392         {
393                 m_env.setTimeOfDay(time);
394                 m_time_of_day_send_timer = 0;
395         }
396
397         bool getShutdownRequested()
398         {
399                 return m_shutdown_requested;
400         }
401         
402         /*
403                 Shall be called with the environment locked.
404                 This is accessed by the map, which is inside the environment,
405                 so it shouldn't be a problem.
406         */
407         void onMapEditEvent(MapEditEvent *event);
408
409         /*
410                 Shall be called with the environment and the connection locked.
411         */
412         Inventory* getInventory(InventoryContext *c, std::string id);
413         void inventoryModified(InventoryContext *c, std::string id);
414
415         // Connection must be locked when called
416         std::wstring getStatusString();
417
418         void requestShutdown(void)
419         {
420                 m_shutdown_requested = true;
421         }
422
423
424         // Envlock and conlock should be locked when calling this
425         void SendMovePlayer(Player *player);
426
427
428 private:
429
430         // con::PeerHandler implementation.
431         // These queue stuff to be processed by handlePeerChanges().
432         // As of now, these create and remove clients and players.
433         void peerAdded(con::Peer *peer);
434         void deletingPeer(con::Peer *peer, bool timeout);
435         
436         /*
437                 Static send methods
438         */
439         
440         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
441         static void SendAccessDenied(con::Connection &con, u16 peer_id);
442         
443         /*
444                 Non-static send methods
445         */
446
447         // Envlock and conlock should be locked when calling these
448         void SendObjectData(float dtime);
449         void SendPlayerInfos();
450         void SendInventory(u16 peer_id);
451         void SendChatMessage(u16 peer_id, const std::wstring &message);
452         void BroadcastChatMessage(const std::wstring &message);
453         void SendPlayerHP(Player *player);
454         /*
455                 Send a node removal/addition event to all clients except ignore_id.
456                 Additionally, if far_players!=NULL, players further away than
457                 far_d_nodes are ignored and their peer_ids are added to far_players
458         */
459         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
460                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
461         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
462                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
463         
464         // Environment and Connection must be locked when called
465         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
466         
467         // Sends blocks to clients
468         void SendBlocks(float dtime);
469
470         /*
471                 Something random
472         */
473         
474         void UpdateCrafting(u16 peer_id);
475         
476         // When called, connection mutex should be locked
477         RemoteClient* getClient(u16 peer_id);
478         
479         /*
480                 Get a player from memory or creates one.
481                 If player is already connected, return NULL
482                 The password is not checked here - it is only used to
483                 set the password if a new player is created.
484
485                 Call with env and con locked.
486         */
487         Player *emergePlayer(const char *name, const char *password, u16 peer_id);
488         
489         // Locks environment and connection by its own
490         struct PeerChange;
491         void handlePeerChange(PeerChange &c);
492         void handlePeerChanges();
493
494         /*
495                 Variables
496         */
497         
498         // Some timers
499         float m_liquid_transform_timer;
500         float m_print_info_timer;
501         float m_objectdata_timer;
502         float m_emergethread_trigger_timer;
503         float m_savemap_timer;
504         
505         // NOTE: If connection and environment are both to be locked,
506         // environment shall be locked first.
507
508         // Environment
509         ServerEnvironment m_env;
510         JMutex m_env_mutex;
511         
512         // Connection
513         con::Connection m_con;
514         JMutex m_con_mutex;
515         // Connected clients (behind the con mutex)
516         core::map<u16, RemoteClient*> m_clients;
517         
518         /*
519                 Threads
520         */
521         
522         // A buffer for time steps
523         // step() increments and AsyncRunStep() run by m_thread reads it.
524         float m_step_dtime;
525         JMutex m_step_dtime_mutex;
526
527         // The server mainly operates in this thread
528         ServerThread m_thread;
529         // This thread fetches and generates map
530         EmergeThread m_emergethread;
531         // Queue of block coordinates to be processed by the emerge thread
532         BlockEmergeQueue m_emerge_queue;
533         
534         /*
535                 Time related stuff
536         */
537
538         // 0-23999
539         //MutexedVariable<u32> m_time_of_day;
540         // Used to buffer dtime for adding to m_time_of_day
541         float m_time_counter;
542         // Timer for sending time of day over network
543         float m_time_of_day_send_timer;
544         // Uptime of server in seconds
545         MutexedVariable<double> m_uptime;
546         
547         /*
548                 Peer change queue.
549                 Queues stuff from peerAdded() and deletingPeer() to
550                 handlePeerChanges()
551         */
552         enum PeerChangeType
553         {
554                 PEER_ADDED,
555                 PEER_REMOVED
556         };
557         struct PeerChange
558         {
559                 PeerChangeType type;
560                 u16 peer_id;
561                 bool timeout;
562         };
563         Queue<PeerChange> m_peer_change_queue;
564
565         /*
566                 Random stuff
567         */
568
569         // Map directory
570         std::string m_mapsavedir;
571
572         bool m_shutdown_requested;
573         
574         /*
575                 Map edit event queue. Automatically receives all map edits.
576                 The constructor of this class registers us to receive them through
577                 onMapEditEvent
578
579                 NOTE: Should these be moved to actually be members of
580                 ServerEnvironment?
581         */
582
583         /*
584                 Queue of map edits from the environment for sending to the clients
585                 This is behind m_env_mutex
586         */
587         Queue<MapEditEvent*> m_unsent_map_edit_queue;
588         /*
589                 Set to true when the server itself is modifying the map and does
590                 all sending of information by itself.
591                 This is behind m_env_mutex
592         */
593         bool m_ignore_map_edit_events;
594         /*
595                 If set to !=0, the incoming MapEditEvents are modified to have
596                 this peed id as the disabled recipient
597                 This is behind m_env_mutex
598         */
599         u16 m_ignore_map_edit_events_peer_id;
600
601         friend class EmergeThread;
602         friend class RemoteClient;
603 };
604
605 /*
606         Runs a simple dedicated server loop.
607
608         Shuts down when run is set to false.
609 */
610 void dedicated_server_loop(Server &server, bool &run);
611
612 #endif
613