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