]> git.lizzy.rs Git - minetest.git/blob - src/server.h
b9097120009329d132f0d2c536adca734621711f
[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
65 enum ClientDeletionReason {
66         CDR_LEAVE,
67         CDR_TIMEOUT,
68         CDR_DENY
69 };
70
71 struct MediaInfo
72 {
73         std::string path;
74         std::string sha1_digest;
75
76         MediaInfo(const std::string &path_="",
77                   const std::string &sha1_digest_=""):
78                 path(path_),
79                 sha1_digest(sha1_digest_)
80         {
81         }
82 };
83
84 struct ServerSoundParams
85 {
86         enum Type {
87                 SSP_LOCAL,
88                 SSP_POSITIONAL,
89                 SSP_OBJECT
90         } type = SSP_LOCAL;
91         float gain = 1.0f;
92         float fade = 0.0f;
93         float pitch = 1.0f;
94         bool loop = false;
95         float max_hear_distance = 32 * BS;
96         v3f pos;
97         u16 object = 0;
98         std::string to_player = "";
99
100         v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
101 };
102
103 struct ServerPlayingSound
104 {
105         ServerSoundParams params;
106         SimpleSoundSpec spec;
107         std::unordered_set<session_t> clients; // peer ids
108 };
109
110 class Server : public con::PeerHandler, public MapEventReceiver,
111                 public InventoryManager, public IGameDef
112 {
113 public:
114         /*
115                 NOTE: Every public method should be thread-safe
116         */
117
118         Server(
119                 const std::string &path_world,
120                 const SubgameSpec &gamespec,
121                 bool simple_singleplayer_mode,
122                 Address bind_addr,
123                 bool dedicated,
124                 ChatInterface *iface = nullptr
125         );
126         ~Server();
127         DISABLE_CLASS_COPY(Server);
128
129         void start();
130         void stop();
131         // This is mainly a way to pass the time to the server.
132         // Actual processing is done in an another thread.
133         void step(float dtime);
134         // This is run by ServerThread and does the actual processing
135         void AsyncRunStep(bool initial_step=false);
136         void Receive();
137         PlayerSAO* StageTwoClientInit(session_t peer_id);
138
139         /*
140          * Command Handlers
141          */
142
143         void handleCommand(NetworkPacket* pkt);
144
145         void handleCommand_Null(NetworkPacket* pkt) {};
146         void handleCommand_Deprecated(NetworkPacket* pkt);
147         void handleCommand_Init(NetworkPacket* pkt);
148         void handleCommand_Init2(NetworkPacket* pkt);
149         void handleCommand_ModChannelJoin(NetworkPacket *pkt);
150         void handleCommand_ModChannelLeave(NetworkPacket *pkt);
151         void handleCommand_ModChannelMsg(NetworkPacket *pkt);
152         void handleCommand_RequestMedia(NetworkPacket* pkt);
153         void handleCommand_ClientReady(NetworkPacket* pkt);
154         void handleCommand_GotBlocks(NetworkPacket* pkt);
155         void handleCommand_PlayerPos(NetworkPacket* pkt);
156         void handleCommand_DeletedBlocks(NetworkPacket* pkt);
157         void handleCommand_InventoryAction(NetworkPacket* pkt);
158         void handleCommand_ChatMessage(NetworkPacket* pkt);
159         void handleCommand_Damage(NetworkPacket* pkt);
160         void handleCommand_Password(NetworkPacket* pkt);
161         void handleCommand_PlayerItem(NetworkPacket* pkt);
162         void handleCommand_Respawn(NetworkPacket* pkt);
163         void handleCommand_Interact(NetworkPacket* pkt);
164         void handleCommand_RemovedSounds(NetworkPacket* pkt);
165         void handleCommand_NodeMetaFields(NetworkPacket* pkt);
166         void handleCommand_InventoryFields(NetworkPacket* pkt);
167         void handleCommand_FirstSrp(NetworkPacket* pkt);
168         void handleCommand_SrpBytesA(NetworkPacket* pkt);
169         void handleCommand_SrpBytesM(NetworkPacket* pkt);
170
171         void ProcessData(NetworkPacket *pkt);
172
173         void Send(NetworkPacket *pkt);
174         void Send(session_t peer_id, NetworkPacket *pkt);
175
176         // Helper for handleCommand_PlayerPos and handleCommand_Interact
177         void process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
178                 NetworkPacket *pkt);
179
180         // Both setter and getter need no envlock,
181         // can be called freely from threads
182         void setTimeOfDay(u32 time);
183
184         /*
185                 Shall be called with the environment locked.
186                 This is accessed by the map, which is inside the environment,
187                 so it shouldn't be a problem.
188         */
189         void onMapEditEvent(MapEditEvent *event);
190
191         /*
192                 Shall be called with the environment and the connection locked.
193         */
194         Inventory* getInventory(const InventoryLocation &loc);
195         void setInventoryModified(const InventoryLocation &loc, bool playerSend = true);
196
197         // Connection must be locked when called
198         std::wstring getStatusString();
199         inline double getUptime() const { return m_uptime.m_value; }
200
201         // read shutdown state
202         inline bool getShutdownRequested() const { return m_shutdown_requested; }
203
204         // request server to shutdown
205         void requestShutdown(const std::string &msg, bool reconnect, float delay = 0.0f);
206
207         // Returns -1 if failed, sound handle on success
208         // Envlock
209         s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
210         void stopSound(s32 handle);
211         void fadeSound(s32 handle, float step, float gain);
212
213         // Envlock
214         std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
215         bool checkPriv(const std::string &name, const std::string &priv);
216         void reportPrivsModified(const std::string &name=""); // ""=all
217         void reportInventoryFormspecModified(const std::string &name);
218
219         void setIpBanned(const std::string &ip, const std::string &name);
220         void unsetIpBanned(const std::string &ip_or_name);
221         std::string getBanDescription(const std::string &ip_or_name);
222
223         void notifyPlayer(const char *name, const std::wstring &msg);
224         void notifyPlayers(const std::wstring &msg);
225         void spawnParticle(const std::string &playername,
226                 v3f pos, v3f velocity, v3f acceleration,
227                 float expirationtime, float size,
228                 bool collisiondetection, bool collision_removal,
229                 bool vertical, const std::string &texture,
230                 const struct TileAnimationParams &animation, u8 glow);
231
232         u32 addParticleSpawner(u16 amount, float spawntime,
233                 v3f minpos, v3f maxpos,
234                 v3f minvel, v3f maxvel,
235                 v3f minacc, v3f maxacc,
236                 float minexptime, float maxexptime,
237                 float minsize, float maxsize,
238                 bool collisiondetection, bool collision_removal,
239                 ServerActiveObject *attached,
240                 bool vertical, const std::string &texture,
241                 const std::string &playername, const struct TileAnimationParams &animation,
242                 u8 glow);
243
244         void deleteParticleSpawner(const std::string &playername, u32 id);
245
246         // Creates or resets inventory
247         Inventory* createDetachedInventory(const std::string &name, const std::string &player="");
248
249         // Envlock and conlock should be locked when using scriptapi
250         ServerScripting *getScriptIface(){ return m_script; }
251
252         // actions: time-reversed list
253         // Return value: success/failure
254         bool rollbackRevertActions(const std::list<RollbackAction> &actions,
255                         std::list<std::string> *log);
256
257         // IGameDef interface
258         // Under envlock
259         virtual IItemDefManager* getItemDefManager();
260         virtual const NodeDefManager* getNodeDefManager();
261         virtual ICraftDefManager* getCraftDefManager();
262         virtual u16 allocateUnknownNodeId(const std::string &name);
263         virtual MtEventManager* getEventManager();
264         IRollbackManager *getRollbackManager() { return m_rollback; }
265         virtual EmergeManager *getEmergeManager() { return m_emerge; }
266
267         IWritableItemDefManager* getWritableItemDefManager();
268         NodeDefManager* getWritableNodeDefManager();
269         IWritableCraftDefManager* getWritableCraftDefManager();
270
271         virtual const std::vector<ModSpec> &getMods() const { return m_mods; }
272         virtual const ModSpec* getModSpec(const std::string &modname) const;
273         void getModNames(std::vector<std::string> &modlist);
274         std::string getBuiltinLuaPath();
275         virtual std::string getWorldPath() const { return m_path_world; }
276         virtual std::string getModStoragePath() const;
277
278         inline bool isSingleplayer()
279                         { return m_simple_singleplayer_mode; }
280
281         inline void setAsyncFatalError(const std::string &error)
282                         { m_async_fatal_error.set(error); }
283
284         bool showFormspec(const char *name, const std::string &formspec, const std::string &formname);
285         Map & getMap() { return m_env->getMap(); }
286         ServerEnvironment & getEnv() { return *m_env; }
287         v3f findSpawnPos();
288
289         u32 hudAdd(RemotePlayer *player, HudElement *element);
290         bool hudRemove(RemotePlayer *player, u32 id);
291         bool hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *value);
292         bool hudSetFlags(RemotePlayer *player, u32 flags, u32 mask);
293         bool hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount);
294         void hudSetHotbarImage(RemotePlayer *player, std::string name);
295         void hudSetHotbarSelectedImage(RemotePlayer *player, std::string name);
296
297         Address getPeerAddress(session_t peer_id);
298
299         void setLocalPlayerAnimations(RemotePlayer *player, v2s32 animation_frames[4],
300                         f32 frame_speed);
301         void setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third);
302
303         void setSky(RemotePlayer *player, const video::SColor &bgcolor,
304                         const std::string &type, const std::vector<std::string> &params,
305                         bool &clouds);
306         void setClouds(RemotePlayer *player, const CloudParams &params);
307
308         bool overrideDayNightRatio(RemotePlayer *player, bool do_override, float brightness);
309
310         /* con::PeerHandler implementation. */
311         void peerAdded(con::Peer *peer);
312         void deletingPeer(con::Peer *peer, bool timeout);
313
314         void DenySudoAccess(session_t peer_id);
315         void DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
316                 const std::string &str_reason = "", bool reconnect = false);
317         void DenyAccess(session_t peer_id, AccessDeniedCode reason,
318                 const std::string &custom_reason = "");
319         void acceptAuth(session_t peer_id, bool forSudoMode);
320         void DenyAccess_Legacy(session_t peer_id, const std::wstring &reason);
321         void DisconnectPeer(session_t peer_id);
322         bool getClientConInfo(session_t peer_id, con::rtt_stat_type type, float *retval);
323         bool getClientInfo(session_t peer_id, ClientState *state, u32 *uptime,
324                         u8* ser_vers, u16* prot_vers, u8* major, u8* minor, u8* patch,
325                         std::string* vers_string);
326
327         void printToConsoleOnly(const std::string &text);
328
329         void SendPlayerHPOrDie(PlayerSAO *player);
330         void SendPlayerBreath(PlayerSAO *sao);
331         void SendInventory(PlayerSAO* playerSAO);
332         void SendMovePlayer(session_t peer_id);
333
334         virtual bool registerModStorage(ModMetadata *storage);
335         virtual void unregisterModStorage(const std::string &name);
336
337         bool joinModChannel(const std::string &channel);
338         bool leaveModChannel(const std::string &channel);
339         bool sendModChannelMessage(const std::string &channel, const std::string &message);
340         ModChannel *getModChannel(const std::string &channel);
341
342         // Bind address
343         Address m_bind_addr;
344
345         // Environment mutex (envlock)
346         std::mutex m_env_mutex;
347
348 private:
349
350         friend class EmergeThread;
351         friend class RemoteClient;
352
353         void SendMovement(session_t peer_id);
354         void SendHP(session_t peer_id, u16 hp);
355         void SendBreath(session_t peer_id, u16 breath);
356         void SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
357                 const std::string &custom_reason, bool reconnect = false);
358         void SendAccessDenied_Legacy(session_t peer_id, const std::wstring &reason);
359         void SendDeathscreen(session_t peer_id, bool set_camera_point_target,
360                 v3f camera_point_target);
361         void SendItemDef(session_t peer_id, IItemDefManager *itemdef, u16 protocol_version);
362         void SendNodeDef(session_t peer_id, const NodeDefManager *nodedef,
363                 u16 protocol_version);
364
365         /* mark blocks not sent for all clients */
366         void SetBlocksNotSent(std::map<v3s16, MapBlock *>& block);
367
368
369         void SendChatMessage(session_t peer_id, const ChatMessage &message);
370         void SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed);
371         void SendPlayerHP(session_t peer_id);
372
373         void SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
374                 f32 animation_speed);
375         void SendEyeOffset(session_t peer_id, v3f first, v3f third);
376         void SendPlayerPrivileges(session_t peer_id);
377         void SendPlayerInventoryFormspec(session_t peer_id);
378         void SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
379                 const std::string &formname);
380         void SendHUDAdd(session_t peer_id, u32 id, HudElement *form);
381         void SendHUDRemove(session_t peer_id, u32 id);
382         void SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value);
383         void SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask);
384         void SendHUDSetParam(session_t peer_id, u16 param, const std::string &value);
385         void SendSetSky(session_t peer_id, const video::SColor &bgcolor,
386                         const std::string &type, const std::vector<std::string> &params,
387                         bool &clouds);
388         void SendCloudParams(session_t peer_id, const CloudParams &params);
389         void SendOverrideDayNightRatio(session_t peer_id, bool do_override, float ratio);
390         void broadcastModChannelMessage(const std::string &channel,
391                         const std::string &message, session_t from_peer);
392
393         /*
394                 Send a node removal/addition event to all clients except ignore_id.
395                 Additionally, if far_players!=NULL, players further away than
396                 far_d_nodes are ignored and their peer_ids are added to far_players
397         */
398         // Envlock and conlock should be locked when calling these
399         void sendRemoveNode(v3s16 p, u16 ignore_id=0,
400                         std::vector<u16> *far_players=NULL, float far_d_nodes=100);
401         void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
402                         std::vector<u16> *far_players=NULL, float far_d_nodes=100,
403                         bool remove_metadata=true);
404
405         // Environment and Connection must be locked when called
406         void SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver, u16 net_proto_version);
407
408         // Sends blocks to clients (locks env and con on its own)
409         void SendBlocks(float dtime);
410
411         void fillMediaCache();
412         void sendMediaAnnouncement(session_t peer_id, const std::string &lang_code);
413         void sendRequestedMedia(session_t peer_id,
414                         const std::vector<std::string> &tosend);
415
416         void sendDetachedInventory(const std::string &name, session_t peer_id);
417         void sendDetachedInventories(session_t peer_id);
418
419         // Adds a ParticleSpawner on peer with peer_id (PEER_ID_INEXISTENT == all)
420         void SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
421                 u16 amount, float spawntime,
422                 v3f minpos, v3f maxpos,
423                 v3f minvel, v3f maxvel,
424                 v3f minacc, v3f maxacc,
425                 float minexptime, float maxexptime,
426                 float minsize, float maxsize,
427                 bool collisiondetection, bool collision_removal,
428                 u16 attached_id,
429                 bool vertical, const std::string &texture, u32 id,
430                 const struct TileAnimationParams &animation, u8 glow);
431
432         void SendDeleteParticleSpawner(session_t peer_id, u32 id);
433
434         // Spawns particle on peer with peer_id (PEER_ID_INEXISTENT == all)
435         void SendSpawnParticle(session_t peer_id, u16 protocol_version,
436                 v3f pos, v3f velocity, v3f acceleration,
437                 float expirationtime, float size,
438                 bool collisiondetection, bool collision_removal,
439                 bool vertical, const std::string &texture,
440                 const struct TileAnimationParams &animation, u8 glow);
441
442         u32 SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas);
443         void SendActiveObjectMessages(session_t peer_id, const std::string &datas,
444                 bool reliable = true);
445         void SendCSMFlavourLimits(session_t peer_id);
446
447         /*
448                 Something random
449         */
450
451         void DiePlayer(session_t peer_id);
452         void RespawnPlayer(session_t peer_id);
453         void DeleteClient(session_t peer_id, ClientDeletionReason reason);
454         void UpdateCrafting(RemotePlayer *player);
455         bool checkInteractDistance(RemotePlayer *player, const f32 d, const std::string what);
456
457         void handleChatInterfaceEvent(ChatEvent *evt);
458
459         // This returns the answer to the sender of wmessage, or "" if there is none
460         std::wstring handleChat(const std::string &name, const std::wstring &wname,
461                 std::wstring wmessage_input,
462                 bool check_shout_priv = false,
463                 RemotePlayer *player = NULL);
464         void handleAdminChat(const ChatEventChat *evt);
465
466         // When called, connection mutex should be locked
467         RemoteClient* getClient(session_t peer_id, ClientState state_min = CS_Active);
468         RemoteClient* getClientNoEx(session_t peer_id, ClientState state_min = CS_Active);
469
470         // When called, environment mutex should be locked
471         std::string getPlayerName(session_t peer_id);
472         PlayerSAO *getPlayerSAO(session_t peer_id);
473
474         /*
475                 Get a player from memory or creates one.
476                 If player is already connected, return NULL
477                 Does not verify/modify auth info and password.
478
479                 Call with env and con locked.
480         */
481         PlayerSAO *emergePlayer(const char *name, session_t peer_id, u16 proto_version);
482
483         void handlePeerChanges();
484
485         /*
486                 Variables
487         */
488
489         // World directory
490         std::string m_path_world;
491         // Subgame specification
492         SubgameSpec m_gamespec;
493         // If true, do not allow multiple players and hide some multiplayer
494         // functionality
495         bool m_simple_singleplayer_mode;
496         u16 m_max_chatmessage_length;
497         // For "dedicated" server list flag
498         bool m_dedicated;
499
500         // Thread can set; step() will throw as ServerError
501         MutexedVariable<std::string> m_async_fatal_error;
502
503         // Some timers
504         float m_liquid_transform_timer = 0.0f;
505         float m_liquid_transform_every = 1.0f;
506         float m_masterserver_timer = 0.0f;
507         float m_emergethread_trigger_timer = 0.0f;
508         float m_savemap_timer = 0.0f;
509         IntervalLimiter m_map_timer_and_unload_interval;
510
511         // Environment
512         ServerEnvironment *m_env = nullptr;
513
514         // server connection
515         std::shared_ptr<con::Connection> m_con;
516
517         // Ban checking
518         BanManager *m_banmanager = nullptr;
519
520         // Rollback manager (behind m_env_mutex)
521         IRollbackManager *m_rollback = nullptr;
522         bool m_enable_rollback_recording = false; // Updated once in a while
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::vector<ModSpec> m_mods;
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);