]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.h
Remove stuff made obsolete by making players more ActiveObject-like and raise protoco...
[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 #include "gamedef.h"
33 #include "serialization.h" // For SER_FMT_VER_INVALID
34 struct LuaState;
35 typedef struct lua_State lua_State;
36 class IWritableToolDefManager;
37 class IWritableNodeDefManager;
38 class IWritableCraftDefManager;
39 class IWritableCraftItemDefManager;
40
41 /*
42         Some random functions
43 */
44 v3f findSpawnPos(ServerMap &map);
45
46 /*
47         A structure containing the data needed for queueing the fetching
48         of blocks.
49 */
50 struct QueuedBlockEmerge
51 {
52         v3s16 pos;
53         // key = peer_id, value = flags
54         core::map<u16, u8> peer_ids;
55 };
56
57 /*
58         This is a thread-safe class.
59 */
60 class BlockEmergeQueue
61 {
62 public:
63         BlockEmergeQueue()
64         {
65                 m_mutex.Init();
66         }
67
68         ~BlockEmergeQueue()
69         {
70                 JMutexAutoLock lock(m_mutex);
71
72                 core::list<QueuedBlockEmerge*>::Iterator i;
73                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
74                 {
75                         QueuedBlockEmerge *q = *i;
76                         delete q;
77                 }
78         }
79         
80         /*
81                 peer_id=0 adds with nobody to send to
82         */
83         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
84         {
85                 DSTACK(__FUNCTION_NAME);
86         
87                 JMutexAutoLock lock(m_mutex);
88
89                 if(peer_id != 0)
90                 {
91                         /*
92                                 Find if block is already in queue.
93                                 If it is, update the peer to it and quit.
94                         */
95                         core::list<QueuedBlockEmerge*>::Iterator i;
96                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
97                         {
98                                 QueuedBlockEmerge *q = *i;
99                                 if(q->pos == pos)
100                                 {
101                                         q->peer_ids[peer_id] = flags;
102                                         return;
103                                 }
104                         }
105                 }
106                 
107                 /*
108                         Add the block
109                 */
110                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
111                 q->pos = pos;
112                 if(peer_id != 0)
113                         q->peer_ids[peer_id] = flags;
114                 m_queue.push_back(q);
115         }
116
117         // Returned pointer must be deleted
118         // Returns NULL if queue is empty
119         QueuedBlockEmerge * pop()
120         {
121                 JMutexAutoLock lock(m_mutex);
122
123                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
124                 if(i == m_queue.end())
125                         return NULL;
126                 QueuedBlockEmerge *q = *i;
127                 m_queue.erase(i);
128                 return q;
129         }
130
131         u32 size()
132         {
133                 JMutexAutoLock lock(m_mutex);
134                 return m_queue.size();
135         }
136         
137         u32 peerItemCount(u16 peer_id)
138         {
139                 JMutexAutoLock lock(m_mutex);
140
141                 u32 count = 0;
142
143                 core::list<QueuedBlockEmerge*>::Iterator i;
144                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
145                 {
146                         QueuedBlockEmerge *q = *i;
147                         if(q->peer_ids.find(peer_id) != NULL)
148                                 count++;
149                 }
150
151                 return count;
152         }
153
154 private:
155         core::list<QueuedBlockEmerge*> m_queue;
156         JMutex m_mutex;
157 };
158
159 class Server;
160
161 class ServerThread : public SimpleThread
162 {
163         Server *m_server;
164
165 public:
166
167         ServerThread(Server *server):
168                 SimpleThread(),
169                 m_server(server)
170         {
171         }
172
173         void * Thread();
174 };
175
176 class EmergeThread : public SimpleThread
177 {
178         Server *m_server;
179
180 public:
181
182         EmergeThread(Server *server):
183                 SimpleThread(),
184                 m_server(server)
185         {
186         }
187
188         void * Thread();
189
190         void trigger()
191         {
192                 setRun(true);
193                 if(IsRunning() == false)
194                 {
195                         Start();
196                 }
197         }
198 };
199
200 struct PlayerInfo
201 {
202         u16 id;
203         char name[PLAYERNAME_SIZE];
204         v3f position;
205         Address address;
206         float avg_rtt;
207
208         PlayerInfo();
209         void PrintLine(std::ostream *s);
210 };
211
212 u32 PIChecksum(core::list<PlayerInfo> &l);
213
214 /*
215         Used for queueing and sorting block transfers in containers
216         
217         Lower priority number means higher priority.
218 */
219 struct PrioritySortedBlockTransfer
220 {
221         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
222         {
223                 priority = a_priority;
224                 pos = a_pos;
225                 peer_id = a_peer_id;
226         }
227         bool operator < (PrioritySortedBlockTransfer &other)
228         {
229                 return priority < other.priority;
230         }
231         float priority;
232         v3s16 pos;
233         u16 peer_id;
234 };
235
236 class RemoteClient
237 {
238 public:
239         // peer_id=0 means this client has no associated peer
240         // NOTE: If client is made allowed to exist while peer doesn't,
241         //       this has to be set to 0 when there is no peer.
242         //       Also, the client must be moved to some other container.
243         u16 peer_id;
244         // The serialization version to use with the client
245         u8 serialization_version;
246         //
247         u16 net_proto_version;
248         // Version is stored in here after INIT before INIT2
249         u8 pending_serialization_version;
250
251         RemoteClient():
252                 m_time_from_building(9999),
253                 m_excess_gotblocks(0)
254         {
255                 peer_id = 0;
256                 serialization_version = SER_FMT_VER_INVALID;
257                 net_proto_version = 0;
258                 pending_serialization_version = SER_FMT_VER_INVALID;
259                 m_nearest_unsent_d = 0;
260                 m_nearest_unsent_reset_timer = 0.0;
261                 m_nothing_to_send_counter = 0;
262                 m_nothing_to_send_pause_timer = 0;
263         }
264         ~RemoteClient()
265         {
266         }
267         
268         /*
269                 Finds block that should be sent next to the client.
270                 Environment should be locked when this is called.
271                 dtime is used for resetting send radius at slow interval
272         */
273         void GetNextBlocks(Server *server, float dtime,
274                         core::array<PrioritySortedBlockTransfer> &dest);
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, public IGameDef,
360                 public IBackgroundBlockEmerger
361 {
362 public:
363         /*
364                 NOTE: Every public method should be thread-safe
365         */
366
367         Server(
368                 std::string mapsavedir,
369                 std::string configpath
370         );
371         ~Server();
372         void start(unsigned short port);
373         void stop();
374         // This is mainly a way to pass the time to the server.
375         // Actual processing is done in an another thread.
376         void step(float dtime);
377         // This is run by ServerThread and does the actual processing
378         void AsyncRunStep();
379         void Receive();
380         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
381
382         core::list<PlayerInfo> getPlayerInfo();
383
384         /*u32 getDayNightRatio()
385         {
386                 return time_to_daynight_ratio(m_time_of_day.get());
387         }*/
388         
389         // Environment must be locked when called
390         void setTimeOfDay(u32 time)
391         {
392                 m_env->setTimeOfDay(time);
393                 m_time_of_day_send_timer = 0;
394         }
395
396         bool getShutdownRequested()
397         {
398                 return m_shutdown_requested;
399         }
400         
401         /*
402                 Shall be called with the environment locked.
403                 This is accessed by the map, which is inside the environment,
404                 so it shouldn't be a problem.
405         */
406         void onMapEditEvent(MapEditEvent *event);
407
408         /*
409                 Shall be called with the environment and the connection locked.
410         */
411         Inventory* getInventory(InventoryContext *c, std::string id);
412         void inventoryModified(InventoryContext *c, std::string id);
413
414         // Connection must be locked when called
415         std::wstring getStatusString();
416
417         void requestShutdown(void)
418         {
419                 m_shutdown_requested = true;
420         }
421
422
423         // Envlock and conlock should be locked when calling this
424         void SendMovePlayer(Player *player);
425         
426         u64 getPlayerAuthPrivs(const std::string &name)
427         {
428                 try{
429                         return m_authmanager.getPrivs(name);
430                 }
431                 catch(AuthNotFoundException &e)
432                 {
433                         dstream<<"WARNING: Auth not found for "<<name<<std::endl;
434                         return 0;
435                 }
436         }
437
438         void setPlayerAuthPrivs(const std::string &name, u64 privs)
439         {
440                 try{
441                         return m_authmanager.setPrivs(name, privs);
442                 }
443                 catch(AuthNotFoundException &e)
444                 {
445                         dstream<<"WARNING: Auth not found for "<<name<<std::endl;
446                 }
447         }
448
449         // Changes a player's password, password must be given as plaintext
450         // If the player doesn't exist, a new entry is added to the auth manager
451         void setPlayerPassword(const std::string &name, const std::wstring &password);
452         
453         // Saves g_settings to configpath given at initialization
454         void saveConfig();
455
456         void setIpBanned(const std::string &ip, const std::string &name)
457         {
458                 m_banmanager.add(ip, name);
459                 return;
460         }
461
462         void unsetIpBanned(const std::string &ip_or_name)
463         {
464                 m_banmanager.remove(ip_or_name);
465                 return;
466         }
467
468         std::string getBanDescription(const std::string &ip_or_name)
469         {
470                 return m_banmanager.getBanDescription(ip_or_name);
471         }
472
473         Address getPeerAddress(u16 peer_id)
474         {
475                 return m_con.GetPeerAddress(peer_id);
476         }
477         
478         // Envlock and conlock should be locked when calling this
479         void notifyPlayer(const char *name, const std::wstring msg);
480         void notifyPlayers(const std::wstring msg);
481
482         void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
483         
484         // Envlock and conlock should be locked when using Lua
485         lua_State *getLua(){ return m_lua; }
486         
487         // IGameDef interface
488         // Under envlock
489         virtual IToolDefManager* getToolDefManager();
490         virtual INodeDefManager* getNodeDefManager();
491         virtual ICraftDefManager* getCraftDefManager();
492         virtual ICraftItemDefManager* getCraftItemDefManager();
493         virtual ITextureSource* getTextureSource();
494         virtual u16 allocateUnknownNodeId(const std::string &name);
495         
496         IWritableToolDefManager* getWritableToolDefManager();
497         IWritableNodeDefManager* getWritableNodeDefManager();
498         IWritableCraftDefManager* getWritableCraftDefManager();
499         IWritableCraftItemDefManager* getWritableCraftItemDefManager();
500
501 private:
502
503         // con::PeerHandler implementation.
504         // These queue stuff to be processed by handlePeerChanges().
505         // As of now, these create and remove clients and players.
506         void peerAdded(con::Peer *peer);
507         void deletingPeer(con::Peer *peer, bool timeout);
508         
509         /*
510                 Static send methods
511         */
512         
513         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
514         static void SendAccessDenied(con::Connection &con, u16 peer_id,
515                         const std::wstring &reason);
516         static void SendDeathscreen(con::Connection &con, u16 peer_id,
517                         bool set_camera_point_target, v3f camera_point_target);
518         static void SendToolDef(con::Connection &con, u16 peer_id,
519                         IToolDefManager *tooldef);
520         static void SendNodeDef(con::Connection &con, u16 peer_id,
521                         INodeDefManager *nodedef);
522         static void SendCraftItemDef(con::Connection &con, u16 peer_id,
523                         ICraftItemDefManager *nodedef);
524         
525         /*
526                 Non-static send methods.
527                 Conlock should be always used.
528                 Envlock usage is documented badly but it's easy to figure out
529                 which ones access the environment.
530         */
531
532         // Envlock and conlock should be locked when calling these
533         void SendInventory(u16 peer_id);
534         // send wielded item info about player to all
535         void SendWieldedItem(const Player *player);
536         // send wielded item info about all players to all players
537         void SendPlayerItems();
538         void SendChatMessage(u16 peer_id, const std::wstring &message);
539         void BroadcastChatMessage(const std::wstring &message);
540         void SendPlayerHP(Player *player);
541         /*
542                 Send a node removal/addition event to all clients except ignore_id.
543                 Additionally, if far_players!=NULL, players further away than
544                 far_d_nodes are ignored and their peer_ids are added to far_players
545         */
546         // Envlock and conlock should be locked when calling these
547         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
548                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
549         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
550                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
551         void setBlockNotSent(v3s16 p);
552         
553         // Environment and Connection must be locked when called
554         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
555         
556         // Sends blocks to clients (locks env and con on its own)
557         void SendBlocks(float dtime);
558         
559         void SendTextures(u16 peer_id);
560
561         /*
562                 Something random
563         */
564         
565         void HandlePlayerHP(Player *player, s16 damage);
566         void RespawnPlayer(Player *player);
567         
568         void UpdateCrafting(u16 peer_id);
569         
570         // When called, connection mutex should be locked
571         RemoteClient* getClient(u16 peer_id);
572         
573         // When called, environment mutex should be locked
574         std::string getPlayerName(u16 peer_id)
575         {
576                 Player *player = m_env->getPlayer(peer_id);
577                 if(player == NULL)
578                         return "[id="+itos(peer_id);
579                 return player->getName();
580         }
581
582         /*
583                 Get a player from memory or creates one.
584                 If player is already connected, return NULL
585                 Does not verify/modify auth info and password.
586
587                 Call with env and con locked.
588         */
589         ServerRemotePlayer *emergePlayer(const char *name, u16 peer_id);
590         
591         // Locks environment and connection by its own
592         struct PeerChange;
593         void handlePeerChange(PeerChange &c);
594         void handlePeerChanges();
595
596         u64 getPlayerPrivs(Player *player);
597
598         /*
599                 Variables
600         */
601         
602         // Some timers
603         float m_liquid_transform_timer;
604         float m_print_info_timer;
605         float m_objectdata_timer;
606         float m_emergethread_trigger_timer;
607         float m_savemap_timer;
608         IntervalLimiter m_map_timer_and_unload_interval;
609         
610         // NOTE: If connection and environment are both to be locked,
611         // environment shall be locked first.
612
613         // Environment
614         ServerEnvironment *m_env;
615         JMutex m_env_mutex;
616         
617         // Connection
618         con::Connection m_con;
619         JMutex m_con_mutex;
620         // Connected clients (behind the con mutex)
621         core::map<u16, RemoteClient*> m_clients;
622
623         // User authentication
624         AuthManager m_authmanager;
625
626         // Bann checking
627         BanManager m_banmanager;
628
629         // Scripting
630         // Envlock and conlock should be locked when using Lua
631         lua_State *m_lua;
632
633         // Tool definition manager
634         IWritableToolDefManager *m_toolmgr;
635         
636         // Node definition manager
637         IWritableNodeDefManager *m_nodedef;
638         
639         // Craft definition manager
640         IWritableCraftDefManager *m_craftdef;
641         
642         // CraftItem definition manager
643         IWritableCraftItemDefManager *m_craftitemdef;
644         
645         /*
646                 Threads
647         */
648         
649         // A buffer for time steps
650         // step() increments and AsyncRunStep() run by m_thread reads it.
651         float m_step_dtime;
652         JMutex m_step_dtime_mutex;
653
654         // The server mainly operates in this thread
655         ServerThread m_thread;
656         // This thread fetches and generates map
657         EmergeThread m_emergethread;
658         // Queue of block coordinates to be processed by the emerge thread
659         BlockEmergeQueue m_emerge_queue;
660         
661         /*
662                 Time related stuff
663         */
664
665         // 0-23999
666         //MutexedVariable<u32> m_time_of_day;
667         // Used to buffer dtime for adding to m_time_of_day
668         float m_time_counter;
669         // Timer for sending time of day over network
670         float m_time_of_day_send_timer;
671         // Uptime of server in seconds
672         MutexedVariable<double> m_uptime;
673         
674         /*
675                 Peer change queue.
676                 Queues stuff from peerAdded() and deletingPeer() to
677                 handlePeerChanges()
678         */
679         enum PeerChangeType
680         {
681                 PEER_ADDED,
682                 PEER_REMOVED
683         };
684         struct PeerChange
685         {
686                 PeerChangeType type;
687                 u16 peer_id;
688                 bool timeout;
689         };
690         Queue<PeerChange> m_peer_change_queue;
691
692         /*
693                 Random stuff
694         */
695
696         // Map directory
697         std::string m_mapsavedir;
698
699         // Configuration path ("" = no configuration file)
700         std::string m_configpath;
701         
702         // Mod parent directory paths
703         core::list<std::string> m_modspaths;
704
705         bool m_shutdown_requested;
706         
707         /*
708                 Map edit event queue. Automatically receives all map edits.
709                 The constructor of this class registers us to receive them through
710                 onMapEditEvent
711
712                 NOTE: Should these be moved to actually be members of
713                 ServerEnvironment?
714         */
715
716         /*
717                 Queue of map edits from the environment for sending to the clients
718                 This is behind m_env_mutex
719         */
720         Queue<MapEditEvent*> m_unsent_map_edit_queue;
721         /*
722                 Set to true when the server itself is modifying the map and does
723                 all sending of information by itself.
724                 This is behind m_env_mutex
725         */
726         bool m_ignore_map_edit_events;
727         /*
728                 If set to !=0, the incoming MapEditEvents are modified to have
729                 this peed id as the disabled recipient
730                 This is behind m_env_mutex
731         */
732         u16 m_ignore_map_edit_events_peer_id;
733
734         friend class EmergeThread;
735         friend class RemoteClient;
736 };
737
738 /*
739         Runs a simple dedicated server loop.
740
741         Shuts down when run is set to false.
742 */
743 void dedicated_server_loop(Server &server, bool &run);
744
745 #endif
746