]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.h
Remove Server::m_ignore_map_edit_events (noop)
[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 #pragma once
21
22 #include "irr_v3d.h"
23 #include "map.h"
24 #include "hud.h"
25 #include "gamedef.h"
26 #include "serialization.h" // For SER_FMT_VER_INVALID
27 #include "content/mods.h"
28 #include "inventorymanager.h"
29 #include "content/subgames.h"
30 #include "tileanimation.h" // struct TileAnimationParams
31 #include "network/peerhandler.h"
32 #include "network/address.h"
33 #include "util/numeric.h"
34 #include "util/thread.h"
35 #include "util/basic_macros.h"
36 #include "serverenvironment.h"
37 #include "clientiface.h"
38 #include "chatmessage.h"
39 #include <string>
40 #include <list>
41 #include <map>
42 #include <vector>
43
44 class ChatEvent;
45 struct ChatEventChat;
46 struct ChatInterface;
47 class IWritableItemDefManager;
48 class NodeDefManager;
49 class IWritableCraftDefManager;
50 class BanManager;
51 class EventManager;
52 class Inventory;
53 class ModChannelMgr;
54 class RemotePlayer;
55 class PlayerSAO;
56 struct PlayerHPChangeReason;
57 class IRollbackManager;
58 struct RollbackAction;
59 class EmergeManager;
60 class ServerScripting;
61 class ServerEnvironment;
62 struct SimpleSoundSpec;
63 struct CloudParams;
64 class ServerThread;
65 class ServerModManager;
66
67 enum ClientDeletionReason {
68         CDR_LEAVE,
69         CDR_TIMEOUT,
70         CDR_DENY
71 };
72
73 struct MediaInfo
74 {
75         std::string path;
76         std::string sha1_digest;
77
78         MediaInfo(const std::string &path_="",
79                   const std::string &sha1_digest_=""):
80                 path(path_),
81                 sha1_digest(sha1_digest_)
82         {
83         }
84 };
85
86 struct ServerSoundParams
87 {
88         enum Type {
89                 SSP_LOCAL,
90                 SSP_POSITIONAL,
91                 SSP_OBJECT
92         } type = SSP_LOCAL;
93         float gain = 1.0f;
94         float fade = 0.0f;
95         float pitch = 1.0f;
96         bool loop = false;
97         float max_hear_distance = 32 * BS;
98         v3f pos;
99         u16 object = 0;
100         std::string to_player = "";
101
102         v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
103 };
104
105 struct ServerPlayingSound
106 {
107         ServerSoundParams params;
108         SimpleSoundSpec spec;
109         std::unordered_set<session_t> clients; // peer ids
110 };
111
112 class Server : public con::PeerHandler, public MapEventReceiver,
113                 public InventoryManager, public IGameDef
114 {
115 public:
116         /*
117                 NOTE: Every public method should be thread-safe
118         */
119
120         Server(
121                 const std::string &path_world,
122                 const SubgameSpec &gamespec,
123                 bool simple_singleplayer_mode,
124                 Address bind_addr,
125                 bool dedicated,
126                 ChatInterface *iface = nullptr
127         );
128         ~Server();
129         DISABLE_CLASS_COPY(Server);
130
131         void init();
132         void start();
133         void stop();
134         // This is mainly a way to pass the time to the server.
135         // Actual processing is done in an another thread.
136         void step(float dtime);
137         // This is run by ServerThread and does the actual processing
138         void AsyncRunStep(bool initial_step=false);
139         void Receive();
140         PlayerSAO* StageTwoClientInit(session_t peer_id);
141
142         /*
143          * Command Handlers
144          */
145
146         void handleCommand(NetworkPacket* pkt);
147
148         void handleCommand_Null(NetworkPacket* pkt) {};
149         void handleCommand_Deprecated(NetworkPacket* pkt);
150         void handleCommand_Init(NetworkPacket* pkt);
151         void handleCommand_Init2(NetworkPacket* pkt);
152         void handleCommand_ModChannelJoin(NetworkPacket *pkt);
153         void handleCommand_ModChannelLeave(NetworkPacket *pkt);
154         void handleCommand_ModChannelMsg(NetworkPacket *pkt);
155         void handleCommand_RequestMedia(NetworkPacket* pkt);
156         void handleCommand_ClientReady(NetworkPacket* pkt);
157         void handleCommand_GotBlocks(NetworkPacket* pkt);
158         void handleCommand_PlayerPos(NetworkPacket* pkt);
159         void handleCommand_DeletedBlocks(NetworkPacket* pkt);
160         void handleCommand_InventoryAction(NetworkPacket* pkt);
161         void handleCommand_ChatMessage(NetworkPacket* pkt);
162         void handleCommand_Damage(NetworkPacket* pkt);
163         void handleCommand_Password(NetworkPacket* pkt);
164         void handleCommand_PlayerItem(NetworkPacket* pkt);
165         void handleCommand_Respawn(NetworkPacket* pkt);
166         void handleCommand_Interact(NetworkPacket* pkt);
167         void handleCommand_RemovedSounds(NetworkPacket* pkt);
168         void handleCommand_NodeMetaFields(NetworkPacket* pkt);
169         void handleCommand_InventoryFields(NetworkPacket* pkt);
170         void handleCommand_FirstSrp(NetworkPacket* pkt);
171         void handleCommand_SrpBytesA(NetworkPacket* pkt);
172         void handleCommand_SrpBytesM(NetworkPacket* pkt);
173
174         void ProcessData(NetworkPacket *pkt);
175
176         void Send(NetworkPacket *pkt);
177         void Send(session_t peer_id, NetworkPacket *pkt);
178
179         // Helper for handleCommand_PlayerPos and handleCommand_Interact
180         void process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
181                 NetworkPacket *pkt);
182
183         // Both setter and getter need no envlock,
184         // can be called freely from threads
185         void setTimeOfDay(u32 time);
186
187         /*
188                 Shall be called with the environment locked.
189                 This is accessed by the map, which is inside the environment,
190                 so it shouldn't be a problem.
191         */
192         void onMapEditEvent(MapEditEvent *event);
193
194         /*
195                 Shall be called with the environment and the connection locked.
196         */
197         Inventory* getInventory(const InventoryLocation &loc);
198         void setInventoryModified(const InventoryLocation &loc, bool playerSend = true);
199
200         // Connection must be locked when called
201         std::wstring getStatusString();
202         inline double getUptime() const { return m_uptime.m_value; }
203
204         // read shutdown state
205         inline bool isShutdownRequested() const { return m_shutdown_state.is_requested; }
206
207         // request server to shutdown
208         void requestShutdown(const std::string &msg, bool reconnect, float delay = 0.0f);
209
210         // Returns -1 if failed, sound handle on success
211         // Envlock
212         s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
213         void stopSound(s32 handle);
214         void fadeSound(s32 handle, float step, float gain);
215
216         // Envlock
217         std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
218         bool checkPriv(const std::string &name, const std::string &priv);
219         void reportPrivsModified(const std::string &name=""); // ""=all
220         void reportInventoryFormspecModified(const std::string &name);
221         void reportFormspecPrependModified(const std::string &name);
222
223         void setIpBanned(const std::string &ip, const std::string &name);
224         void unsetIpBanned(const std::string &ip_or_name);
225         std::string getBanDescription(const std::string &ip_or_name);
226
227         void notifyPlayer(const char *name, const std::wstring &msg);
228         void notifyPlayers(const std::wstring &msg);
229         void spawnParticle(const std::string &playername,
230                 v3f pos, v3f velocity, v3f acceleration,
231                 float expirationtime, float size,
232                 bool collisiondetection, bool collision_removal,
233                 bool vertical, const std::string &texture,
234                 const struct TileAnimationParams &animation, u8 glow);
235
236         u32 addParticleSpawner(u16 amount, float spawntime,
237                 v3f minpos, v3f maxpos,
238                 v3f minvel, v3f maxvel,
239                 v3f minacc, v3f maxacc,
240                 float minexptime, float maxexptime,
241                 float minsize, float maxsize,
242                 bool collisiondetection, bool collision_removal,
243                 ServerActiveObject *attached,
244                 bool vertical, const std::string &texture,
245                 const std::string &playername, const struct TileAnimationParams &animation,
246                 u8 glow);
247
248         void deleteParticleSpawner(const std::string &playername, u32 id);
249
250         // Creates or resets inventory
251         Inventory* createDetachedInventory(const std::string &name, const std::string &player="");
252
253         // Envlock and conlock should be locked when using scriptapi
254         ServerScripting *getScriptIface(){ return m_script; }
255
256         // actions: time-reversed list
257         // Return value: success/failure
258         bool rollbackRevertActions(const std::list<RollbackAction> &actions,
259                         std::list<std::string> *log);
260
261         // IGameDef interface
262         // Under envlock
263         virtual IItemDefManager* getItemDefManager();
264         virtual const NodeDefManager* getNodeDefManager();
265         virtual ICraftDefManager* getCraftDefManager();
266         virtual u16 allocateUnknownNodeId(const std::string &name);
267         IRollbackManager *getRollbackManager() { return m_rollback; }
268         virtual EmergeManager *getEmergeManager() { return m_emerge; }
269
270         IWritableItemDefManager* getWritableItemDefManager();
271         NodeDefManager* getWritableNodeDefManager();
272         IWritableCraftDefManager* getWritableCraftDefManager();
273
274         virtual const std::vector<ModSpec> &getMods() const;
275         virtual const ModSpec* getModSpec(const std::string &modname) const;
276         void getModNames(std::vector<std::string> &modlist);
277         std::string getBuiltinLuaPath();
278         virtual std::string getWorldPath() const { return m_path_world; }
279         virtual std::string getModStoragePath() const;
280
281         inline bool isSingleplayer()
282                         { return m_simple_singleplayer_mode; }
283
284         inline void setAsyncFatalError(const std::string &error)
285                         { m_async_fatal_error.set(error); }
286
287         bool showFormspec(const char *name, const std::string &formspec, const std::string &formname);
288         Map & getMap() { return m_env->getMap(); }
289         ServerEnvironment & getEnv() { return *m_env; }
290         v3f findSpawnPos();
291
292         u32 hudAdd(RemotePlayer *player, HudElement *element);
293         bool hudRemove(RemotePlayer *player, u32 id);
294         bool hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *value);
295         bool hudSetFlags(RemotePlayer *player, u32 flags, u32 mask);
296         bool hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount);
297         void hudSetHotbarImage(RemotePlayer *player, std::string name);
298         void hudSetHotbarSelectedImage(RemotePlayer *player, std::string name);
299
300         Address getPeerAddress(session_t peer_id);
301
302         void setLocalPlayerAnimations(RemotePlayer *player, v2s32 animation_frames[4],
303                         f32 frame_speed);
304         void setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third);
305
306         void setSky(RemotePlayer *player, const video::SColor &bgcolor,
307                         const std::string &type, const std::vector<std::string> &params,
308                         bool &clouds);
309         void setClouds(RemotePlayer *player, const CloudParams &params);
310
311         bool overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness);
312
313         /* con::PeerHandler implementation. */
314         void peerAdded(con::Peer *peer);
315         void deletingPeer(con::Peer *peer, bool timeout);
316
317         void DenySudoAccess(session_t peer_id);
318         void DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
319                 const std::string &str_reason = "", bool reconnect = false);
320         void DenyAccess(session_t peer_id, AccessDeniedCode reason,
321                 const std::string &custom_reason = "");
322         void acceptAuth(session_t peer_id, bool forSudoMode);
323         void DenyAccess_Legacy(session_t peer_id, const std::wstring &reason);
324         void DisconnectPeer(session_t peer_id);
325         bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval);
326         bool getClientInfo(session_t peer_id, ClientState *state, u32 *uptime,
327                         u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch,
328                         std::string* vers_string);
329
330         void printToConsoleOnly(const std::string &text);
331
332         void SendPlayerHPOrDie(PlayerSAO *player, const PlayerHPChangeReason &reason);
333         void SendPlayerBreath(PlayerSAO *sao);
334         void SendInventory(PlayerSAO* playerSAO);
335         void SendMovePlayer(session_t peer_id);
336
337         virtual bool registerModStorage(ModMetadata *storage);
338         virtual void unregisterModStorage(const std::string &name);
339
340         bool joinModChannel(const std::string &channel);
341         bool leaveModChannel(const std::string &channel);
342         bool sendModChannelMessage(const std::string &channel, const std::string &message);
343         ModChannel *getModChannel(const std::string &channel);
344
345         // Bind address
346         Address m_bind_addr;
347
348         // Environment mutex (envlock)
349         std::mutex m_env_mutex;
350
351 private:
352         friend class EmergeThread;
353         friend class RemoteClient;
354         friend class TestServerShutdownState;
355
356         struct ShutdownState {
357                 friend class TestServerShutdownState;
358                 public:
359                         bool is_requested = false;
360                         bool should_reconnect = false;
361                         std::string message;
362
363                         void reset();
364                         void trigger(float delay, const std::string &msg, bool reconnect);
365                         void tick(float dtime, Server *server);
366                         std::wstring getShutdownTimerMessage() const;
367                         bool isTimerRunning() const { return m_timer > 0.0f; }
368                 private:
369                         float m_timer = 0.0f;
370         };
371
372         void SendMovement(session_t peer_id);
373         void SendHP(session_t peer_id, u16 hp);
374         void SendBreath(session_t peer_id, u16 breath);
375         void SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
376                 const std::string &custom_reason, bool reconnect = false);
377         void SendAccessDenied_Legacy(session_t peer_id, const std::wstring &reason);
378         void SendDeathscreen(session_t peer_id, bool set_camera_point_target,
379                 v3f camera_point_target);
380         void SendItemDef(session_t peer_id, IItemDefManager *itemdef, u16 protocol_version);
381         void SendNodeDef(session_t peer_id, const NodeDefManager *nodedef,
382                 u16 protocol_version);
383
384         /* mark blocks not sent for all clients */
385         void SetBlocksNotSent(std::map<v3s16, MapBlock *>& block);
386
387
388         virtual void SendChatMessage(session_t peer_id, const ChatMessage &message);
389         void SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed);
390         void SendPlayerHP(session_t peer_id);
391
392         void SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
393                 f32 animation_speed);
394         void SendEyeOffset(session_t peer_id, v3f first, v3f third);
395         void SendPlayerPrivileges(session_t peer_id);
396         void SendPlayerInventoryFormspec(session_t peer_id);
397         void SendPlayerFormspecPrepend(session_t peer_id);
398         void SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
399                 const std::string &formname);
400         void SendHUDAdd(session_t peer_id, u32 id, HudElement *form);
401         void SendHUDRemove(session_t peer_id, u32 id);
402         void SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value);
403         void SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask);
404         void SendHUDSetParam(session_t peer_id, u16 param, const std::string &value);
405         void SendSetSky(session_t peer_id, const video::SColor &bgcolor,
406                         const std::string &type, const std::vector<std::string> &params,
407                         bool &clouds);
408         void SendCloudParams(session_t peer_id, const CloudParams &params);
409         void SendOverrideDayNightRatio(session_t peer_id, bool do_override, float ratio);
410         void broadcastModChannelMessage(const std::string &channel,
411                         const std::string &message, session_t from_peer);
412
413         /*
414                 Send a node removal/addition event to all clients except ignore_id.
415                 Additionally, if far_players!=NULL, players further away than
416                 far_d_nodes are ignored and their peer_ids are added to far_players
417         */
418         // Envlock and conlock should be locked when calling these
419         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
420                         std::vector<u16> *far_players=NULL, float far_d_nodes=100);
421         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
422                         std::vector<u16> *far_players=NULL, float far_d_nodes=100,
423                         bool remove_metadata=true);
424
425         // Environment and Connection must be locked when called
426         void SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver, u16 net_proto_version);
427
428         // Sends blocks to clients (locks env and con on its own)
429         void SendBlocks(float dtime);
430
431         void fillMediaCache();
432         void sendMediaAnnouncement(session_t peer_id, const std::string &lang_code);
433         void sendRequestedMedia(session_t peer_id,
434                         const std::vector<std::string> &tosend);
435
436         void sendDetachedInventory(const std::string &name, session_t peer_id);
437         void sendDetachedInventories(session_t peer_id);
438
439         // Adds a ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all)
440         void SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
441                 u16 amount, float spawntime,
442                 v3f minpos, v3f maxpos,
443                 v3f minvel, v3f maxvel,
444                 v3f minacc, v3f maxacc,
445                 float minexptime, float maxexptime,
446                 float minsize, float maxsize,
447                 bool collisiondetection, bool collision_removal,
448                 u16 attached_id,
449                 bool vertical, const std::string &texture, u32 id,
450                 const struct TileAnimationParams &animation, u8 glow);
451
452         void SendDeleteParticleSpawner(session_t peer_id, u32 id);
453
454         // Spawns particle on peer with peer_id (PEER_ID_INEXISTENT == all)
455         void SendSpawnParticle(session_t peer_id, u16 protocol_version,
456                 v3f pos, v3f velocity, v3f acceleration,
457                 float expirationtime, float size,
458                 bool collisiondetection, bool collision_removal,
459                 bool vertical, const std::string &texture,
460                 const struct TileAnimationParams &animation, u8 glow);
461
462         u32 SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas);
463         void SendActiveObjectMessages(session_t peer_id, const std::string &datas,
464                 bool reliable = true);
465         void SendCSMFlavourLimits(session_t peer_id);
466
467         /*
468                 Something random
469         */
470
471         void DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason);
472         void RespawnPlayer(session_t peer_id);
473         void DeleteClient(session_t peer_id, ClientDeletionReason reason);
474         void UpdateCrafting(RemotePlayer *player);
475         bool checkInteractDistance(RemotePlayer *player, const f32 d, const std::string what);
476
477         void handleChatInterfaceEvent(ChatEvent *evt);
478
479         // This returns the answer to the sender of wmessage, or "" if there is none
480         std::wstring handleChat(const std::string &name, const std::wstring &wname,
481                 std::wstring wmessage_input,
482                 bool check_shout_priv = false,
483                 RemotePlayer *player = NULL);
484         void handleAdminChat(const ChatEventChat *evt);
485
486         // When called, connection mutex should be locked
487         RemoteClient* getClient(session_t peer_id, ClientState state_min = CS_Active);
488         RemoteClient* getClientNoEx(session_t peer_id, ClientState state_min = CS_Active);
489
490         // When called, environment mutex should be locked
491         std::string getPlayerName(session_t peer_id);
492         PlayerSAO *getPlayerSAO(session_t peer_id);
493
494         /*
495                 Get a player from memory or creates one.
496                 If player is already connected, return NULL
497                 Does not verify/modify auth info and password.
498
499                 Call with env and con locked.
500         */
501         PlayerSAO *emergePlayer(const char *name, session_t peer_id, u16 proto_version);
502
503         void handlePeerChanges();
504
505         /*
506                 Variables
507         */
508
509         // World directory
510         std::string m_path_world;
511         // Subgame specification
512         SubgameSpec m_gamespec;
513         // If true, do not allow multiple players and hide some multiplayer
514         // functionality
515         bool m_simple_singleplayer_mode;
516         u16 m_max_chatmessage_length;
517         // For "dedicated" server list flag
518         bool m_dedicated;
519
520         // Thread can set; step() will throw as ServerError
521         MutexedVariable<std::string> m_async_fatal_error;
522
523         // Some timers
524         float m_liquid_transform_timer = 0.0f;
525         float m_liquid_transform_every = 1.0f;
526         float m_masterserver_timer = 0.0f;
527         float m_emergethread_trigger_timer = 0.0f;
528         float m_savemap_timer = 0.0f;
529         IntervalLimiter m_map_timer_and_unload_interval;
530
531         // Environment
532         ServerEnvironment *m_env = nullptr;
533
534         // server connection
535         std::shared_ptr<con::Connection> m_con;
536
537         // Ban checking
538         BanManager *m_banmanager = nullptr;
539
540         // Rollback manager (behind m_env_mutex)
541         IRollbackManager *m_rollback = nullptr;
542
543         // Emerge manager
544         EmergeManager *m_emerge = nullptr;
545
546         // Scripting
547         // Envlock and conlock should be locked when using Lua
548         ServerScripting *m_script = nullptr;
549
550         // Item definition manager
551         IWritableItemDefManager *m_itemdef;
552
553         // Node definition manager
554         NodeDefManager *m_nodedef;
555
556         // Craft definition manager
557         IWritableCraftDefManager *m_craftdef;
558
559         // Event manager
560         EventManager *m_event;
561
562         // Mods
563         std::unique_ptr<ServerModManager> m_modmgr;
564
565         /*
566                 Threads
567         */
568
569         // A buffer for time steps
570         // step() increments and AsyncRunStep() run by m_thread reads it.
571         float m_step_dtime = 0.0f;
572         std::mutex m_step_dtime_mutex;
573
574         // current server step lag counter
575         float m_lag;
576
577         // The server mainly operates in this thread
578         ServerThread *m_thread = nullptr;
579
580         /*
581                 Time related stuff
582         */
583
584         // Timer for sending time of day over network
585         float m_time_of_day_send_timer = 0.0f;
586         // Uptime of server in seconds
587         MutexedVariable<double> m_uptime;
588         /*
589          Client interface
590          */
591         ClientInterface m_clients;
592
593         /*
594                 Peer change queue.
595                 Queues stuff from peerAdded() and deletingPeer() to
596                 handlePeerChanges()
597         */
598         std::queue<con::PeerChange> m_peer_change_queue;
599
600         std::unordered_map<session_t, std::string> m_formspec_state_data;
601
602         /*
603                 Random stuff
604         */
605
606         ShutdownState m_shutdown_state;
607
608         ChatInterface *m_admin_chat;
609         std::string m_admin_nick;
610
611         /*
612                 Map edit event queue. Automatically receives all map edits.
613                 The constructor of this class registers us to receive them through
614                 onMapEditEvent
615
616                 NOTE: Should these be moved to actually be members of
617                 ServerEnvironment?
618         */
619
620         /*
621                 Queue of map edits from the environment for sending to the clients
622                 This is behind m_env_mutex
623         */
624         std::queue<MapEditEvent*> m_unsent_map_edit_queue;
625         /*
626                 If a non-empty area, map edit events contained within are left
627                 unsent. Done at map generation time to speed up editing of the
628                 generated area, as it will be sent anyway.
629                 This is behind m_env_mutex
630         */
631         VoxelArea m_ignore_map_edit_events_area;
632
633         // media files known to server
634         std::unordered_map<std::string, MediaInfo> m_media;
635
636         /*
637                 Sounds
638         */
639         std::unordered_map<s32, ServerPlayingSound> m_playing_sounds;
640         s32 m_next_sound_id = 0;
641
642         /*
643                 Detached inventories (behind m_env_mutex)
644         */
645         // key = name
646         std::map<std::string, Inventory*> m_detached_inventories;
647         // value = "" (visible to all players) or player name
648         std::map<std::string, std::string> m_detached_inventories_player;
649
650         std::unordered_map<std::string, ModMetadata *> m_mod_storages;
651         float m_mod_storage_save_timer = 10.0f;
652
653         // CSM flavour limits byteflag
654         u64 m_csm_flavour_limits = CSMFlavourLimit::CSM_FL_NONE;
655         u32 m_csm_noderange_limit = 8;
656
657         // ModChannel manager
658         std::unique_ptr<ModChannelMgr> m_modchannel_mgr;
659 };
660
661 /*
662         Runs a simple dedicated server loop.
663
664         Shuts down when kill is set to true.
665 */
666 void dedicated_server_loop(Server &server, bool &kill);