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