]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.h
1e7e41c9673a4a942d62a584b5eae3c954d4c987
[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 #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 "porting.h"
28 #include "map.h"
29 #include "inventory.h"
30 #include "auth.h"
31 #include "ban.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         //
239         u16 net_proto_version;
240         // Version is stored in here after INIT before INIT2
241         u8 pending_serialization_version;
242
243         RemoteClient():
244                 m_time_from_building(9999),
245                 m_excess_gotblocks(0)
246         {
247                 peer_id = 0;
248                 serialization_version = SER_FMT_VER_INVALID;
249                 net_proto_version = 0;
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                 std::string configpath
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         // Saves g_settings to configpath given at initialization
452         void saveConfig();
453
454         void setIpBanned(const std::string &ip, const std::string &name)
455         {
456                 m_banmanager.add(ip, name);
457                 return;
458         }
459
460         void unsetIpBanned(const std::string &ip_or_name)
461         {
462                 m_banmanager.remove(ip_or_name);
463                 return;
464         }
465
466         std::string getBanDescription(const std::string &ip_or_name)
467         {
468                 return m_banmanager.getBanDescription(ip_or_name);
469         }
470
471         con::Peer* getPeerNoEx(u16 peer_id)
472         {
473                 return m_con.GetPeerNoEx(peer_id);
474         }
475         
476         // Envlock and conlock should be locked when calling this
477         void notifyPlayer(const char *name, const std::wstring msg);
478
479 private:
480
481         // con::PeerHandler implementation.
482         // These queue stuff to be processed by handlePeerChanges().
483         // As of now, these create and remove clients and players.
484         void peerAdded(con::Peer *peer);
485         void deletingPeer(con::Peer *peer, bool timeout);
486         
487         /*
488                 Static send methods
489         */
490         
491         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
492         static void SendAccessDenied(con::Connection &con, u16 peer_id,
493                         const std::wstring &reason);
494         static void SendDeathscreen(con::Connection &con, u16 peer_id,
495                         bool set_camera_point_target, v3f camera_point_target);
496         
497         /*
498                 Non-static send methods
499         */
500
501         // Envlock and conlock should be locked when calling these
502         void SendObjectData(float dtime);
503         void SendPlayerInfos();
504         void SendInventory(u16 peer_id);
505         // send wielded item info about player to all
506         void SendWieldedItem(const Player *player);
507         // send wielded item info about all players to all players
508         void SendPlayerItems();
509         void SendChatMessage(u16 peer_id, const std::wstring &message);
510         void BroadcastChatMessage(const std::wstring &message);
511         void SendPlayerHP(Player *player);
512         /*
513                 Send a node removal/addition event to all clients except ignore_id.
514                 Additionally, if far_players!=NULL, players further away than
515                 far_d_nodes are ignored and their peer_ids are added to far_players
516         */
517         // Envlock and conlock should be locked when calling these
518         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
519                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
520         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
521                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
522         void setBlockNotSent(v3s16 p);
523         
524         // Environment and Connection must be locked when called
525         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
526         
527         // Sends blocks to clients (locks env and con on its own)
528         void SendBlocks(float dtime);
529
530         /*
531                 Something random
532         */
533         
534         void HandlePlayerHP(Player *player, s16 damage);
535         void RespawnPlayer(Player *player);
536         
537         void UpdateCrafting(u16 peer_id);
538         
539         // When called, connection mutex should be locked
540         RemoteClient* getClient(u16 peer_id);
541         
542         // When called, environment mutex should be locked
543         std::string getPlayerName(u16 peer_id)
544         {
545                 Player *player = m_env.getPlayer(peer_id);
546                 if(player == NULL)
547                         return "[id="+itos(peer_id);
548                 return player->getName();
549         }
550
551         /*
552                 Get a player from memory or creates one.
553                 If player is already connected, return NULL
554                 The password is not checked here - it is only used to
555                 set the password if a new player is created.
556
557                 Call with env and con locked.
558         */
559         Player *emergePlayer(const char *name, const char *password, u16 peer_id);
560         
561         // Locks environment and connection by its own
562         struct PeerChange;
563         void handlePeerChange(PeerChange &c);
564         void handlePeerChanges();
565
566         u64 getPlayerPrivs(Player *player);
567
568         /*
569                 Variables
570         */
571         
572         // Some timers
573         float m_liquid_transform_timer;
574         float m_print_info_timer;
575         float m_objectdata_timer;
576         float m_emergethread_trigger_timer;
577         float m_savemap_timer;
578         IntervalLimiter m_map_timer_and_unload_interval;
579         
580         // NOTE: If connection and environment are both to be locked,
581         // environment shall be locked first.
582
583         // Environment
584         ServerEnvironment m_env;
585         JMutex m_env_mutex;
586         
587         // Connection
588         con::Connection m_con;
589         JMutex m_con_mutex;
590         // Connected clients (behind the con mutex)
591         core::map<u16, RemoteClient*> m_clients;
592
593         // User authentication
594         AuthManager m_authmanager;
595
596         // Bann checking
597         BanManager m_banmanager;
598         
599         /*
600                 Threads
601         */
602         
603         // A buffer for time steps
604         // step() increments and AsyncRunStep() run by m_thread reads it.
605         float m_step_dtime;
606         JMutex m_step_dtime_mutex;
607
608         // The server mainly operates in this thread
609         ServerThread m_thread;
610         // This thread fetches and generates map
611         EmergeThread m_emergethread;
612         // Queue of block coordinates to be processed by the emerge thread
613         BlockEmergeQueue m_emerge_queue;
614         
615         /*
616                 Time related stuff
617         */
618
619         // 0-23999
620         //MutexedVariable<u32> m_time_of_day;
621         // Used to buffer dtime for adding to m_time_of_day
622         float m_time_counter;
623         // Timer for sending time of day over network
624         float m_time_of_day_send_timer;
625         // Uptime of server in seconds
626         MutexedVariable<double> m_uptime;
627         
628         /*
629                 Peer change queue.
630                 Queues stuff from peerAdded() and deletingPeer() to
631                 handlePeerChanges()
632         */
633         enum PeerChangeType
634         {
635                 PEER_ADDED,
636                 PEER_REMOVED
637         };
638         struct PeerChange
639         {
640                 PeerChangeType type;
641                 u16 peer_id;
642                 bool timeout;
643         };
644         Queue<PeerChange> m_peer_change_queue;
645
646         /*
647                 Random stuff
648         */
649
650         // Map directory
651         std::string m_mapsavedir;
652
653         // Configuration path ("" = no configuration file)
654         std::string m_configpath;
655
656         bool m_shutdown_requested;
657         
658         /*
659                 Map edit event queue. Automatically receives all map edits.
660                 The constructor of this class registers us to receive them through
661                 onMapEditEvent
662
663                 NOTE: Should these be moved to actually be members of
664                 ServerEnvironment?
665         */
666
667         /*
668                 Queue of map edits from the environment for sending to the clients
669                 This is behind m_env_mutex
670         */
671         Queue<MapEditEvent*> m_unsent_map_edit_queue;
672         /*
673                 Set to true when the server itself is modifying the map and does
674                 all sending of information by itself.
675                 This is behind m_env_mutex
676         */
677         bool m_ignore_map_edit_events;
678         /*
679                 If set to !=0, the incoming MapEditEvents are modified to have
680                 this peed id as the disabled recipient
681                 This is behind m_env_mutex
682         */
683         u16 m_ignore_map_edit_events_peer_id;
684
685         Profiler *m_profiler;
686
687         friend class EmergeThread;
688         friend class RemoteClient;
689 };
690
691 /*
692         Runs a simple dedicated server loop.
693
694         Shuts down when run is set to false.
695 */
696 void dedicated_server_loop(Server &server, bool &run);
697
698 #endif
699