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