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