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