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