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