4316bc21fd4a64726c8b43e7ac6fb1cbdf7bcdbd
[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 Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser 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 "irrlichttypes_bloated.h"
26 #include <string>
27 #include "porting.h"
28 #include "map.h"
29 #include "inventory.h"
30 #include "ban.h"
31 #include "gamedef.h"
32 #include "serialization.h" // For SER_FMT_VER_INVALID
33 #include "mods.h"
34 #include "inventorymanager.h"
35 #include "subgame.h"
36 #include "sound.h"
37 #include "util/thread.h"
38 #include "util/string.h"
39
40 struct LuaState;
41 typedef struct lua_State lua_State;
42 class IWritableItemDefManager;
43 class IWritableNodeDefManager;
44 class IWritableCraftDefManager;
45 class EventManager;
46 class PlayerSAO;
47
48 class ServerError : public std::exception
49 {
50 public:
51         ServerError(const std::string &s)
52         {
53                 m_s = "ServerError: ";
54                 m_s += s;
55         }
56         virtual ~ServerError() throw()
57         {}
58         virtual const char * what() const throw()
59         {
60                 return m_s.c_str();
61         }
62         std::string m_s;
63 };
64
65 /*
66         Some random functions
67 */
68 v3f findSpawnPos(ServerMap &map);
69
70 /*
71         A structure containing the data needed for queueing the fetching
72         of blocks.
73 */
74 struct QueuedBlockEmerge
75 {
76         v3s16 pos;
77         // key = peer_id, value = flags
78         core::map<u16, u8> peer_ids;
79 };
80
81 /*
82         This is a thread-safe class.
83 */
84 class BlockEmergeQueue
85 {
86 public:
87         BlockEmergeQueue()
88         {
89                 m_mutex.Init();
90         }
91
92         ~BlockEmergeQueue()
93         {
94                 JMutexAutoLock lock(m_mutex);
95
96                 core::list<QueuedBlockEmerge*>::Iterator i;
97                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
98                 {
99                         QueuedBlockEmerge *q = *i;
100                         delete q;
101                 }
102         }
103         
104         /*
105                 peer_id=0 adds with nobody to send to
106         */
107         void addBlock(u16 peer_id, v3s16 pos, u8 flags)
108         {
109                 DSTACK(__FUNCTION_NAME);
110         
111                 JMutexAutoLock lock(m_mutex);
112
113                 if(peer_id != 0)
114                 {
115                         /*
116                                 Find if block is already in queue.
117                                 If it is, update the peer to it and quit.
118                         */
119                         core::list<QueuedBlockEmerge*>::Iterator i;
120                         for(i=m_queue.begin(); i!=m_queue.end(); i++)
121                         {
122                                 QueuedBlockEmerge *q = *i;
123                                 if(q->pos == pos)
124                                 {
125                                         q->peer_ids[peer_id] = flags;
126                                         return;
127                                 }
128                         }
129                 }
130                 
131                 /*
132                         Add the block
133                 */
134                 QueuedBlockEmerge *q = new QueuedBlockEmerge;
135                 q->pos = pos;
136                 if(peer_id != 0)
137                         q->peer_ids[peer_id] = flags;
138                 m_queue.push_back(q);
139         }
140
141         // Returned pointer must be deleted
142         // Returns NULL if queue is empty
143         QueuedBlockEmerge * pop()
144         {
145                 JMutexAutoLock lock(m_mutex);
146
147                 core::list<QueuedBlockEmerge*>::Iterator i = m_queue.begin();
148                 if(i == m_queue.end())
149                         return NULL;
150                 QueuedBlockEmerge *q = *i;
151                 m_queue.erase(i);
152                 return q;
153         }
154
155         u32 size()
156         {
157                 JMutexAutoLock lock(m_mutex);
158                 return m_queue.size();
159         }
160         
161         u32 peerItemCount(u16 peer_id)
162         {
163                 JMutexAutoLock lock(m_mutex);
164
165                 u32 count = 0;
166
167                 core::list<QueuedBlockEmerge*>::Iterator i;
168                 for(i=m_queue.begin(); i!=m_queue.end(); i++)
169                 {
170                         QueuedBlockEmerge *q = *i;
171                         if(q->peer_ids.find(peer_id) != NULL)
172                                 count++;
173                 }
174
175                 return count;
176         }
177
178 private:
179         core::list<QueuedBlockEmerge*> m_queue;
180         JMutex m_mutex;
181 };
182
183 class Server;
184
185 class ServerThread : public SimpleThread
186 {
187         Server *m_server;
188
189 public:
190
191         ServerThread(Server *server):
192                 SimpleThread(),
193                 m_server(server)
194         {
195         }
196
197         void * Thread();
198 };
199
200 class EmergeThread : public SimpleThread
201 {
202         Server *m_server;
203
204 public:
205
206         EmergeThread(Server *server):
207                 SimpleThread(),
208                 m_server(server)
209         {
210         }
211
212         void * Thread();
213
214         void trigger()
215         {
216                 setRun(true);
217                 if(IsRunning() == false)
218                 {
219                         Start();
220                 }
221         }
222 };
223
224 struct PlayerInfo
225 {
226         u16 id;
227         char name[PLAYERNAME_SIZE];
228         v3f position;
229         Address address;
230         float avg_rtt;
231
232         PlayerInfo();
233         void PrintLine(std::ostream *s);
234 };
235
236 /*
237         Used for queueing and sorting block transfers in containers
238         
239         Lower priority number means higher priority.
240 */
241 struct PrioritySortedBlockTransfer
242 {
243         PrioritySortedBlockTransfer(float a_priority, v3s16 a_pos, u16 a_peer_id)
244         {
245                 priority = a_priority;
246                 pos = a_pos;
247                 peer_id = a_peer_id;
248         }
249         bool operator < (PrioritySortedBlockTransfer &other)
250         {
251                 return priority < other.priority;
252         }
253         float priority;
254         v3s16 pos;
255         u16 peer_id;
256 };
257
258 struct MediaRequest
259 {
260         std::string name;
261
262         MediaRequest(const std::string &name_=""):
263                 name(name_)
264         {}
265 };
266
267 struct MediaInfo
268 {
269         std::string path;
270         std::string sha1_digest;
271
272         MediaInfo(const std::string path_="",
273                         const std::string sha1_digest_=""):
274                 path(path_),
275                 sha1_digest(sha1_digest_)
276         {
277         }
278 };
279
280 struct ServerSoundParams
281 {
282         float gain;
283         std::string to_player;
284         enum Type{
285                 SSP_LOCAL=0,
286                 SSP_POSITIONAL=1,
287                 SSP_OBJECT=2
288         } type;
289         v3f pos;
290         u16 object;
291         float max_hear_distance;
292         bool loop;
293
294         ServerSoundParams():
295                 gain(1.0),
296                 to_player(""),
297                 type(SSP_LOCAL),
298                 pos(0,0,0),
299                 object(0),
300                 max_hear_distance(32*BS),
301                 loop(false)
302         {}
303         
304         v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
305 };
306
307 struct ServerPlayingSound
308 {
309         ServerSoundParams params;
310         std::set<u16> clients; // peer ids
311 };
312
313 class RemoteClient
314 {
315 public:
316         // peer_id=0 means this client has no associated peer
317         // NOTE: If client is made allowed to exist while peer doesn't,
318         //       this has to be set to 0 when there is no peer.
319         //       Also, the client must be moved to some other container.
320         u16 peer_id;
321         // The serialization version to use with the client
322         u8 serialization_version;
323         //
324         u16 net_proto_version;
325         // Version is stored in here after INIT before INIT2
326         u8 pending_serialization_version;
327
328         bool definitions_sent;
329
330         RemoteClient():
331                 m_time_from_building(9999),
332                 m_excess_gotblocks(0)
333         {
334                 peer_id = 0;
335                 serialization_version = SER_FMT_VER_INVALID;
336                 net_proto_version = 0;
337                 pending_serialization_version = SER_FMT_VER_INVALID;
338                 definitions_sent = false;
339                 m_nearest_unsent_d = 0;
340                 m_nearest_unsent_reset_timer = 0.0;
341                 m_nothing_to_send_counter = 0;
342                 m_nothing_to_send_pause_timer = 0;
343         }
344         ~RemoteClient()
345         {
346         }
347         
348         /*
349                 Finds block that should be sent next to the client.
350                 Environment should be locked when this is called.
351                 dtime is used for resetting send radius at slow interval
352         */
353         void GetNextBlocks(Server *server, float dtime,
354                         core::array<PrioritySortedBlockTransfer> &dest);
355
356         void GotBlock(v3s16 p);
357
358         void SentBlock(v3s16 p);
359
360         void SetBlockNotSent(v3s16 p);
361         void SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks);
362
363         s32 SendingCount()
364         {
365                 return m_blocks_sending.size();
366         }
367         
368         // Increments timeouts and removes timed-out blocks from list
369         // NOTE: This doesn't fix the server-not-sending-block bug
370         //       because it is related to emerging, not sending.
371         //void RunSendingTimeouts(float dtime, float timeout);
372
373         void PrintInfo(std::ostream &o)
374         {
375                 o<<"RemoteClient "<<peer_id<<": "
376                                 <<"m_blocks_sent.size()="<<m_blocks_sent.size()
377                                 <<", m_blocks_sending.size()="<<m_blocks_sending.size()
378                                 <<", m_nearest_unsent_d="<<m_nearest_unsent_d
379                                 <<", m_excess_gotblocks="<<m_excess_gotblocks
380                                 <<std::endl;
381                 m_excess_gotblocks = 0;
382         }
383
384         // Time from last placing or removing blocks
385         float m_time_from_building;
386         
387         /*JMutex m_dig_mutex;
388         float m_dig_time_remaining;
389         // -1 = not digging
390         s16 m_dig_tool_item;
391         v3s16 m_dig_position;*/
392         
393         /*
394                 List of active objects that the client knows of.
395                 Value is dummy.
396         */
397         core::map<u16, bool> m_known_objects;
398
399 private:
400         /*
401                 Blocks that have been sent to client.
402                 - These don't have to be sent again.
403                 - A block is cleared from here when client says it has
404                   deleted it from it's memory
405                 
406                 Key is position, value is dummy.
407                 No MapBlock* is stored here because the blocks can get deleted.
408         */
409         core::map<v3s16, bool> m_blocks_sent;
410         s16 m_nearest_unsent_d;
411         v3s16 m_last_center;
412         float m_nearest_unsent_reset_timer;
413         
414         /*
415                 Blocks that are currently on the line.
416                 This is used for throttling the sending of blocks.
417                 - The size of this list is limited to some value
418                 Block is added when it is sent with BLOCKDATA.
419                 Block is removed when GOTBLOCKS is received.
420                 Value is time from sending. (not used at the moment)
421         */
422         core::map<v3s16, float> m_blocks_sending;
423
424         /*
425                 Count of excess GotBlocks().
426                 There is an excess amount because the client sometimes
427                 gets a block so late that the server sends it again,
428                 and the client then sends two GOTBLOCKs.
429                 This is resetted by PrintInfo()
430         */
431         u32 m_excess_gotblocks;
432         
433         // CPU usage optimization
434         u32 m_nothing_to_send_counter;
435         float m_nothing_to_send_pause_timer;
436 };
437
438 class Server : public con::PeerHandler, public MapEventReceiver,
439                 public InventoryManager, public IGameDef,
440                 public IBackgroundBlockEmerger
441 {
442 public:
443         /*
444                 NOTE: Every public method should be thread-safe
445         */
446         
447         Server(
448                 const std::string &path_world,
449                 const std::string &path_config,
450                 const SubgameSpec &gamespec,
451                 bool simple_singleplayer_mode
452         );
453         ~Server();
454         void start(unsigned short port);
455         void stop();
456         // This is mainly a way to pass the time to the server.
457         // Actual processing is done in an another thread.
458         void step(float dtime);
459         // This is run by ServerThread and does the actual processing
460         void AsyncRunStep();
461         void Receive();
462         void ProcessData(u8 *data, u32 datasize, u16 peer_id);
463
464         core::list<PlayerInfo> getPlayerInfo();
465
466         // Environment must be locked when called
467         void setTimeOfDay(u32 time)
468         {
469                 m_env->setTimeOfDay(time);
470                 m_time_of_day_send_timer = 0;
471         }
472
473         bool getShutdownRequested()
474         {
475                 return m_shutdown_requested;
476         }
477         
478         /*
479                 Shall be called with the environment locked.
480                 This is accessed by the map, which is inside the environment,
481                 so it shouldn't be a problem.
482         */
483         void onMapEditEvent(MapEditEvent *event);
484
485         /*
486                 Shall be called with the environment and the connection locked.
487         */
488         Inventory* getInventory(const InventoryLocation &loc);
489         void setInventoryModified(const InventoryLocation &loc);
490
491         // Connection must be locked when called
492         std::wstring getStatusString();
493
494         void requestShutdown(void)
495         {
496                 m_shutdown_requested = true;
497         }
498
499         // Returns -1 if failed, sound handle on success
500         // Envlock + conlock
501         s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
502         void stopSound(s32 handle);
503         
504         // Envlock + conlock
505         std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
506         bool checkPriv(const std::string &name, const std::string &priv);
507         void reportPrivsModified(const std::string &name=""); // ""=all
508         void reportInventoryFormspecModified(const std::string &name);
509
510         // Saves g_settings to configpath given at initialization
511         void saveConfig();
512
513         void setIpBanned(const std::string &ip, const std::string &name)
514         {
515                 m_banmanager.add(ip, name);
516                 return;
517         }
518
519         void unsetIpBanned(const std::string &ip_or_name)
520         {
521                 m_banmanager.remove(ip_or_name);
522                 return;
523         }
524
525         std::string getBanDescription(const std::string &ip_or_name)
526         {
527                 return m_banmanager.getBanDescription(ip_or_name);
528         }
529
530         Address getPeerAddress(u16 peer_id)
531         {
532                 return m_con.GetPeerAddress(peer_id);
533         }
534         
535         // Envlock and conlock should be locked when calling this
536         void notifyPlayer(const char *name, const std::wstring msg);
537         void notifyPlayers(const std::wstring msg);
538
539         void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
540         
541         // Creates or resets inventory
542         Inventory* createDetachedInventory(const std::string &name);
543         
544         // Envlock and conlock should be locked when using Lua
545         lua_State *getLua(){ return m_lua; }
546         
547         // IGameDef interface
548         // Under envlock
549         virtual IItemDefManager* getItemDefManager();
550         virtual INodeDefManager* getNodeDefManager();
551         virtual ICraftDefManager* getCraftDefManager();
552         virtual ITextureSource* getTextureSource();
553         virtual u16 allocateUnknownNodeId(const std::string &name);
554         virtual ISoundManager* getSoundManager();
555         virtual MtEventManager* getEventManager();
556         
557         IWritableItemDefManager* getWritableItemDefManager();
558         IWritableNodeDefManager* getWritableNodeDefManager();
559         IWritableCraftDefManager* getWritableCraftDefManager();
560
561         const ModSpec* getModSpec(const std::string &modname);
562         void getModNames(core::list<std::string> &modlist);
563         std::string getBuiltinLuaPath();
564         
565         std::string getWorldPath(){ return m_path_world; }
566
567         bool isSingleplayer(){ return m_simple_singleplayer_mode; }
568
569         void setAsyncFatalError(const std::string &error)
570         {
571                 m_async_fatal_error.set(error);
572         }
573
574 private:
575
576         // con::PeerHandler implementation.
577         // These queue stuff to be processed by handlePeerChanges().
578         // As of now, these create and remove clients and players.
579         void peerAdded(con::Peer *peer);
580         void deletingPeer(con::Peer *peer, bool timeout);
581         
582         /*
583                 Static send methods
584         */
585         
586         static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
587         static void SendAccessDenied(con::Connection &con, u16 peer_id,
588                         const std::wstring &reason);
589         static void SendDeathscreen(con::Connection &con, u16 peer_id,
590                         bool set_camera_point_target, v3f camera_point_target);
591         static void SendItemDef(con::Connection &con, u16 peer_id,
592                         IItemDefManager *itemdef);
593         static void SendNodeDef(con::Connection &con, u16 peer_id,
594                         INodeDefManager *nodedef);
595         
596         /*
597                 Non-static send methods.
598                 Conlock should be always used.
599                 Envlock usage is documented badly but it's easy to figure out
600                 which ones access the environment.
601         */
602
603         // Envlock and conlock should be locked when calling these
604         void SendInventory(u16 peer_id);
605         void SendChatMessage(u16 peer_id, const std::wstring &message);
606         void BroadcastChatMessage(const std::wstring &message);
607         void SendPlayerHP(u16 peer_id);
608         void SendMovePlayer(u16 peer_id);
609         void SendPlayerPrivileges(u16 peer_id);
610         void SendPlayerInventoryFormspec(u16 peer_id);
611         /*
612                 Send a node removal/addition event to all clients except ignore_id.
613                 Additionally, if far_players!=NULL, players further away than
614                 far_d_nodes are ignored and their peer_ids are added to far_players
615         */
616         // Envlock and conlock should be locked when calling these
617         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
618                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
619         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
620                         core::list<u16> *far_players=NULL, float far_d_nodes=100);
621         void setBlockNotSent(v3s16 p);
622         
623         // Environment and Connection must be locked when called
624         void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
625         
626         // Sends blocks to clients (locks env and con on its own)
627         void SendBlocks(float dtime);
628         
629         void fillMediaCache();
630         void sendMediaAnnouncement(u16 peer_id);
631         void sendRequestedMedia(u16 peer_id,
632                         const core::list<MediaRequest> &tosend);
633         
634         void sendDetachedInventory(const std::string &name, u16 peer_id);
635         void sendDetachedInventoryToAll(const std::string &name);
636         void sendDetachedInventories(u16 peer_id);
637
638         /*
639                 Something random
640         */
641         
642         void DiePlayer(u16 peer_id);
643         void RespawnPlayer(u16 peer_id);
644         
645         void UpdateCrafting(u16 peer_id);
646         
647         // When called, connection mutex should be locked
648         RemoteClient* getClient(u16 peer_id);
649         
650         // When called, environment mutex should be locked
651         std::string getPlayerName(u16 peer_id)
652         {
653                 Player *player = m_env->getPlayer(peer_id);
654                 if(player == NULL)
655                         return "[id="+itos(peer_id)+"]";
656                 return player->getName();
657         }
658
659         // When called, environment mutex should be locked
660         PlayerSAO* getPlayerSAO(u16 peer_id)
661         {
662                 Player *player = m_env->getPlayer(peer_id);
663                 if(player == NULL)
664                         return NULL;
665                 return player->getPlayerSAO();
666         }
667
668         /*
669                 Get a player from memory or creates one.
670                 If player is already connected, return NULL
671                 Does not verify/modify auth info and password.
672
673                 Call with env and con locked.
674         */
675         PlayerSAO *emergePlayer(const char *name, u16 peer_id);
676         
677         // Locks environment and connection by its own
678         struct PeerChange;
679         void handlePeerChange(PeerChange &c);
680         void handlePeerChanges();
681
682         /*
683                 Variables
684         */
685         
686         // World directory
687         std::string m_path_world;
688         // Path to user's configuration file ("" = no configuration file)
689         std::string m_path_config;
690         // Subgame specification
691         SubgameSpec m_gamespec;
692         // If true, do not allow multiple players and hide some multiplayer
693         // functionality
694         bool m_simple_singleplayer_mode;
695
696         // Thread can set; step() will throw as ServerError
697         MutexedVariable<std::string> m_async_fatal_error;
698         
699         // Some timers
700         float m_liquid_transform_timer;
701         float m_print_info_timer;
702         float m_objectdata_timer;
703         float m_emergethread_trigger_timer;
704         float m_savemap_timer;
705         IntervalLimiter m_map_timer_and_unload_interval;
706         
707         // NOTE: If connection and environment are both to be locked,
708         // environment shall be locked first.
709
710         // Environment
711         ServerEnvironment *m_env;
712         JMutex m_env_mutex;
713         
714         // Connection
715         con::Connection m_con;
716         JMutex m_con_mutex;
717         // Connected clients (behind the con mutex)
718         core::map<u16, RemoteClient*> m_clients;
719
720         // Bann checking
721         BanManager m_banmanager;
722
723         // Scripting
724         // Envlock and conlock should be locked when using Lua
725         lua_State *m_lua;
726
727         // Item definition manager
728         IWritableItemDefManager *m_itemdef;
729         
730         // Node definition manager
731         IWritableNodeDefManager *m_nodedef;
732         
733         // Craft definition manager
734         IWritableCraftDefManager *m_craftdef;
735         
736         // Event manager
737         EventManager *m_event;
738         
739         // Mods
740         core::list<ModSpec> m_mods;
741         
742         /*
743                 Threads
744         */
745         
746         // A buffer for time steps
747         // step() increments and AsyncRunStep() run by m_thread reads it.
748         float m_step_dtime;
749         JMutex m_step_dtime_mutex;
750
751         // The server mainly operates in this thread
752         ServerThread m_thread;
753         // This thread fetches and generates map
754         EmergeThread m_emergethread;
755         // Queue of block coordinates to be processed by the emerge thread
756         BlockEmergeQueue m_emerge_queue;
757         
758         /*
759                 Time related stuff
760         */
761
762         // Timer for sending time of day over network
763         float m_time_of_day_send_timer;
764         // Uptime of server in seconds
765         MutexedVariable<double> m_uptime;
766         
767         /*
768                 Peer change queue.
769                 Queues stuff from peerAdded() and deletingPeer() to
770                 handlePeerChanges()
771         */
772         enum PeerChangeType
773         {
774                 PEER_ADDED,
775                 PEER_REMOVED
776         };
777         struct PeerChange
778         {
779                 PeerChangeType type;
780                 u16 peer_id;
781                 bool timeout;
782         };
783         Queue<PeerChange> m_peer_change_queue;
784
785         /*
786                 Random stuff
787         */
788         
789         // Mod parent directory paths
790         core::list<std::string> m_modspaths;
791
792         bool m_shutdown_requested;
793
794         /*
795                 Map edit event queue. Automatically receives all map edits.
796                 The constructor of this class registers us to receive them through
797                 onMapEditEvent
798
799                 NOTE: Should these be moved to actually be members of
800                 ServerEnvironment?
801         */
802
803         /*
804                 Queue of map edits from the environment for sending to the clients
805                 This is behind m_env_mutex
806         */
807         Queue<MapEditEvent*> m_unsent_map_edit_queue;
808         /*
809                 Set to true when the server itself is modifying the map and does
810                 all sending of information by itself.
811                 This is behind m_env_mutex
812         */
813         bool m_ignore_map_edit_events;
814         /*
815                 If a non-empty area, map edit events contained within are left
816                 unsent. Done at map generation time to speed up editing of the
817                 generated area, as it will be sent anyway.
818                 This is behind m_env_mutex
819         */
820         VoxelArea m_ignore_map_edit_events_area;
821         /*
822                 If set to !=0, the incoming MapEditEvents are modified to have
823                 this peed id as the disabled recipient
824                 This is behind m_env_mutex
825         */
826         u16 m_ignore_map_edit_events_peer_id;
827
828         friend class EmergeThread;
829         friend class RemoteClient;
830
831         std::map<std::string,MediaInfo> m_media;
832
833         /*
834                 Sounds
835         */
836         std::map<s32, ServerPlayingSound> m_playing_sounds;
837         s32 m_next_sound_id;
838
839         /*
840                 Detached inventories (behind m_env_mutex)
841         */
842         // key = name
843         std::map<std::string, Inventory*> m_detached_inventories;
844 };
845
846 /*
847         Runs a simple dedicated server loop.
848
849         Shuts down when run is set to false.
850 */
851 void dedicated_server_loop(Server &server, bool &run);
852
853 #endif
854