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