7ed8a8bf4877303f8453e17cbb4e153e78bd58b5
[oweals/minetest.git] / src / server.cpp
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 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "threading/mutex_auto_lock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "serverscripting.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_abm.h"
51 #include "content_sao.h"
52 #include "mods.h"
53 #include "event_manager.h"
54 #include "serverlist.h"
55 #include "util/string.h"
56 #include "rollback.h"
57 #include "util/serialize.h"
58 #include "util/thread.h"
59 #include "defaultsettings.h"
60 #include "util/base64.h"
61 #include "util/sha1.h"
62 #include "util/hex.h"
63
64 class ClientNotFoundException : public BaseException
65 {
66 public:
67         ClientNotFoundException(const char *s):
68                 BaseException(s)
69         {}
70 };
71
72 class ServerThread : public Thread
73 {
74 public:
75
76         ServerThread(Server *server):
77                 Thread("Server"),
78                 m_server(server)
79         {}
80
81         void *run();
82
83 private:
84         Server *m_server;
85 };
86
87 void *ServerThread::run()
88 {
89         DSTACK(FUNCTION_NAME);
90         BEGIN_DEBUG_EXCEPTION_HANDLER
91
92         m_server->AsyncRunStep(true);
93
94         while (!stopRequested()) {
95                 try {
96                         //TimeTaker timer("AsyncRunStep() + Receive()");
97
98                         m_server->AsyncRunStep();
99
100                         m_server->Receive();
101
102                 } catch (con::NoIncomingDataException &e) {
103                 } catch (con::PeerNotFoundException &e) {
104                         infostream<<"Server: PeerNotFoundException"<<std::endl;
105                 } catch (ClientNotFoundException &e) {
106                 } catch (con::ConnectionBindFailed &e) {
107                         m_server->setAsyncFatalError(e.what());
108                 } catch (LuaError &e) {
109                         m_server->setAsyncFatalError(
110                                         "ServerThread::run Lua: " + std::string(e.what()));
111                 }
112         }
113
114         END_DEBUG_EXCEPTION_HANDLER
115
116         return NULL;
117 }
118
119 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
120 {
121         if(pos_exists) *pos_exists = false;
122         switch(type){
123         case SSP_LOCAL:
124                 return v3f(0,0,0);
125         case SSP_POSITIONAL:
126                 if(pos_exists) *pos_exists = true;
127                 return pos;
128         case SSP_OBJECT: {
129                 if(object == 0)
130                         return v3f(0,0,0);
131                 ServerActiveObject *sao = env->getActiveObject(object);
132                 if(!sao)
133                         return v3f(0,0,0);
134                 if(pos_exists) *pos_exists = true;
135                 return sao->getBasePosition(); }
136         }
137         return v3f(0,0,0);
138 }
139
140
141
142 /*
143         Server
144 */
145
146 Server::Server(
147                 const std::string &path_world,
148                 const SubgameSpec &gamespec,
149                 bool simple_singleplayer_mode,
150                 bool ipv6,
151                 bool dedicated,
152                 ChatInterface *iface
153         ):
154         m_path_world(path_world),
155         m_gamespec(gamespec),
156         m_simple_singleplayer_mode(simple_singleplayer_mode),
157         m_dedicated(dedicated),
158         m_async_fatal_error(""),
159         m_env(NULL),
160         m_con(PROTOCOL_ID,
161                         512,
162                         CONNECTION_TIMEOUT,
163                         ipv6,
164                         this),
165         m_banmanager(NULL),
166         m_rollback(NULL),
167         m_enable_rollback_recording(false),
168         m_emerge(NULL),
169         m_script(NULL),
170         m_itemdef(createItemDefManager()),
171         m_nodedef(createNodeDefManager()),
172         m_craftdef(createCraftDefManager()),
173         m_event(new EventManager()),
174         m_thread(NULL),
175         m_time_of_day_send_timer(0),
176         m_uptime(0),
177         m_clients(&m_con),
178         m_shutdown_requested(false),
179         m_shutdown_ask_reconnect(false),
180         m_admin_chat(iface),
181         m_ignore_map_edit_events(false),
182         m_ignore_map_edit_events_peer_id(0),
183         m_next_sound_id(0),
184         m_mod_storage_save_timer(10.0f)
185 {
186         m_liquid_transform_timer = 0.0;
187         m_liquid_transform_every = 1.0;
188         m_masterserver_timer = 0.0;
189         m_emergethread_trigger_timer = 0.0;
190         m_savemap_timer = 0.0;
191
192         m_step_dtime = 0.0;
193         m_lag = g_settings->getFloat("dedicated_server_step");
194
195         if(path_world == "")
196                 throw ServerError("Supplied empty world path");
197
198         if(!gamespec.isValid())
199                 throw ServerError("Supplied invalid gamespec");
200
201         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
202         if(m_simple_singleplayer_mode)
203                 infostream<<" in simple singleplayer mode"<<std::endl;
204         else
205                 infostream<<std::endl;
206         infostream<<"- world:  "<<m_path_world<<std::endl;
207         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
208
209         // Create world if it doesn't exist
210         if(!loadGameConfAndInitWorld(m_path_world, m_gamespec))
211                 throw ServerError("Failed to initialize world");
212
213         // Create server thread
214         m_thread = new ServerThread(this);
215
216         // Create emerge manager
217         m_emerge = new EmergeManager(this);
218
219         // Create ban manager
220         std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
221         m_banmanager = new BanManager(ban_path);
222
223         ServerModConfiguration modconf(m_path_world);
224         m_mods = modconf.getMods();
225         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
226         // complain about mods with unsatisfied dependencies
227         if (!modconf.isConsistent()) {
228                 modconf.printUnsatisfiedModsError();
229         }
230
231         Settings worldmt_settings;
232         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
233         worldmt_settings.readConfigFile(worldmt.c_str());
234         std::vector<std::string> names = worldmt_settings.getNames();
235         std::set<std::string> load_mod_names;
236         for(std::vector<std::string>::iterator it = names.begin();
237                 it != names.end(); ++it) {
238                 std::string name = *it;
239                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
240                         load_mod_names.insert(name.substr(9));
241         }
242         // complain about mods declared to be loaded, but not found
243         for(std::vector<ModSpec>::iterator it = m_mods.begin();
244                         it != m_mods.end(); ++it)
245                 load_mod_names.erase((*it).name);
246         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
247                         it != unsatisfied_mods.end(); ++it)
248                 load_mod_names.erase((*it).name);
249         if(!load_mod_names.empty()) {
250                 errorstream << "The following mods could not be found:";
251                 for(std::set<std::string>::iterator it = load_mod_names.begin();
252                         it != load_mod_names.end(); ++it)
253                         errorstream << " \"" << (*it) << "\"";
254                 errorstream << std::endl;
255         }
256
257         //lock environment
258         MutexAutoLock envlock(m_env_mutex);
259
260         // Create the Map (loads map_meta.txt, overriding configured mapgen params)
261         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
262
263         // Initialize scripting
264         infostream<<"Server: Initializing Lua"<<std::endl;
265
266         m_script = new ServerScripting(this);
267
268         m_script->loadMod(getBuiltinLuaPath() + DIR_DELIM "init.lua", BUILTIN_MOD_NAME);
269
270         // Print mods
271         infostream << "Server: Loading mods: ";
272         for (std::vector<ModSpec>::const_iterator i = m_mods.begin();
273                         i != m_mods.end(); ++i) {
274                 infostream << (*i).name << " ";
275         }
276         infostream << std::endl;
277         // Load and run "mod" scripts
278         for (std::vector<ModSpec>::const_iterator it = m_mods.begin();
279                         it != m_mods.end(); ++it) {
280                 const ModSpec &mod = *it;
281                 if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
282                         throw ModError("Error loading mod \"" + mod.name +
283                                 "\": Mod name does not follow naming conventions: "
284                                 "Only chararacters [a-z0-9_] are allowed.");
285                 }
286                 std::string script_path = mod.path + DIR_DELIM + "init.lua";
287                 infostream << "  [" << padStringRight(mod.name, 12) << "] [\""
288                                 << script_path << "\"]" << std::endl;
289                 m_script->loadMod(script_path, mod.name);
290         }
291
292         // Read Textures and calculate sha1 sums
293         fillMediaCache();
294
295         // Apply item aliases in the node definition manager
296         m_nodedef->updateAliases(m_itemdef);
297
298         // Apply texture overrides from texturepack/override.txt
299         std::string texture_path = g_settings->get("texture_path");
300         if (texture_path != "" && fs::IsDir(texture_path))
301                 m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt");
302
303         m_nodedef->setNodeRegistrationStatus(true);
304
305         // Perform pending node name resolutions
306         m_nodedef->runNodeResolveCallbacks();
307
308         // unmap node names for connected nodeboxes
309         m_nodedef->mapNodeboxConnections();
310
311         // init the recipe hashes to speed up crafting
312         m_craftdef->initHashes(this);
313
314         // Initialize Environment
315         m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
316
317         m_clients.setEnv(m_env);
318
319         if (!servermap->settings_mgr.makeMapgenParams())
320                 FATAL_ERROR("Couldn't create any mapgen type");
321
322         // Initialize mapgens
323         m_emerge->initMapgens(servermap->getMapgenParams());
324
325         m_enable_rollback_recording = g_settings->getBool("enable_rollback_recording");
326         if (m_enable_rollback_recording) {
327                 // Create rollback manager
328                 m_rollback = new RollbackManager(m_path_world, this);
329         }
330
331         // Give environment reference to scripting api
332         m_script->initializeEnvironment(m_env);
333
334         // Register us to receive map edit events
335         servermap->addEventReceiver(this);
336
337         // If file exists, load environment metadata
338         if (fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt")) {
339                 infostream << "Server: Loading environment metadata" << std::endl;
340                 m_env->loadMeta();
341         } else {
342                 m_env->loadDefaultMeta();
343         }
344
345         // Add some test ActiveBlockModifiers to environment
346         add_legacy_abms(m_env, m_nodedef);
347
348         m_liquid_transform_every = g_settings->getFloat("liquid_update");
349         m_max_chatmessage_length = g_settings->getU16("chat_message_max_size");
350 }
351
352 Server::~Server()
353 {
354         infostream<<"Server destructing"<<std::endl;
355
356         // Send shutdown message
357         SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
358
359         {
360                 MutexAutoLock envlock(m_env_mutex);
361
362                 // Execute script shutdown hooks
363                 m_script->on_shutdown();
364
365                 infostream << "Server: Saving players" << std::endl;
366                 m_env->saveLoadedPlayers();
367
368                 infostream << "Server: Kicking players" << std::endl;
369                 std::string kick_msg;
370                 bool reconnect = false;
371                 if (getShutdownRequested()) {
372                         reconnect = m_shutdown_ask_reconnect;
373                         kick_msg = m_shutdown_msg;
374                 }
375                 if (kick_msg == "") {
376                         kick_msg = g_settings->get("kick_msg_shutdown");
377                 }
378                 m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
379                         kick_msg, reconnect);
380
381                 infostream << "Server: Saving environment metadata" << std::endl;
382                 m_env->saveMeta();
383         }
384
385         // Stop threads
386         stop();
387         delete m_thread;
388
389         // stop all emerge threads before deleting players that may have
390         // requested blocks to be emerged
391         m_emerge->stopThreads();
392
393         // Delete things in the reverse order of creation
394         delete m_emerge;
395         delete m_env;
396         delete m_rollback;
397         delete m_banmanager;
398         delete m_event;
399         delete m_itemdef;
400         delete m_nodedef;
401         delete m_craftdef;
402
403         // Deinitialize scripting
404         infostream<<"Server: Deinitializing scripting"<<std::endl;
405         delete m_script;
406
407         // Delete detached inventories
408         for (std::map<std::string, Inventory*>::iterator
409                         i = m_detached_inventories.begin();
410                         i != m_detached_inventories.end(); ++i) {
411                 delete i->second;
412         }
413 }
414
415 void Server::start(Address bind_addr)
416 {
417         DSTACK(FUNCTION_NAME);
418
419         m_bind_addr = bind_addr;
420
421         infostream<<"Starting server on "
422                         << bind_addr.serializeString() <<"..."<<std::endl;
423
424         // Stop thread if already running
425         m_thread->stop();
426
427         // Initialize connection
428         m_con.SetTimeoutMs(30);
429         m_con.Serve(bind_addr);
430
431         // Start thread
432         m_thread->start();
433
434         // ASCII art for the win!
435         actionstream
436         <<"        .__               __                   __   "<<std::endl
437         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
438         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
439         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
440         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
441         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
442         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
443         actionstream<<"Server for gameid=\""<<m_gamespec.id
444                         <<"\" listening on "<<bind_addr.serializeString()<<":"
445                         <<bind_addr.getPort() << "."<<std::endl;
446 }
447
448 void Server::stop()
449 {
450         DSTACK(FUNCTION_NAME);
451
452         infostream<<"Server: Stopping and waiting threads"<<std::endl;
453
454         // Stop threads (set run=false first so both start stopping)
455         m_thread->stop();
456         //m_emergethread.setRun(false);
457         m_thread->wait();
458         //m_emergethread.stop();
459
460         infostream<<"Server: Threads stopped"<<std::endl;
461 }
462
463 void Server::step(float dtime)
464 {
465         DSTACK(FUNCTION_NAME);
466         // Limit a bit
467         if (dtime > 2.0)
468                 dtime = 2.0;
469         {
470                 MutexAutoLock lock(m_step_dtime_mutex);
471                 m_step_dtime += dtime;
472         }
473         // Throw if fatal error occurred in thread
474         std::string async_err = m_async_fatal_error.get();
475         if (!async_err.empty()) {
476                 if (!m_simple_singleplayer_mode) {
477                         m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
478                                 g_settings->get("kick_msg_crash"),
479                                 g_settings->getBool("ask_reconnect_on_crash"));
480                 }
481                 throw ServerError("AsyncErr: " + async_err);
482         }
483 }
484
485 void Server::AsyncRunStep(bool initial_step)
486 {
487         DSTACK(FUNCTION_NAME);
488
489         g_profiler->add("Server::AsyncRunStep (num)", 1);
490
491         float dtime;
492         {
493                 MutexAutoLock lock1(m_step_dtime_mutex);
494                 dtime = m_step_dtime;
495         }
496
497         {
498                 // Send blocks to clients
499                 SendBlocks(dtime);
500         }
501
502         if((dtime < 0.001) && (initial_step == false))
503                 return;
504
505         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
506
507         //infostream<<"Server steps "<<dtime<<std::endl;
508         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
509
510         {
511                 MutexAutoLock lock1(m_step_dtime_mutex);
512                 m_step_dtime -= dtime;
513         }
514
515         /*
516                 Update uptime
517         */
518         {
519                 m_uptime.set(m_uptime.get() + dtime);
520         }
521
522         handlePeerChanges();
523
524         /*
525                 Update time of day and overall game time
526         */
527         m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
528
529         /*
530                 Send to clients at constant intervals
531         */
532
533         m_time_of_day_send_timer -= dtime;
534         if(m_time_of_day_send_timer < 0.0) {
535                 m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
536                 u16 time = m_env->getTimeOfDay();
537                 float time_speed = g_settings->getFloat("time_speed");
538                 SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
539         }
540
541         {
542                 MutexAutoLock lock(m_env_mutex);
543                 // Figure out and report maximum lag to environment
544                 float max_lag = m_env->getMaxLagEstimate();
545                 max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
546                 if(dtime > max_lag){
547                         if(dtime > 0.1 && dtime > max_lag * 2.0)
548                                 infostream<<"Server: Maximum lag peaked to "<<dtime
549                                                 <<" s"<<std::endl;
550                         max_lag = dtime;
551                 }
552                 m_env->reportMaxLagEstimate(max_lag);
553                 // Step environment
554                 ScopeProfiler sp(g_profiler, "SEnv step");
555                 ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
556                 m_env->step(dtime);
557         }
558
559         static const float map_timer_and_unload_dtime = 2.92;
560         if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
561         {
562                 MutexAutoLock lock(m_env_mutex);
563                 // Run Map's timers and unload unused data
564                 ScopeProfiler sp(g_profiler, "Server: map timer and unload");
565                 m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
566                         g_settings->getFloat("server_unload_unused_data_timeout"),
567                         U32_MAX);
568         }
569
570         /*
571                 Listen to the admin chat, if available
572         */
573         if (m_admin_chat) {
574                 if (!m_admin_chat->command_queue.empty()) {
575                         MutexAutoLock lock(m_env_mutex);
576                         while (!m_admin_chat->command_queue.empty()) {
577                                 ChatEvent *evt = m_admin_chat->command_queue.pop_frontNoEx();
578                                 handleChatInterfaceEvent(evt);
579                                 delete evt;
580                         }
581                 }
582                 m_admin_chat->outgoing_queue.push_back(
583                         new ChatEventTimeInfo(m_env->getGameTime(), m_env->getTimeOfDay()));
584         }
585
586         /*
587                 Do background stuff
588         */
589
590         /* Transform liquids */
591         m_liquid_transform_timer += dtime;
592         if(m_liquid_transform_timer >= m_liquid_transform_every)
593         {
594                 m_liquid_transform_timer -= m_liquid_transform_every;
595
596                 MutexAutoLock lock(m_env_mutex);
597
598                 ScopeProfiler sp(g_profiler, "Server: liquid transform");
599
600                 std::map<v3s16, MapBlock*> modified_blocks;
601                 m_env->getMap().transformLiquids(modified_blocks);
602 #if 0
603                 /*
604                         Update lighting
605                 */
606                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
607                 ServerMap &map = ((ServerMap&)m_env->getMap());
608                 map.updateLighting(modified_blocks, lighting_modified_blocks);
609
610                 // Add blocks modified by lighting to modified_blocks
611                 for(core::map<v3s16, MapBlock*>::Iterator
612                                 i = lighting_modified_blocks.getIterator();
613                                 i.atEnd() == false; i++)
614                 {
615                         MapBlock *block = i.getNode()->getValue();
616                         modified_blocks.insert(block->getPos(), block);
617                 }
618 #endif
619                 /*
620                         Set the modified blocks unsent for all the clients
621                 */
622                 if(!modified_blocks.empty())
623                 {
624                         SetBlocksNotSent(modified_blocks);
625                 }
626         }
627         m_clients.step(dtime);
628
629         m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
630 #if USE_CURL
631         // send masterserver announce
632         {
633                 float &counter = m_masterserver_timer;
634                 if (!isSingleplayer() && (!counter || counter >= 300.0) &&
635                                 g_settings->getBool("server_announce")) {
636                         ServerList::sendAnnounce(counter ? ServerList::AA_UPDATE :
637                                                 ServerList::AA_START,
638                                         m_bind_addr.getPort(),
639                                         m_clients.getPlayerNames(),
640                                         m_uptime.get(),
641                                         m_env->getGameTime(),
642                                         m_lag,
643                                         m_gamespec.id,
644                                         Mapgen::getMapgenName(m_emerge->mgparams->mgtype),
645                                         m_mods,
646                                         m_dedicated);
647                         counter = 0.01;
648                 }
649                 counter += dtime;
650         }
651 #endif
652
653         /*
654                 Check added and deleted active objects
655         */
656         {
657                 //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
658                 MutexAutoLock envlock(m_env_mutex);
659
660                 m_clients.lock();
661                 UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
662                 ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
663
664                 // Radius inside which objects are active
665                 static const s16 radius =
666                         g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
667
668                 // Radius inside which players are active
669                 static const bool is_transfer_limited =
670                         g_settings->exists("unlimited_player_transfer_distance") &&
671                         !g_settings->getBool("unlimited_player_transfer_distance");
672                 static const s16 player_transfer_dist = g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
673                 s16 player_radius = player_transfer_dist;
674                 if (player_radius == 0 && is_transfer_limited)
675                         player_radius = radius;
676
677                 for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
678                         i != clients.end(); ++i) {
679                         RemoteClient *client = i->second;
680
681                         // If definitions and textures have not been sent, don't
682                         // send objects either
683                         if (client->getState() < CS_DefinitionsSent)
684                                 continue;
685
686                         RemotePlayer *player = m_env->getPlayer(client->peer_id);
687                         if (player == NULL) {
688                                 // This can happen if the client timeouts somehow
689                                 /*warningstream<<FUNCTION_NAME<<": Client "
690                                                 <<client->peer_id
691                                                 <<" has no associated player"<<std::endl;*/
692                                 continue;
693                         }
694
695                         PlayerSAO *playersao = player->getPlayerSAO();
696                         if (playersao == NULL)
697                                 continue;
698
699                         s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
700                         if (my_radius <= 0) my_radius = radius;
701                         //infostream << "Server: Active Radius " << my_radius << std::endl;
702
703                         std::queue<u16> removed_objects;
704                         std::queue<u16> added_objects;
705                         m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
706                                         client->m_known_objects, removed_objects);
707                         m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
708                                         client->m_known_objects, added_objects);
709
710                         // Ignore if nothing happened
711                         if (removed_objects.empty() && added_objects.empty()) {
712                                 continue;
713                         }
714
715                         std::string data_buffer;
716
717                         char buf[4];
718
719                         // Handle removed objects
720                         writeU16((u8*)buf, removed_objects.size());
721                         data_buffer.append(buf, 2);
722                         while (!removed_objects.empty()) {
723                                 // Get object
724                                 u16 id = removed_objects.front();
725                                 ServerActiveObject* obj = m_env->getActiveObject(id);
726
727                                 // Add to data buffer for sending
728                                 writeU16((u8*)buf, id);
729                                 data_buffer.append(buf, 2);
730
731                                 // Remove from known objects
732                                 client->m_known_objects.erase(id);
733
734                                 if(obj && obj->m_known_by_count > 0)
735                                         obj->m_known_by_count--;
736                                 removed_objects.pop();
737                         }
738
739                         // Handle added objects
740                         writeU16((u8*)buf, added_objects.size());
741                         data_buffer.append(buf, 2);
742                         while (!added_objects.empty()) {
743                                 // Get object
744                                 u16 id = added_objects.front();
745                                 ServerActiveObject* obj = m_env->getActiveObject(id);
746
747                                 // Get object type
748                                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
749                                 if(obj == NULL)
750                                         warningstream<<FUNCTION_NAME
751                                                         <<": NULL object"<<std::endl;
752                                 else
753                                         type = obj->getSendType();
754
755                                 // Add to data buffer for sending
756                                 writeU16((u8*)buf, id);
757                                 data_buffer.append(buf, 2);
758                                 writeU8((u8*)buf, type);
759                                 data_buffer.append(buf, 1);
760
761                                 if(obj)
762                                         data_buffer.append(serializeLongString(
763                                                         obj->getClientInitializationData(client->net_proto_version)));
764                                 else
765                                         data_buffer.append(serializeLongString(""));
766
767                                 // Add to known objects
768                                 client->m_known_objects.insert(id);
769
770                                 if(obj)
771                                         obj->m_known_by_count++;
772
773                                 added_objects.pop();
774                         }
775
776                         u32 pktSize = SendActiveObjectRemoveAdd(client->peer_id, data_buffer);
777                         verbosestream << "Server: Sent object remove/add: "
778                                         << removed_objects.size() << " removed, "
779                                         << added_objects.size() << " added, "
780                                         << "packet size is " << pktSize << std::endl;
781                 }
782                 m_clients.unlock();
783
784                 m_mod_storage_save_timer -= dtime;
785                 if (m_mod_storage_save_timer <= 0.0f) {
786                         infostream << "Saving registered mod storages." << std::endl;
787                         m_mod_storage_save_timer = g_settings->getFloat("server_map_save_interval");
788                         for (UNORDERED_MAP<std::string, ModMetadata *>::const_iterator
789                                 it = m_mod_storages.begin(); it != m_mod_storages.end(); ++it) {
790                                 if (it->second->isModified()) {
791                                         it->second->save(getModStoragePath());
792                                 }
793                         }
794                 }
795         }
796
797         /*
798                 Send object messages
799         */
800         {
801                 MutexAutoLock envlock(m_env_mutex);
802                 ScopeProfiler sp(g_profiler, "Server: sending object messages");
803
804                 // Key = object id
805                 // Value = data sent by object
806                 UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* > buffered_messages;
807
808                 // Get active object messages from environment
809                 for(;;) {
810                         ActiveObjectMessage aom = m_env->getActiveObjectMessage();
811                         if (aom.id == 0)
812                                 break;
813
814                         std::vector<ActiveObjectMessage>* message_list = NULL;
815                         UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* >::iterator n;
816                         n = buffered_messages.find(aom.id);
817                         if (n == buffered_messages.end()) {
818                                 message_list = new std::vector<ActiveObjectMessage>;
819                                 buffered_messages[aom.id] = message_list;
820                         }
821                         else {
822                                 message_list = n->second;
823                         }
824                         message_list->push_back(aom);
825                 }
826
827                 m_clients.lock();
828                 UNORDERED_MAP<u16, RemoteClient*> clients = m_clients.getClientList();
829                 // Route data to every client
830                 for (UNORDERED_MAP<u16, RemoteClient*>::iterator i = clients.begin();
831                         i != clients.end(); ++i) {
832                         RemoteClient *client = i->second;
833                         std::string reliable_data;
834                         std::string unreliable_data;
835                         // Go through all objects in message buffer
836                         for (UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* >::iterator
837                                         j = buffered_messages.begin();
838                                         j != buffered_messages.end(); ++j) {
839                                 // If object is not known by client, skip it
840                                 u16 id = j->first;
841                                 if (client->m_known_objects.find(id) == client->m_known_objects.end())
842                                         continue;
843
844                                 // Get message list of object
845                                 std::vector<ActiveObjectMessage>* list = j->second;
846                                 // Go through every message
847                                 for (std::vector<ActiveObjectMessage>::iterator
848                                                 k = list->begin(); k != list->end(); ++k) {
849                                         // Compose the full new data with header
850                                         ActiveObjectMessage aom = *k;
851                                         std::string new_data;
852                                         // Add object id
853                                         char buf[2];
854                                         writeU16((u8*)&buf[0], aom.id);
855                                         new_data.append(buf, 2);
856                                         // Add data
857                                         new_data += serializeString(aom.datastring);
858                                         // Add data to buffer
859                                         if(aom.reliable)
860                                                 reliable_data += new_data;
861                                         else
862                                                 unreliable_data += new_data;
863                                 }
864                         }
865                         /*
866                                 reliable_data and unreliable_data are now ready.
867                                 Send them.
868                         */
869                         if(reliable_data.size() > 0) {
870                                 SendActiveObjectMessages(client->peer_id, reliable_data);
871                         }
872
873                         if(unreliable_data.size() > 0) {
874                                 SendActiveObjectMessages(client->peer_id, unreliable_data, false);
875                         }
876                 }
877                 m_clients.unlock();
878
879                 // Clear buffered_messages
880                 for (UNORDERED_MAP<u16, std::vector<ActiveObjectMessage>* >::iterator
881                                 i = buffered_messages.begin();
882                                 i != buffered_messages.end(); ++i) {
883                         delete i->second;
884                 }
885         }
886
887         /*
888                 Send queued-for-sending map edit events.
889         */
890         {
891                 // We will be accessing the environment
892                 MutexAutoLock lock(m_env_mutex);
893
894                 // Don't send too many at a time
895                 //u32 count = 0;
896
897                 // Single change sending is disabled if queue size is not small
898                 bool disable_single_change_sending = false;
899                 if(m_unsent_map_edit_queue.size() >= 4)
900                         disable_single_change_sending = true;
901
902                 int event_count = m_unsent_map_edit_queue.size();
903
904                 // We'll log the amount of each
905                 Profiler prof;
906
907                 while(m_unsent_map_edit_queue.size() != 0)
908                 {
909                         MapEditEvent* event = m_unsent_map_edit_queue.front();
910                         m_unsent_map_edit_queue.pop();
911
912                         // Players far away from the change are stored here.
913                         // Instead of sending the changes, MapBlocks are set not sent
914                         // for them.
915                         std::vector<u16> far_players;
916
917                         switch (event->type) {
918                         case MEET_ADDNODE:
919                         case MEET_SWAPNODE:
920                                 prof.add("MEET_ADDNODE", 1);
921                                 sendAddNode(event->p, event->n, event->already_known_by_peer,
922                                                 &far_players, disable_single_change_sending ? 5 : 30,
923                                                 event->type == MEET_ADDNODE);
924                                 break;
925                         case MEET_REMOVENODE:
926                                 prof.add("MEET_REMOVENODE", 1);
927                                 sendRemoveNode(event->p, event->already_known_by_peer,
928                                                 &far_players, disable_single_change_sending ? 5 : 30);
929                                 break;
930                         case MEET_BLOCK_NODE_METADATA_CHANGED:
931                                 infostream << "Server: MEET_BLOCK_NODE_METADATA_CHANGED" << std::endl;
932                                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
933                                                 setBlockNotSent(event->p);
934                                 break;
935                         case MEET_OTHER:
936                                 infostream << "Server: MEET_OTHER" << std::endl;
937                                 prof.add("MEET_OTHER", 1);
938                                 for(std::set<v3s16>::iterator
939                                                 i = event->modified_blocks.begin();
940                                                 i != event->modified_blocks.end(); ++i) {
941                                         setBlockNotSent(*i);
942                                 }
943                                 break;
944                         default:
945                                 prof.add("unknown", 1);
946                                 warningstream << "Server: Unknown MapEditEvent "
947                                                 << ((u32)event->type) << std::endl;
948                                 break;
949                         }
950
951                         /*
952                                 Set blocks not sent to far players
953                         */
954                         if(!far_players.empty()) {
955                                 // Convert list format to that wanted by SetBlocksNotSent
956                                 std::map<v3s16, MapBlock*> modified_blocks2;
957                                 for(std::set<v3s16>::iterator
958                                                 i = event->modified_blocks.begin();
959                                                 i != event->modified_blocks.end(); ++i) {
960                                         modified_blocks2[*i] =
961                                                         m_env->getMap().getBlockNoCreateNoEx(*i);
962                                 }
963
964                                 // Set blocks not sent
965                                 for(std::vector<u16>::iterator
966                                                 i = far_players.begin();
967                                                 i != far_players.end(); ++i) {
968                                         if(RemoteClient *client = getClient(*i))
969                                                 client->SetBlocksNotSent(modified_blocks2);
970                                 }
971                         }
972
973                         delete event;
974
975                         /*// Don't send too many at a time
976                         count++;
977                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
978                                 break;*/
979                 }
980
981                 if(event_count >= 5){
982                         infostream<<"Server: MapEditEvents:"<<std::endl;
983                         prof.print(infostream);
984                 } else if(event_count != 0){
985                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
986                         prof.print(verbosestream);
987                 }
988
989         }
990
991         /*
992                 Trigger emergethread (it somehow gets to a non-triggered but
993                 bysy state sometimes)
994         */
995         {
996                 float &counter = m_emergethread_trigger_timer;
997                 counter += dtime;
998                 if (counter >= 2.0) {
999                         counter = 0.0;
1000
1001                         m_emerge->startThreads();
1002                 }
1003         }
1004
1005         // Save map, players and auth stuff
1006         {
1007                 float &counter = m_savemap_timer;
1008                 counter += dtime;
1009                 static const float save_interval =
1010                         g_settings->getFloat("server_map_save_interval");
1011                 if (counter >= save_interval) {
1012                         counter = 0.0;
1013                         MutexAutoLock lock(m_env_mutex);
1014
1015                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1016
1017                         // Save ban file
1018                         if (m_banmanager->isModified()) {
1019                                 m_banmanager->save();
1020                         }
1021
1022                         // Save changed parts of map
1023                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1024
1025                         // Save players
1026                         m_env->saveLoadedPlayers();
1027
1028                         // Save environment metadata
1029                         m_env->saveMeta();
1030                 }
1031         }
1032 }
1033
1034 void Server::Receive()
1035 {
1036         DSTACK(FUNCTION_NAME);
1037         SharedBuffer<u8> data;
1038         u16 peer_id;
1039         try {
1040                 NetworkPacket pkt;
1041                 m_con.Receive(&pkt);
1042                 peer_id = pkt.getPeerId();
1043                 ProcessData(&pkt);
1044         }
1045         catch(con::InvalidIncomingDataException &e) {
1046                 infostream<<"Server::Receive(): "
1047                                 "InvalidIncomingDataException: what()="
1048                                 <<e.what()<<std::endl;
1049         }
1050         catch(SerializationError &e) {
1051                 infostream<<"Server::Receive(): "
1052                                 "SerializationError: what()="
1053                                 <<e.what()<<std::endl;
1054         }
1055         catch(ClientStateError &e) {
1056                 errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1057                 DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect."
1058                                 L"Try reconnecting or updating your client");
1059         }
1060         catch(con::PeerNotFoundException &e) {
1061                 // Do nothing
1062         }
1063 }
1064
1065 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1066 {
1067         std::string playername = "";
1068         PlayerSAO *playersao = NULL;
1069         m_clients.lock();
1070         try {
1071                 RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
1072                 if (client != NULL) {
1073                         playername = client->getName();
1074                         playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
1075                 }
1076         } catch (std::exception &e) {
1077                 m_clients.unlock();
1078                 throw;
1079         }
1080         m_clients.unlock();
1081
1082         RemotePlayer *player = m_env->getPlayer(playername.c_str());
1083
1084         // If failed, cancel
1085         if ((playersao == NULL) || (player == NULL)) {
1086                 if (player && player->peer_id != 0) {
1087                         actionstream << "Server: Failed to emerge player \"" << playername
1088                                         << "\" (player allocated to an another client)" << std::endl;
1089                         DenyAccess_Legacy(peer_id, L"Another client is connected with this "
1090                                         L"name. If your client closed unexpectedly, try again in "
1091                                         L"a minute.");
1092                 } else {
1093                         errorstream << "Server: " << playername << ": Failed to emerge player"
1094                                         << std::endl;
1095                         DenyAccess_Legacy(peer_id, L"Could not allocate player.");
1096                 }
1097                 return NULL;
1098         }
1099
1100         /*
1101                 Send complete position information
1102         */
1103         SendMovePlayer(peer_id);
1104
1105         // Send privileges
1106         SendPlayerPrivileges(peer_id);
1107
1108         // Send inventory formspec
1109         SendPlayerInventoryFormspec(peer_id);
1110
1111         // Send inventory
1112         SendInventory(playersao);
1113
1114         // Send HP or death screen
1115         if (playersao->isDead())
1116                 SendDeathscreen(peer_id, false, v3f(0,0,0));
1117         else
1118                 SendPlayerHPOrDie(playersao);
1119
1120         // Send Breath
1121         SendPlayerBreath(playersao);
1122
1123         // Note things in chat if not in simple singleplayer mode
1124         if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) {
1125                 // Send information about server to player in chat
1126                 SendChatMessage(peer_id, getStatusString());
1127         }
1128         Address addr = getPeerAddress(player->peer_id);
1129         std::string ip_str = addr.serializeString();
1130         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1131         /*
1132                 Print out action
1133         */
1134         {
1135                 const std::vector<std::string> &names = m_clients.getPlayerNames();
1136
1137                 actionstream << player->getName() << " joins game. List of players: ";
1138
1139                 for (std::vector<std::string>::const_iterator i = names.begin();
1140                                 i != names.end(); ++i) {
1141                         actionstream << *i << " ";
1142                 }
1143
1144                 actionstream << player->getName() <<std::endl;
1145         }
1146         return playersao;
1147 }
1148
1149 inline void Server::handleCommand(NetworkPacket* pkt)
1150 {
1151         const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
1152         (this->*opHandle.handler)(pkt);
1153 }
1154
1155 void Server::ProcessData(NetworkPacket *pkt)
1156 {
1157         DSTACK(FUNCTION_NAME);
1158         // Environment is locked first.
1159         MutexAutoLock envlock(m_env_mutex);
1160
1161         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1162         u32 peer_id = pkt->getPeerId();
1163
1164         try {
1165                 Address address = getPeerAddress(peer_id);
1166                 std::string addr_s = address.serializeString();
1167
1168                 if(m_banmanager->isIpBanned(addr_s)) {
1169                         std::string ban_name = m_banmanager->getBanName(addr_s);
1170                         infostream << "Server: A banned client tried to connect from "
1171                                         << addr_s << "; banned name was "
1172                                         << ban_name << std::endl;
1173                         // This actually doesn't seem to transfer to the client
1174                         DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
1175                                         + utf8_to_wide(ban_name));
1176                         return;
1177                 }
1178         }
1179         catch(con::PeerNotFoundException &e) {
1180                 /*
1181                  * no peer for this packet found
1182                  * most common reason is peer timeout, e.g. peer didn't
1183                  * respond for some time, your server was overloaded or
1184                  * things like that.
1185                  */
1186                 infostream << "Server::ProcessData(): Canceling: peer "
1187                                 << peer_id << " not found" << std::endl;
1188                 return;
1189         }
1190
1191         try {
1192                 ToServerCommand command = (ToServerCommand) pkt->getCommand();
1193
1194                 // Command must be handled into ToServerCommandHandler
1195                 if (command >= TOSERVER_NUM_MSG_TYPES) {
1196                         infostream << "Server: Ignoring unknown command "
1197                                          << command << std::endl;
1198                         return;
1199                 }
1200
1201                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1202                         handleCommand(pkt);
1203                         return;
1204                 }
1205
1206                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1207
1208                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1209                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1210                                         " serialization format invalid or not initialized."
1211                                         " Skipping incoming command=" << command << std::endl;
1212                         return;
1213                 }
1214
1215                 /* Handle commands related to client startup */
1216                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1217                         handleCommand(pkt);
1218                         return;
1219                 }
1220
1221                 if (m_clients.getClientState(peer_id) < CS_Active) {
1222                         if (command == TOSERVER_PLAYERPOS) return;
1223
1224                         errorstream << "Got packet command: " << command << " for peer id "
1225                                         << peer_id << " but client isn't active yet. Dropping packet "
1226                                         << std::endl;
1227                         return;
1228                 }
1229
1230                 handleCommand(pkt);
1231         } catch (SendFailedException &e) {
1232                 errorstream << "Server::ProcessData(): SendFailedException: "
1233                                 << "what=" << e.what()
1234                                 << std::endl;
1235         } catch (PacketError &e) {
1236                 actionstream << "Server::ProcessData(): PacketError: "
1237                                 << "what=" << e.what()
1238                                 << std::endl;
1239         }
1240 }
1241
1242 void Server::setTimeOfDay(u32 time)
1243 {
1244         m_env->setTimeOfDay(time);
1245         m_time_of_day_send_timer = 0;
1246 }
1247
1248 void Server::onMapEditEvent(MapEditEvent *event)
1249 {
1250         if(m_ignore_map_edit_events)
1251                 return;
1252         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1253                 return;
1254         MapEditEvent *e = event->clone();
1255         m_unsent_map_edit_queue.push(e);
1256 }
1257
1258 Inventory* Server::getInventory(const InventoryLocation &loc)
1259 {
1260         switch (loc.type) {
1261         case InventoryLocation::UNDEFINED:
1262         case InventoryLocation::CURRENT_PLAYER:
1263                 break;
1264         case InventoryLocation::PLAYER:
1265         {
1266                 RemotePlayer *player = dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
1267                 if(!player)
1268                         return NULL;
1269                 PlayerSAO *playersao = player->getPlayerSAO();
1270                 if(!playersao)
1271                         return NULL;
1272                 return playersao->getInventory();
1273         }
1274                 break;
1275         case InventoryLocation::NODEMETA:
1276         {
1277                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1278                 if(!meta)
1279                         return NULL;
1280                 return meta->getInventory();
1281         }
1282                 break;
1283         case InventoryLocation::DETACHED:
1284         {
1285                 if(m_detached_inventories.count(loc.name) == 0)
1286                         return NULL;
1287                 return m_detached_inventories[loc.name];
1288         }
1289                 break;
1290         default:
1291                 sanity_check(false); // abort
1292                 break;
1293         }
1294         return NULL;
1295 }
1296 void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
1297 {
1298         switch(loc.type){
1299         case InventoryLocation::UNDEFINED:
1300                 break;
1301         case InventoryLocation::PLAYER:
1302         {
1303                 if (!playerSend)
1304                         return;
1305
1306                 RemotePlayer *player =
1307                         dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
1308
1309                 if (!player)
1310                         return;
1311
1312                 PlayerSAO *playersao = player->getPlayerSAO();
1313                 if(!playersao)
1314                         return;
1315
1316                 SendInventory(playersao);
1317         }
1318                 break;
1319         case InventoryLocation::NODEMETA:
1320         {
1321                 v3s16 blockpos = getNodeBlockPos(loc.p);
1322
1323                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1324                 if(block)
1325                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1326
1327                 setBlockNotSent(blockpos);
1328         }
1329                 break;
1330         case InventoryLocation::DETACHED:
1331         {
1332                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1333         }
1334                 break;
1335         default:
1336                 sanity_check(false); // abort
1337                 break;
1338         }
1339 }
1340
1341 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1342 {
1343         std::vector<u16> clients = m_clients.getClientIDs();
1344         m_clients.lock();
1345         // Set the modified blocks unsent for all the clients
1346         for (std::vector<u16>::iterator i = clients.begin();
1347                  i != clients.end(); ++i) {
1348                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1349                                 client->SetBlocksNotSent(block);
1350         }
1351         m_clients.unlock();
1352 }
1353
1354 void Server::peerAdded(con::Peer *peer)
1355 {
1356         DSTACK(FUNCTION_NAME);
1357         verbosestream<<"Server::peerAdded(): peer->id="
1358                         <<peer->id<<std::endl;
1359
1360         con::PeerChange c;
1361         c.type = con::PEER_ADDED;
1362         c.peer_id = peer->id;
1363         c.timeout = false;
1364         m_peer_change_queue.push(c);
1365 }
1366
1367 void Server::deletingPeer(con::Peer *peer, bool timeout)
1368 {
1369         DSTACK(FUNCTION_NAME);
1370         verbosestream<<"Server::deletingPeer(): peer->id="
1371                         <<peer->id<<", timeout="<<timeout<<std::endl;
1372
1373         m_clients.event(peer->id, CSE_Disconnect);
1374         con::PeerChange c;
1375         c.type = con::PEER_REMOVED;
1376         c.peer_id = peer->id;
1377         c.timeout = timeout;
1378         m_peer_change_queue.push(c);
1379 }
1380
1381 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1382 {
1383         *retval = m_con.getPeerStat(peer_id,type);
1384         if (*retval == -1) return false;
1385         return true;
1386 }
1387
1388 bool Server::getClientInfo(
1389                 u16          peer_id,
1390                 ClientState* state,
1391                 u32*         uptime,
1392                 u8*          ser_vers,
1393                 u16*         prot_vers,
1394                 u8*          major,
1395                 u8*          minor,
1396                 u8*          patch,
1397                 std::string* vers_string
1398         )
1399 {
1400         *state = m_clients.getClientState(peer_id);
1401         m_clients.lock();
1402         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1403
1404         if (client == NULL) {
1405                 m_clients.unlock();
1406                 return false;
1407         }
1408
1409         *uptime = client->uptime();
1410         *ser_vers = client->serialization_version;
1411         *prot_vers = client->net_proto_version;
1412
1413         *major = client->getMajor();
1414         *minor = client->getMinor();
1415         *patch = client->getPatch();
1416         *vers_string = client->getPatch();
1417
1418         m_clients.unlock();
1419
1420         return true;
1421 }
1422
1423 void Server::handlePeerChanges()
1424 {
1425         while(m_peer_change_queue.size() > 0)
1426         {
1427                 con::PeerChange c = m_peer_change_queue.front();
1428                 m_peer_change_queue.pop();
1429
1430                 verbosestream<<"Server: Handling peer change: "
1431                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1432                                 <<std::endl;
1433
1434                 switch(c.type)
1435                 {
1436                 case con::PEER_ADDED:
1437                         m_clients.CreateClient(c.peer_id);
1438                         break;
1439
1440                 case con::PEER_REMOVED:
1441                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1442                         break;
1443
1444                 default:
1445                         FATAL_ERROR("Invalid peer change event received!");
1446                         break;
1447                 }
1448         }
1449 }
1450
1451 void Server::printToConsoleOnly(const std::string &text)
1452 {
1453         if (m_admin_chat) {
1454                 m_admin_chat->outgoing_queue.push_back(
1455                         new ChatEventChat("", utf8_to_wide(text)));
1456         } else {
1457                 std::cout << text << std::endl;
1458         }
1459 }
1460
1461 void Server::Send(NetworkPacket* pkt)
1462 {
1463         m_clients.send(pkt->getPeerId(),
1464                 clientCommandFactoryTable[pkt->getCommand()].channel,
1465                 pkt,
1466                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1467 }
1468
1469 void Server::SendMovement(u16 peer_id)
1470 {
1471         DSTACK(FUNCTION_NAME);
1472         std::ostringstream os(std::ios_base::binary);
1473
1474         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1475
1476         pkt << g_settings->getFloat("movement_acceleration_default");
1477         pkt << g_settings->getFloat("movement_acceleration_air");
1478         pkt << g_settings->getFloat("movement_acceleration_fast");
1479         pkt << g_settings->getFloat("movement_speed_walk");
1480         pkt << g_settings->getFloat("movement_speed_crouch");
1481         pkt << g_settings->getFloat("movement_speed_fast");
1482         pkt << g_settings->getFloat("movement_speed_climb");
1483         pkt << g_settings->getFloat("movement_speed_jump");
1484         pkt << g_settings->getFloat("movement_liquid_fluidity");
1485         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1486         pkt << g_settings->getFloat("movement_liquid_sink");
1487         pkt << g_settings->getFloat("movement_gravity");
1488
1489         Send(&pkt);
1490 }
1491
1492 void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
1493 {
1494         if (!g_settings->getBool("enable_damage"))
1495                 return;
1496
1497         u16 peer_id   = playersao->getPeerID();
1498         bool is_alive = playersao->getHP() > 0;
1499
1500         if (is_alive)
1501                 SendPlayerHP(peer_id);
1502         else
1503                 DiePlayer(peer_id);
1504 }
1505
1506 void Server::SendHP(u16 peer_id, u8 hp)
1507 {
1508         DSTACK(FUNCTION_NAME);
1509
1510         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1511         pkt << hp;
1512         Send(&pkt);
1513 }
1514
1515 void Server::SendBreath(u16 peer_id, u16 breath)
1516 {
1517         DSTACK(FUNCTION_NAME);
1518
1519         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1520         pkt << (u16) breath;
1521         Send(&pkt);
1522 }
1523
1524 void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
1525                 const std::string &custom_reason, bool reconnect)
1526 {
1527         assert(reason < SERVER_ACCESSDENIED_MAX);
1528
1529         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1530         pkt << (u8)reason;
1531         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1532                 pkt << custom_reason;
1533         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1534                         reason == SERVER_ACCESSDENIED_CRASH)
1535                 pkt << custom_reason << (u8)reconnect;
1536         Send(&pkt);
1537 }
1538
1539 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1540 {
1541         DSTACK(FUNCTION_NAME);
1542
1543         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1544         pkt << reason;
1545         Send(&pkt);
1546 }
1547
1548 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1549                 v3f camera_point_target)
1550 {
1551         DSTACK(FUNCTION_NAME);
1552
1553         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1554         pkt << set_camera_point_target << camera_point_target;
1555         Send(&pkt);
1556 }
1557
1558 void Server::SendItemDef(u16 peer_id,
1559                 IItemDefManager *itemdef, u16 protocol_version)
1560 {
1561         DSTACK(FUNCTION_NAME);
1562
1563         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1564
1565         /*
1566                 u16 command
1567                 u32 length of the next item
1568                 zlib-compressed serialized ItemDefManager
1569         */
1570         std::ostringstream tmp_os(std::ios::binary);
1571         itemdef->serialize(tmp_os, protocol_version);
1572         std::ostringstream tmp_os2(std::ios::binary);
1573         compressZlib(tmp_os.str(), tmp_os2);
1574         pkt.putLongString(tmp_os2.str());
1575
1576         // Make data buffer
1577         verbosestream << "Server: Sending item definitions to id(" << peer_id
1578                         << "): size=" << pkt.getSize() << std::endl;
1579
1580         Send(&pkt);
1581 }
1582
1583 void Server::SendNodeDef(u16 peer_id,
1584                 INodeDefManager *nodedef, u16 protocol_version)
1585 {
1586         DSTACK(FUNCTION_NAME);
1587
1588         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1589
1590         /*
1591                 u16 command
1592                 u32 length of the next item
1593                 zlib-compressed serialized NodeDefManager
1594         */
1595         std::ostringstream tmp_os(std::ios::binary);
1596         nodedef->serialize(tmp_os, protocol_version);
1597         std::ostringstream tmp_os2(std::ios::binary);
1598         compressZlib(tmp_os.str(), tmp_os2);
1599
1600         pkt.putLongString(tmp_os2.str());
1601
1602         // Make data buffer
1603         verbosestream << "Server: Sending node definitions to id(" << peer_id
1604                         << "): size=" << pkt.getSize() << std::endl;
1605
1606         Send(&pkt);
1607 }
1608
1609 /*
1610         Non-static send methods
1611 */
1612
1613 void Server::SendInventory(PlayerSAO* playerSAO)
1614 {
1615         DSTACK(FUNCTION_NAME);
1616
1617         UpdateCrafting(playerSAO->getPlayer());
1618
1619         /*
1620                 Serialize it
1621         */
1622
1623         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1624
1625         std::ostringstream os;
1626         playerSAO->getInventory()->serialize(os);
1627
1628         std::string s = os.str();
1629
1630         pkt.putRawString(s.c_str(), s.size());
1631         Send(&pkt);
1632 }
1633
1634 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
1635 {
1636         DSTACK(FUNCTION_NAME);
1637
1638         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1639         pkt << message;
1640
1641         if (peer_id != PEER_ID_INEXISTENT) {
1642                 Send(&pkt);
1643         }
1644         else {
1645                 m_clients.sendToAll(&pkt);
1646         }
1647 }
1648
1649 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1650                                      const std::string &formname)
1651 {
1652         DSTACK(FUNCTION_NAME);
1653
1654         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1655         if (formspec == "" ){
1656                 //the client should close the formspec
1657                 pkt.putLongString("");
1658         } else {
1659                 pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1660         }
1661         pkt << formname;
1662
1663         Send(&pkt);
1664 }
1665
1666 // Spawns a particle on peer with peer_id
1667 void Server::SendSpawnParticle(u16 peer_id, u16 protocol_version,
1668                                 v3f pos, v3f velocity, v3f acceleration,
1669                                 float expirationtime, float size, bool collisiondetection,
1670                                 bool collision_removal,
1671                                 bool vertical, const std::string &texture,
1672                                 const struct TileAnimationParams &animation, u8 glow)
1673 {
1674         DSTACK(FUNCTION_NAME);
1675         if (peer_id == PEER_ID_INEXISTENT) {
1676                 // This sucks and should be replaced by a better solution in a refactor:
1677                 std::vector<u16> clients = m_clients.getClientIDs();
1678                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
1679                         RemotePlayer *player = m_env->getPlayer(*i);
1680                         if (!player)
1681                                 continue;
1682                         SendSpawnParticle(*i, player->protocol_version,
1683                                         pos, velocity, acceleration,
1684                                         expirationtime, size, collisiondetection,
1685                                         collision_removal, vertical, texture, animation, glow);
1686                 }
1687                 return;
1688         }
1689
1690         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1691
1692         pkt << pos << velocity << acceleration << expirationtime
1693                         << size << collisiondetection;
1694         pkt.putLongString(texture);
1695         pkt << vertical;
1696         pkt << collision_removal;
1697         // This is horrible but required (why are there two ways to serialize pkts?)
1698         std::ostringstream os(std::ios_base::binary);
1699         animation.serialize(os, protocol_version);
1700         pkt.putRawString(os.str());
1701         pkt << glow;
1702
1703         Send(&pkt);
1704 }
1705
1706 // Adds a ParticleSpawner on peer with peer_id
1707 void Server::SendAddParticleSpawner(u16 peer_id, u16 protocol_version,
1708         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1709         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1710         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1711         u16 attached_id, bool vertical, const std::string &texture, u32 id,
1712         const struct TileAnimationParams &animation, u8 glow)
1713 {
1714         DSTACK(FUNCTION_NAME);
1715         if (peer_id == PEER_ID_INEXISTENT) {
1716                 // This sucks and should be replaced:
1717                 std::vector<u16> clients = m_clients.getClientIDs();
1718                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
1719                         RemotePlayer *player = m_env->getPlayer(*i);
1720                         if (!player)
1721                                 continue;
1722                         SendAddParticleSpawner(*i, player->protocol_version,
1723                                         amount, spawntime, minpos, maxpos,
1724                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1725                                         minsize, maxsize, collisiondetection, collision_removal,
1726                                         attached_id, vertical, texture, id, animation, glow);
1727                 }
1728                 return;
1729         }
1730
1731         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1732
1733         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1734                         << minacc << maxacc << minexptime << maxexptime << minsize
1735                         << maxsize << collisiondetection;
1736
1737         pkt.putLongString(texture);
1738
1739         pkt << id << vertical;
1740         pkt << collision_removal;
1741         pkt << attached_id;
1742         // This is horrible but required
1743         std::ostringstream os(std::ios_base::binary);
1744         animation.serialize(os, protocol_version);
1745         pkt.putRawString(os.str());
1746         pkt << glow;
1747
1748         Send(&pkt);
1749 }
1750
1751 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1752 {
1753         DSTACK(FUNCTION_NAME);
1754
1755         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1756
1757         // Ugly error in this packet
1758         pkt << (u16) id;
1759
1760         if (peer_id != PEER_ID_INEXISTENT) {
1761                 Send(&pkt);
1762         }
1763         else {
1764                 m_clients.sendToAll(&pkt);
1765         }
1766
1767 }
1768
1769 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1770 {
1771         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1772
1773         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1774                         << form->text << form->number << form->item << form->dir
1775                         << form->align << form->offset << form->world_pos << form->size;
1776
1777         Send(&pkt);
1778 }
1779
1780 void Server::SendHUDRemove(u16 peer_id, u32 id)
1781 {
1782         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1783         pkt << id;
1784         Send(&pkt);
1785 }
1786
1787 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1788 {
1789         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1790         pkt << id << (u8) stat;
1791
1792         switch (stat) {
1793                 case HUD_STAT_POS:
1794                 case HUD_STAT_SCALE:
1795                 case HUD_STAT_ALIGN:
1796                 case HUD_STAT_OFFSET:
1797                         pkt << *(v2f *) value;
1798                         break;
1799                 case HUD_STAT_NAME:
1800                 case HUD_STAT_TEXT:
1801                         pkt << *(std::string *) value;
1802                         break;
1803                 case HUD_STAT_WORLD_POS:
1804                         pkt << *(v3f *) value;
1805                         break;
1806                 case HUD_STAT_SIZE:
1807                         pkt << *(v2s32 *) value;
1808                         break;
1809                 case HUD_STAT_NUMBER:
1810                 case HUD_STAT_ITEM:
1811                 case HUD_STAT_DIR:
1812                 default:
1813                         pkt << *(u32 *) value;
1814                         break;
1815         }
1816
1817         Send(&pkt);
1818 }
1819
1820 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1821 {
1822         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1823
1824         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1825
1826         pkt << flags << mask;
1827
1828         Send(&pkt);
1829 }
1830
1831 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1832 {
1833         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1834         pkt << param << value;
1835         Send(&pkt);
1836 }
1837
1838 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1839                 const std::string &type, const std::vector<std::string> &params)
1840 {
1841         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1842         pkt << bgcolor << type << (u16) params.size();
1843
1844         for(size_t i=0; i<params.size(); i++)
1845                 pkt << params[i];
1846
1847         Send(&pkt);
1848 }
1849
1850 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1851                 float ratio)
1852 {
1853         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1854                         1 + 2, peer_id);
1855
1856         pkt << do_override << (u16) (ratio * 65535);
1857
1858         Send(&pkt);
1859 }
1860
1861 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1862 {
1863         DSTACK(FUNCTION_NAME);
1864
1865         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1866         pkt << time << time_speed;
1867
1868         if (peer_id == PEER_ID_INEXISTENT) {
1869                 m_clients.sendToAll(&pkt);
1870         }
1871         else {
1872                 Send(&pkt);
1873         }
1874 }
1875
1876 void Server::SendPlayerHP(u16 peer_id)
1877 {
1878         DSTACK(FUNCTION_NAME);
1879         PlayerSAO *playersao = getPlayerSAO(peer_id);
1880         // In some rare case if the player is disconnected
1881         // while Lua call l_punch, for example, this can be NULL
1882         if (!playersao)
1883                 return;
1884
1885         SendHP(peer_id, playersao->getHP());
1886         m_script->player_event(playersao,"health_changed");
1887
1888         // Send to other clients
1889         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1890         ActiveObjectMessage aom(playersao->getId(), true, str);
1891         playersao->m_messages_out.push(aom);
1892 }
1893
1894 void Server::SendPlayerBreath(PlayerSAO *sao)
1895 {
1896         DSTACK(FUNCTION_NAME);
1897         assert(sao);
1898
1899         m_script->player_event(sao, "breath_changed");
1900         SendBreath(sao->getPeerID(), sao->getBreath());
1901 }
1902
1903 void Server::SendMovePlayer(u16 peer_id)
1904 {
1905         DSTACK(FUNCTION_NAME);
1906         RemotePlayer *player = m_env->getPlayer(peer_id);
1907         assert(player);
1908         PlayerSAO *sao = player->getPlayerSAO();
1909         assert(sao);
1910
1911         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1912         pkt << sao->getBasePosition() << sao->getPitch() << sao->getYaw();
1913
1914         {
1915                 v3f pos = sao->getBasePosition();
1916                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1917                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1918                                 << " pitch=" << sao->getPitch()
1919                                 << " yaw=" << sao->getYaw()
1920                                 << std::endl;
1921         }
1922
1923         Send(&pkt);
1924 }
1925
1926 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1927 {
1928         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1929                 peer_id);
1930
1931         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1932                         << animation_frames[3] << animation_speed;
1933
1934         Send(&pkt);
1935 }
1936
1937 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1938 {
1939         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1940         pkt << first << third;
1941         Send(&pkt);
1942 }
1943 void Server::SendPlayerPrivileges(u16 peer_id)
1944 {
1945         RemotePlayer *player = m_env->getPlayer(peer_id);
1946         assert(player);
1947         if(player->peer_id == PEER_ID_INEXISTENT)
1948                 return;
1949
1950         std::set<std::string> privs;
1951         m_script->getAuth(player->getName(), NULL, &privs);
1952
1953         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1954         pkt << (u16) privs.size();
1955
1956         for(std::set<std::string>::const_iterator i = privs.begin();
1957                         i != privs.end(); ++i) {
1958                 pkt << (*i);
1959         }
1960
1961         Send(&pkt);
1962 }
1963
1964 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1965 {
1966         RemotePlayer *player = m_env->getPlayer(peer_id);
1967         assert(player);
1968         if(player->peer_id == PEER_ID_INEXISTENT)
1969                 return;
1970
1971         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1972         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1973         Send(&pkt);
1974 }
1975
1976 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
1977 {
1978         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1979         pkt.putRawString(datas.c_str(), datas.size());
1980         Send(&pkt);
1981         return pkt.getSize();
1982 }
1983
1984 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
1985 {
1986         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1987                         datas.size(), peer_id);
1988
1989         pkt.putRawString(datas.c_str(), datas.size());
1990
1991         m_clients.send(pkt.getPeerId(),
1992                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1993                         &pkt, reliable);
1994
1995 }
1996
1997 s32 Server::playSound(const SimpleSoundSpec &spec,
1998                 const ServerSoundParams &params)
1999 {
2000         // Find out initial position of sound
2001         bool pos_exists = false;
2002         v3f pos = params.getPos(m_env, &pos_exists);
2003         // If position is not found while it should be, cancel sound
2004         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
2005                 return -1;
2006
2007         // Filter destination clients
2008         std::vector<u16> dst_clients;
2009         if(params.to_player != "")
2010         {
2011                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
2012                 if(!player){
2013                         infostream<<"Server::playSound: Player \""<<params.to_player
2014                                         <<"\" not found"<<std::endl;
2015                         return -1;
2016                 }
2017                 if(player->peer_id == PEER_ID_INEXISTENT){
2018                         infostream<<"Server::playSound: Player \""<<params.to_player
2019                                         <<"\" not connected"<<std::endl;
2020                         return -1;
2021                 }
2022                 dst_clients.push_back(player->peer_id);
2023         }
2024         else {
2025                 std::vector<u16> clients = m_clients.getClientIDs();
2026
2027                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2028                         RemotePlayer *player = m_env->getPlayer(*i);
2029                         if (!player)
2030                                 continue;
2031
2032                         PlayerSAO *sao = player->getPlayerSAO();
2033                         if (!sao)
2034                                 continue;
2035
2036                         if (pos_exists) {
2037                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2038                                                 params.max_hear_distance)
2039                                         continue;
2040                         }
2041                         dst_clients.push_back(*i);
2042                 }
2043         }
2044
2045         if(dst_clients.empty())
2046                 return -1;
2047
2048         // Create the sound
2049         s32 id = m_next_sound_id++;
2050         // The sound will exist as a reference in m_playing_sounds
2051         m_playing_sounds[id] = ServerPlayingSound();
2052         ServerPlayingSound &psound = m_playing_sounds[id];
2053         psound.params = params;
2054
2055         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2056         pkt << id << spec.name << (float) (spec.gain * params.gain)
2057                         << (u8) params.type << pos << params.object << params.loop;
2058
2059         for(std::vector<u16>::iterator i = dst_clients.begin();
2060                         i != dst_clients.end(); ++i) {
2061                 psound.clients.insert(*i);
2062                 m_clients.send(*i, 0, &pkt, true);
2063         }
2064         return id;
2065 }
2066 void Server::stopSound(s32 handle)
2067 {
2068         // Get sound reference
2069         UNORDERED_MAP<s32, ServerPlayingSound>::iterator i = m_playing_sounds.find(handle);
2070         if (i == m_playing_sounds.end())
2071                 return;
2072         ServerPlayingSound &psound = i->second;
2073
2074         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2075         pkt << handle;
2076
2077         for (UNORDERED_SET<u16>::iterator i = psound.clients.begin();
2078                         i != psound.clients.end(); ++i) {
2079                 // Send as reliable
2080                 m_clients.send(*i, 0, &pkt, true);
2081         }
2082         // Remove sound reference
2083         m_playing_sounds.erase(i);
2084 }
2085
2086 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2087         std::vector<u16> *far_players, float far_d_nodes)
2088 {
2089         float maxd = far_d_nodes*BS;
2090         v3f p_f = intToFloat(p, BS);
2091
2092         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2093         pkt << p;
2094
2095         std::vector<u16> clients = m_clients.getClientIDs();
2096         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2097                 if (far_players) {
2098                         // Get player
2099                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2100                                 PlayerSAO *sao = player->getPlayerSAO();
2101                                 if (!sao)
2102                                         continue;
2103
2104                                 // If player is far away, only set modified blocks not sent
2105                                 v3f player_pos = sao->getBasePosition();
2106                                 if (player_pos.getDistanceFrom(p_f) > maxd) {
2107                                         far_players->push_back(*i);
2108                                         continue;
2109                                 }
2110                         }
2111                 }
2112
2113                 // Send as reliable
2114                 m_clients.send(*i, 0, &pkt, true);
2115         }
2116 }
2117
2118 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2119                 std::vector<u16> *far_players, float far_d_nodes,
2120                 bool remove_metadata)
2121 {
2122         float maxd = far_d_nodes*BS;
2123         v3f p_f = intToFloat(p, BS);
2124
2125         std::vector<u16> clients = m_clients.getClientIDs();
2126         for(std::vector<u16>::iterator i = clients.begin();     i != clients.end(); ++i) {
2127                 if (far_players) {
2128                         // Get player
2129                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2130                                 PlayerSAO *sao = player->getPlayerSAO();
2131                                 if (!sao)
2132                                         continue;
2133
2134                                 // If player is far away, only set modified blocks not sent
2135                                 v3f player_pos = sao->getBasePosition();
2136                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2137                                         far_players->push_back(*i);
2138                                         continue;
2139                                 }
2140                         }
2141                 }
2142
2143                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2144                 m_clients.lock();
2145                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2146                 if (client != 0) {
2147                         pkt << p << n.param0 << n.param1 << n.param2
2148                                         << (u8) (remove_metadata ? 0 : 1);
2149                 }
2150                 m_clients.unlock();
2151
2152                 // Send as reliable
2153                 if (pkt.getSize() > 0)
2154                         m_clients.send(*i, 0, &pkt, true);
2155         }
2156 }
2157
2158 void Server::setBlockNotSent(v3s16 p)
2159 {
2160         std::vector<u16> clients = m_clients.getClientIDs();
2161         m_clients.lock();
2162         for(std::vector<u16>::iterator i = clients.begin();
2163                 i != clients.end(); ++i) {
2164                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2165                 client->SetBlockNotSent(p);
2166         }
2167         m_clients.unlock();
2168 }
2169
2170 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2171 {
2172         DSTACK(FUNCTION_NAME);
2173
2174         v3s16 p = block->getPos();
2175
2176         /*
2177                 Create a packet with the block in the right format
2178         */
2179
2180         std::ostringstream os(std::ios_base::binary);
2181         block->serialize(os, ver, false);
2182         block->serializeNetworkSpecific(os);
2183         std::string s = os.str();
2184
2185         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2186
2187         pkt << p;
2188         pkt.putRawString(s.c_str(), s.size());
2189         Send(&pkt);
2190 }
2191
2192 void Server::SendBlocks(float dtime)
2193 {
2194         DSTACK(FUNCTION_NAME);
2195
2196         MutexAutoLock envlock(m_env_mutex);
2197         //TODO check if one big lock could be faster then multiple small ones
2198
2199         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2200
2201         std::vector<PrioritySortedBlockTransfer> queue;
2202
2203         s32 total_sending = 0;
2204
2205         {
2206                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2207
2208                 std::vector<u16> clients = m_clients.getClientIDs();
2209
2210                 m_clients.lock();
2211                 for(std::vector<u16>::iterator i = clients.begin();
2212                         i != clients.end(); ++i) {
2213                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2214
2215                         if (client == NULL)
2216                                 continue;
2217
2218                         total_sending += client->SendingCount();
2219                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2220                 }
2221                 m_clients.unlock();
2222         }
2223
2224         // Sort.
2225         // Lowest priority number comes first.
2226         // Lowest is most important.
2227         std::sort(queue.begin(), queue.end());
2228
2229         m_clients.lock();
2230         for(u32 i=0; i<queue.size(); i++)
2231         {
2232                 //TODO: Calculate limit dynamically
2233                 if(total_sending >= g_settings->getS32
2234                                 ("max_simultaneous_block_sends_server_total"))
2235                         break;
2236
2237                 PrioritySortedBlockTransfer q = queue[i];
2238
2239                 MapBlock *block = NULL;
2240                 try
2241                 {
2242                         block = m_env->getMap().getBlockNoCreate(q.pos);
2243                 }
2244                 catch(InvalidPositionException &e)
2245                 {
2246                         continue;
2247                 }
2248
2249                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2250
2251                 if(!client)
2252                         continue;
2253
2254                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2255
2256                 client->SentBlock(q.pos);
2257                 total_sending++;
2258         }
2259         m_clients.unlock();
2260 }
2261
2262 void Server::fillMediaCache()
2263 {
2264         DSTACK(FUNCTION_NAME);
2265
2266         infostream<<"Server: Calculating media file checksums"<<std::endl;
2267
2268         // Collect all media file paths
2269         std::vector<std::string> paths;
2270         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2271                         i != m_mods.end(); ++i) {
2272                 const ModSpec &mod = *i;
2273                 paths.push_back(mod.path + DIR_DELIM + "textures");
2274                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2275                 paths.push_back(mod.path + DIR_DELIM + "media");
2276                 paths.push_back(mod.path + DIR_DELIM + "models");
2277         }
2278         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2279
2280         // Collect media file information from paths into cache
2281         for(std::vector<std::string>::iterator i = paths.begin();
2282                         i != paths.end(); ++i) {
2283                 std::string mediapath = *i;
2284                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2285                 for (u32 j = 0; j < dirlist.size(); j++) {
2286                         if (dirlist[j].dir) // Ignode dirs
2287                                 continue;
2288                         std::string filename = dirlist[j].name;
2289                         // If name contains illegal characters, ignore the file
2290                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2291                                 infostream<<"Server: ignoring illegal file name: \""
2292                                                 << filename << "\"" << std::endl;
2293                                 continue;
2294                         }
2295                         // If name is not in a supported format, ignore it
2296                         const char *supported_ext[] = {
2297                                 ".png", ".jpg", ".bmp", ".tga",
2298                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2299                                 ".ogg",
2300                                 ".x", ".b3d", ".md2", ".obj",
2301                                 NULL
2302                         };
2303                         if (removeStringEnd(filename, supported_ext) == ""){
2304                                 infostream << "Server: ignoring unsupported file extension: \""
2305                                                 << filename << "\"" << std::endl;
2306                                 continue;
2307                         }
2308                         // Ok, attempt to load the file and add to cache
2309                         std::string filepath = mediapath + DIR_DELIM + filename;
2310                         // Read data
2311                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2312                         if (!fis.good()) {
2313                                 errorstream << "Server::fillMediaCache(): Could not open \""
2314                                                 << filename << "\" for reading" << std::endl;
2315                                 continue;
2316                         }
2317                         std::ostringstream tmp_os(std::ios_base::binary);
2318                         bool bad = false;
2319                         for(;;) {
2320                                 char buf[1024];
2321                                 fis.read(buf, 1024);
2322                                 std::streamsize len = fis.gcount();
2323                                 tmp_os.write(buf, len);
2324                                 if (fis.eof())
2325                                         break;
2326                                 if (!fis.good()) {
2327                                         bad = true;
2328                                         break;
2329                                 }
2330                         }
2331                         if(bad) {
2332                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2333                                                 << filename << "\"" << std::endl;
2334                                 continue;
2335                         }
2336                         if(tmp_os.str().length() == 0) {
2337                                 errorstream << "Server::fillMediaCache(): Empty file \""
2338                                                 << filepath << "\"" << std::endl;
2339                                 continue;
2340                         }
2341
2342                         SHA1 sha1;
2343                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2344
2345                         unsigned char *digest = sha1.getDigest();
2346                         std::string sha1_base64 = base64_encode(digest, 20);
2347                         std::string sha1_hex = hex_encode((char*)digest, 20);
2348                         free(digest);
2349
2350                         // Put in list
2351                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2352                         verbosestream << "Server: " << sha1_hex << " is " << filename
2353                                         << std::endl;
2354                 }
2355         }
2356 }
2357
2358 void Server::sendMediaAnnouncement(u16 peer_id)
2359 {
2360         DSTACK(FUNCTION_NAME);
2361
2362         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2363                 << std::endl;
2364
2365         // Make packet
2366         std::ostringstream os(std::ios_base::binary);
2367
2368         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2369         pkt << (u16) m_media.size();
2370
2371         for (UNORDERED_MAP<std::string, MediaInfo>::iterator i = m_media.begin();
2372                         i != m_media.end(); ++i) {
2373                 pkt << i->first << i->second.sha1_digest;
2374         }
2375
2376         pkt << g_settings->get("remote_media");
2377         Send(&pkt);
2378 }
2379
2380 struct SendableMedia
2381 {
2382         std::string name;
2383         std::string path;
2384         std::string data;
2385
2386         SendableMedia(const std::string &name_="", const std::string &path_="",
2387                       const std::string &data_=""):
2388                 name(name_),
2389                 path(path_),
2390                 data(data_)
2391         {}
2392 };
2393
2394 void Server::sendRequestedMedia(u16 peer_id,
2395                 const std::vector<std::string> &tosend)
2396 {
2397         DSTACK(FUNCTION_NAME);
2398
2399         verbosestream<<"Server::sendRequestedMedia(): "
2400                         <<"Sending files to client"<<std::endl;
2401
2402         /* Read files */
2403
2404         // Put 5kB in one bunch (this is not accurate)
2405         u32 bytes_per_bunch = 5000;
2406
2407         std::vector< std::vector<SendableMedia> > file_bunches;
2408         file_bunches.push_back(std::vector<SendableMedia>());
2409
2410         u32 file_size_bunch_total = 0;
2411
2412         for(std::vector<std::string>::const_iterator i = tosend.begin();
2413                         i != tosend.end(); ++i) {
2414                 const std::string &name = *i;
2415
2416                 if (m_media.find(name) == m_media.end()) {
2417                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2418                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2419                         continue;
2420                 }
2421
2422                 //TODO get path + name
2423                 std::string tpath = m_media[name].path;
2424
2425                 // Read data
2426                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2427                 if(fis.good() == false){
2428                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2429                                         <<tpath<<"\" for reading"<<std::endl;
2430                         continue;
2431                 }
2432                 std::ostringstream tmp_os(std::ios_base::binary);
2433                 bool bad = false;
2434                 for(;;) {
2435                         char buf[1024];
2436                         fis.read(buf, 1024);
2437                         std::streamsize len = fis.gcount();
2438                         tmp_os.write(buf, len);
2439                         file_size_bunch_total += len;
2440                         if(fis.eof())
2441                                 break;
2442                         if(!fis.good()) {
2443                                 bad = true;
2444                                 break;
2445                         }
2446                 }
2447                 if(bad) {
2448                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2449                                         <<name<<"\""<<std::endl;
2450                         continue;
2451                 }
2452                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2453                                 <<tname<<"\""<<std::endl;*/
2454                 // Put in list
2455                 file_bunches[file_bunches.size()-1].push_back(
2456                                 SendableMedia(name, tpath, tmp_os.str()));
2457
2458                 // Start next bunch if got enough data
2459                 if(file_size_bunch_total >= bytes_per_bunch) {
2460                         file_bunches.push_back(std::vector<SendableMedia>());
2461                         file_size_bunch_total = 0;
2462                 }
2463
2464         }
2465
2466         /* Create and send packets */
2467
2468         u16 num_bunches = file_bunches.size();
2469         for(u16 i = 0; i < num_bunches; i++) {
2470                 /*
2471                         u16 command
2472                         u16 total number of texture bunches
2473                         u16 index of this bunch
2474                         u32 number of files in this bunch
2475                         for each file {
2476                                 u16 length of name
2477                                 string name
2478                                 u32 length of data
2479                                 data
2480                         }
2481                 */
2482
2483                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2484                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2485
2486                 for(std::vector<SendableMedia>::iterator
2487                                 j = file_bunches[i].begin();
2488                                 j != file_bunches[i].end(); ++j) {
2489                         pkt << j->name;
2490                         pkt.putLongString(j->data);
2491                 }
2492
2493                 verbosestream << "Server::sendRequestedMedia(): bunch "
2494                                 << i << "/" << num_bunches
2495                                 << " files=" << file_bunches[i].size()
2496                                 << " size="  << pkt.getSize() << std::endl;
2497                 Send(&pkt);
2498         }
2499 }
2500
2501 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2502 {
2503         if(m_detached_inventories.count(name) == 0) {
2504                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2505                 return;
2506         }
2507         Inventory *inv = m_detached_inventories[name];
2508         std::ostringstream os(std::ios_base::binary);
2509
2510         os << serializeString(name);
2511         inv->serialize(os);
2512
2513         // Make data buffer
2514         std::string s = os.str();
2515
2516         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2517         pkt.putRawString(s.c_str(), s.size());
2518
2519         const std::string &check = m_detached_inventories_player[name];
2520         if (peer_id == PEER_ID_INEXISTENT) {
2521                 if (check == "")
2522                         return m_clients.sendToAll(&pkt);
2523                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2524                 if (p)
2525                         m_clients.send(p->peer_id, 0, &pkt, true);
2526         } else {
2527                 if (check == "" || getPlayerName(peer_id) == check)
2528                         Send(&pkt);
2529         }
2530 }
2531
2532 void Server::sendDetachedInventories(u16 peer_id)
2533 {
2534         DSTACK(FUNCTION_NAME);
2535
2536         for(std::map<std::string, Inventory*>::iterator
2537                         i = m_detached_inventories.begin();
2538                         i != m_detached_inventories.end(); ++i) {
2539                 const std::string &name = i->first;
2540                 //Inventory *inv = i->second;
2541                 sendDetachedInventory(name, peer_id);
2542         }
2543 }
2544
2545 /*
2546         Something random
2547 */
2548
2549 void Server::DiePlayer(u16 peer_id)
2550 {
2551         DSTACK(FUNCTION_NAME);
2552         PlayerSAO *playersao = getPlayerSAO(peer_id);
2553         // In some rare cases this can be NULL -- if the player is disconnected
2554         // when a Lua function modifies l_punch, for example
2555         if (!playersao)
2556                 return;
2557
2558         infostream << "Server::DiePlayer(): Player "
2559                         << playersao->getPlayer()->getName()
2560                         << " dies" << std::endl;
2561
2562         playersao->setHP(0);
2563
2564         // Trigger scripted stuff
2565         m_script->on_dieplayer(playersao);
2566
2567         SendPlayerHP(peer_id);
2568         SendDeathscreen(peer_id, false, v3f(0,0,0));
2569 }
2570
2571 void Server::RespawnPlayer(u16 peer_id)
2572 {
2573         DSTACK(FUNCTION_NAME);
2574
2575         PlayerSAO *playersao = getPlayerSAO(peer_id);
2576         assert(playersao);
2577
2578         infostream << "Server::RespawnPlayer(): Player "
2579                         << playersao->getPlayer()->getName()
2580                         << " respawns" << std::endl;
2581
2582         playersao->setHP(PLAYER_MAX_HP);
2583         playersao->setBreath(PLAYER_MAX_BREATH);
2584
2585         bool repositioned = m_script->on_respawnplayer(playersao);
2586         if (!repositioned) {
2587                 v3f pos = findSpawnPos();
2588                 // setPos will send the new position to client
2589                 playersao->setPos(pos);
2590         }
2591
2592         SendPlayerHP(peer_id);
2593 }
2594
2595
2596 void Server::DenySudoAccess(u16 peer_id)
2597 {
2598         DSTACK(FUNCTION_NAME);
2599
2600         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2601         Send(&pkt);
2602 }
2603
2604
2605 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2606                 const std::string &str_reason, bool reconnect)
2607 {
2608         if (proto_ver >= 25) {
2609                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2610         } else {
2611                 std::wstring wreason = utf8_to_wide(
2612                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2613                         accessDeniedStrings[(u8)reason]);
2614                 SendAccessDenied_Legacy(peer_id, wreason);
2615         }
2616
2617         m_clients.event(peer_id, CSE_SetDenied);
2618         m_con.DisconnectPeer(peer_id);
2619 }
2620
2621
2622 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2623 {
2624         DSTACK(FUNCTION_NAME);
2625
2626         SendAccessDenied(peer_id, reason, custom_reason);
2627         m_clients.event(peer_id, CSE_SetDenied);
2628         m_con.DisconnectPeer(peer_id);
2629 }
2630
2631 // 13/03/15: remove this function when protocol version 25 will become
2632 // the minimum version for MT users, maybe in 1 year
2633 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2634 {
2635         DSTACK(FUNCTION_NAME);
2636
2637         SendAccessDenied_Legacy(peer_id, reason);
2638         m_clients.event(peer_id, CSE_SetDenied);
2639         m_con.DisconnectPeer(peer_id);
2640 }
2641
2642 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2643 {
2644         DSTACK(FUNCTION_NAME);
2645
2646         if (!forSudoMode) {
2647                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2648
2649                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2650
2651                 // Right now, the auth mechs don't change between login and sudo mode.
2652                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2653                 client->allowed_sudo_mechs = sudo_auth_mechs;
2654
2655                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2656                                 << g_settings->getFloat("dedicated_server_step")
2657                                 << sudo_auth_mechs;
2658
2659                 Send(&resp_pkt);
2660                 m_clients.event(peer_id, CSE_AuthAccept);
2661         } else {
2662                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2663
2664                 // We only support SRP right now
2665                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2666
2667                 resp_pkt << sudo_auth_mechs;
2668                 Send(&resp_pkt);
2669                 m_clients.event(peer_id, CSE_SudoSuccess);
2670         }
2671 }
2672
2673 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2674 {
2675         DSTACK(FUNCTION_NAME);
2676         std::wstring message;
2677         {
2678                 /*
2679                         Clear references to playing sounds
2680                 */
2681                 for (UNORDERED_MAP<s32, ServerPlayingSound>::iterator
2682                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2683                         ServerPlayingSound &psound = i->second;
2684                         psound.clients.erase(peer_id);
2685                         if (psound.clients.empty())
2686                                 m_playing_sounds.erase(i++);
2687                         else
2688                                 ++i;
2689                 }
2690
2691                 RemotePlayer *player = m_env->getPlayer(peer_id);
2692
2693                 /* Run scripts and remove from environment */
2694                 if (player != NULL) {
2695                         PlayerSAO *playersao = player->getPlayerSAO();
2696                         assert(playersao);
2697
2698                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2699
2700                         playersao->disconnected();
2701                 }
2702
2703                 /*
2704                         Print out action
2705                 */
2706                 {
2707                         if(player != NULL && reason != CDR_DENY) {
2708                                 std::ostringstream os(std::ios_base::binary);
2709                                 std::vector<u16> clients = m_clients.getClientIDs();
2710
2711                                 for(std::vector<u16>::iterator i = clients.begin();
2712                                         i != clients.end(); ++i) {
2713                                         // Get player
2714                                         RemotePlayer *player = m_env->getPlayer(*i);
2715                                         if (!player)
2716                                                 continue;
2717
2718                                         // Get name of player
2719                                         os << player->getName() << " ";
2720                                 }
2721
2722                                 std::string name = player->getName();
2723                                 actionstream << name << " "
2724                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2725                                                 << " List of players: " << os.str() << std::endl;
2726                                 if (m_admin_chat)
2727                                         m_admin_chat->outgoing_queue.push_back(
2728                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2729                         }
2730                 }
2731                 {
2732                         MutexAutoLock env_lock(m_env_mutex);
2733                         m_clients.DeleteClient(peer_id);
2734                 }
2735         }
2736
2737         // Send leave chat message to all remaining clients
2738         if(message.length() != 0)
2739                 SendChatMessage(PEER_ID_INEXISTENT,message);
2740 }
2741
2742 void Server::UpdateCrafting(RemotePlayer *player)
2743 {
2744         DSTACK(FUNCTION_NAME);
2745
2746         // Get a preview for crafting
2747         ItemStack preview;
2748         InventoryLocation loc;
2749         loc.setPlayer(player->getName());
2750         std::vector<ItemStack> output_replacements;
2751         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2752         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2753                         (&player->inventory)->getList("craft"), loc);
2754
2755         // Put the new preview in
2756         InventoryList *plist = player->inventory.getList("craftpreview");
2757         sanity_check(plist);
2758         sanity_check(plist->getSize() >= 1);
2759         plist->changeItem(0, preview);
2760 }
2761
2762 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2763 {
2764         if (evt->type == CET_NICK_ADD) {
2765                 // The terminal informed us of its nick choice
2766                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2767                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2768                         errorstream << "You haven't set up an account." << std::endl
2769                                 << "Please log in using the client as '"
2770                                 << m_admin_nick << "' with a secure password." << std::endl
2771                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2772                                 << "and everybody can claim the user account instead of you," << std::endl
2773                                 << "giving them full control over this server." << std::endl;
2774                 }
2775         } else {
2776                 assert(evt->type == CET_CHAT);
2777                 handleAdminChat((ChatEventChat *)evt);
2778         }
2779 }
2780
2781 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2782         const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
2783 {
2784         // If something goes wrong, this player is to blame
2785         RollbackScopeActor rollback_scope(m_rollback,
2786                 std::string("player:") + name);
2787
2788         if (player) {
2789                 switch (player->canSendChatMessage()) {
2790                         case RPLAYER_CHATRESULT_FLOODING: {
2791                                 std::wstringstream ws;
2792                                 ws << L"You cannot send more messages. You are limited to "
2793                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2794                                    << L" messages per 10 seconds.";
2795                                 return ws.str();
2796                         }
2797                         case RPLAYER_CHATRESULT_KICK:
2798                                 DenyAccess_Legacy(player->peer_id,
2799                                                 L"You have been kicked due to message flooding.");
2800                                 return L"";
2801                         case RPLAYER_CHATRESULT_OK:
2802                                 break;
2803                         default:
2804                                 FATAL_ERROR("Unhandled chat filtering result found.");
2805                 }
2806         }
2807
2808         if (m_max_chatmessage_length > 0
2809                         && wmessage.length() > m_max_chatmessage_length) {
2810                 return L"Your message exceed the maximum chat message limit set on the server. "
2811                                 L"It was refused. Send a shorter message";
2812         }
2813
2814         // Run script hook, exit if script ate the chat message
2815         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2816                 return L"";
2817
2818         // Line to send
2819         std::wstring line;
2820         // Whether to send line to the player that sent the message, or to all players
2821         bool broadcast_line = true;
2822
2823         if (check_shout_priv && !checkPriv(name, "shout")) {
2824                 line += L"-!- You don't have permission to shout.";
2825                 broadcast_line = false;
2826         } else {
2827                 line += L"<";
2828                 line += wname;
2829                 line += L"> ";
2830                 line += wmessage;
2831         }
2832
2833         /*
2834                 Tell calling method to send the message to sender
2835         */
2836         if (!broadcast_line) {
2837                 return line;
2838         } else {
2839                 /*
2840                         Send the message to others
2841                 */
2842                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2843
2844                 std::vector<u16> clients = m_clients.getClientIDs();
2845
2846                 /*
2847                         Send the message back to the inital sender
2848                         if they are using protocol version >= 29
2849                 */
2850
2851                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2852                 if (player && player->protocol_version >= 29)
2853                         peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2854
2855                 for (u16 i = 0; i < clients.size(); i++) {
2856                         u16 cid = clients[i];
2857                         if (cid != peer_id_to_avoid_sending)
2858                                 SendChatMessage(cid, line);
2859                 }
2860         }
2861         return L"";
2862 }
2863
2864 void Server::handleAdminChat(const ChatEventChat *evt)
2865 {
2866         std::string name = evt->nick;
2867         std::wstring wname = utf8_to_wide(name);
2868         std::wstring wmessage = evt->evt_msg;
2869
2870         std::wstring answer = handleChat(name, wname, wmessage);
2871
2872         // If asked to send answer to sender
2873         if (!answer.empty()) {
2874                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2875         }
2876 }
2877
2878 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2879 {
2880         RemoteClient *client = getClientNoEx(peer_id,state_min);
2881         if(!client)
2882                 throw ClientNotFoundException("Client not found");
2883
2884         return client;
2885 }
2886 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2887 {
2888         return m_clients.getClientNoEx(peer_id, state_min);
2889 }
2890
2891 std::string Server::getPlayerName(u16 peer_id)
2892 {
2893         RemotePlayer *player = m_env->getPlayer(peer_id);
2894         if (player == NULL)
2895                 return "[id="+itos(peer_id)+"]";
2896         return player->getName();
2897 }
2898
2899 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2900 {
2901         RemotePlayer *player = m_env->getPlayer(peer_id);
2902         if (player == NULL)
2903                 return NULL;
2904         return player->getPlayerSAO();
2905 }
2906
2907 std::wstring Server::getStatusString()
2908 {
2909         std::wostringstream os(std::ios_base::binary);
2910         os<<L"# Server: ";
2911         // Version
2912         os<<L"version="<<narrow_to_wide(g_version_string);
2913         // Uptime
2914         os<<L", uptime="<<m_uptime.get();
2915         // Max lag estimate
2916         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2917         // Information about clients
2918         bool first = true;
2919         os<<L", clients={";
2920         std::vector<u16> clients = m_clients.getClientIDs();
2921         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2922                 // Get player
2923                 RemotePlayer *player = m_env->getPlayer(*i);
2924                 // Get name of player
2925                 std::wstring name = L"unknown";
2926                 if (player != NULL)
2927                         name = narrow_to_wide(player->getName());
2928                 // Add name to information string
2929                 if(!first)
2930                         os << L", ";
2931                 else
2932                         first = false;
2933                 os << name;
2934         }
2935         os << L"}";
2936         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2937                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2938         if(g_settings->get("motd") != "")
2939                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2940         return os.str();
2941 }
2942
2943 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2944 {
2945         std::set<std::string> privs;
2946         m_script->getAuth(name, NULL, &privs);
2947         return privs;
2948 }
2949
2950 bool Server::checkPriv(const std::string &name, const std::string &priv)
2951 {
2952         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2953         return (privs.count(priv) != 0);
2954 }
2955
2956 void Server::reportPrivsModified(const std::string &name)
2957 {
2958         if(name == "") {
2959                 std::vector<u16> clients = m_clients.getClientIDs();
2960                 for(std::vector<u16>::iterator i = clients.begin();
2961                                 i != clients.end(); ++i) {
2962                         RemotePlayer *player = m_env->getPlayer(*i);
2963                         reportPrivsModified(player->getName());
2964                 }
2965         } else {
2966                 RemotePlayer *player = m_env->getPlayer(name.c_str());
2967                 if (!player)
2968                         return;
2969                 SendPlayerPrivileges(player->peer_id);
2970                 PlayerSAO *sao = player->getPlayerSAO();
2971                 if(!sao)
2972                         return;
2973                 sao->updatePrivileges(
2974                                 getPlayerEffectivePrivs(name),
2975                                 isSingleplayer());
2976         }
2977 }
2978
2979 void Server::reportInventoryFormspecModified(const std::string &name)
2980 {
2981         RemotePlayer *player = m_env->getPlayer(name.c_str());
2982         if (!player)
2983                 return;
2984         SendPlayerInventoryFormspec(player->peer_id);
2985 }
2986
2987 void Server::setIpBanned(const std::string &ip, const std::string &name)
2988 {
2989         m_banmanager->add(ip, name);
2990 }
2991
2992 void Server::unsetIpBanned(const std::string &ip_or_name)
2993 {
2994         m_banmanager->remove(ip_or_name);
2995 }
2996
2997 std::string Server::getBanDescription(const std::string &ip_or_name)
2998 {
2999         return m_banmanager->getBanDescription(ip_or_name);
3000 }
3001
3002 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3003 {
3004         // m_env will be NULL if the server is initializing
3005         if (!m_env)
3006                 return;
3007
3008         if (m_admin_nick == name && !m_admin_nick.empty()) {
3009                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3010         }
3011
3012         RemotePlayer *player = m_env->getPlayer(name);
3013         if (!player) {
3014                 return;
3015         }
3016
3017         if (player->peer_id == PEER_ID_INEXISTENT)
3018                 return;
3019
3020         SendChatMessage(player->peer_id, msg);
3021 }
3022
3023 bool Server::showFormspec(const char *playername, const std::string &formspec,
3024         const std::string &formname)
3025 {
3026         // m_env will be NULL if the server is initializing
3027         if (!m_env)
3028                 return false;
3029
3030         RemotePlayer *player = m_env->getPlayer(playername);
3031         if (!player)
3032                 return false;
3033
3034         SendShowFormspecMessage(player->peer_id, formspec, formname);
3035         return true;
3036 }
3037
3038 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3039 {
3040         if (!player)
3041                 return -1;
3042
3043         u32 id = player->addHud(form);
3044
3045         SendHUDAdd(player->peer_id, id, form);
3046
3047         return id;
3048 }
3049
3050 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3051         if (!player)
3052                 return false;
3053
3054         HudElement* todel = player->removeHud(id);
3055
3056         if (!todel)
3057                 return false;
3058
3059         delete todel;
3060
3061         SendHUDRemove(player->peer_id, id);
3062         return true;
3063 }
3064
3065 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3066 {
3067         if (!player)
3068                 return false;
3069
3070         SendHUDChange(player->peer_id, id, stat, data);
3071         return true;
3072 }
3073
3074 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3075 {
3076         if (!player)
3077                 return false;
3078
3079         SendHUDSetFlags(player->peer_id, flags, mask);
3080         player->hud_flags &= ~mask;
3081         player->hud_flags |= flags;
3082
3083         PlayerSAO* playersao = player->getPlayerSAO();
3084
3085         if (playersao == NULL)
3086                 return false;
3087
3088         m_script->player_event(playersao, "hud_changed");
3089         return true;
3090 }
3091
3092 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3093 {
3094         if (!player)
3095                 return false;
3096
3097         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3098                 return false;
3099
3100         player->setHotbarItemcount(hotbar_itemcount);
3101         std::ostringstream os(std::ios::binary);
3102         writeS32(os, hotbar_itemcount);
3103         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3104         return true;
3105 }
3106
3107 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3108 {
3109         if (!player)
3110                 return;
3111
3112         player->setHotbarImage(name);
3113         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3114 }
3115
3116 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3117 {
3118         if (!player)
3119                 return "";
3120         return player->getHotbarImage();
3121 }
3122
3123 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3124 {
3125         if (!player)
3126                 return;
3127
3128         player->setHotbarSelectedImage(name);
3129         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3130 }
3131
3132 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3133                 v2s32 animation_frames[4], f32 frame_speed)
3134 {
3135         if (!player)
3136                 return false;
3137
3138         player->setLocalAnimations(animation_frames, frame_speed);
3139         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3140         return true;
3141 }
3142
3143 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3144 {
3145         if (!player)
3146                 return false;
3147
3148         player->eye_offset_first = first;
3149         player->eye_offset_third = third;
3150         SendEyeOffset(player->peer_id, first, third);
3151         return true;
3152 }
3153
3154 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3155         const std::string &type, const std::vector<std::string> &params)
3156 {
3157         if (!player)
3158                 return false;
3159
3160         player->setSky(bgcolor, type, params);
3161         SendSetSky(player->peer_id, bgcolor, type, params);
3162         return true;
3163 }
3164
3165 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3166         float ratio)
3167 {
3168         if (!player)
3169                 return false;
3170
3171         player->overrideDayNightRatio(do_override, ratio);
3172         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3173         return true;
3174 }
3175
3176 void Server::notifyPlayers(const std::wstring &msg)
3177 {
3178         SendChatMessage(PEER_ID_INEXISTENT,msg);
3179 }
3180
3181 void Server::spawnParticle(const std::string &playername, v3f pos,
3182         v3f velocity, v3f acceleration,
3183         float expirationtime, float size, bool
3184         collisiondetection, bool collision_removal,
3185         bool vertical, const std::string &texture,
3186         const struct TileAnimationParams &animation, u8 glow)
3187 {
3188         // m_env will be NULL if the server is initializing
3189         if (!m_env)
3190                 return;
3191
3192         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3193         if (playername != "") {
3194                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3195                 if (!player)
3196                         return;
3197                 peer_id = player->peer_id;
3198                 proto_ver = player->protocol_version;
3199         }
3200
3201         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3202                         expirationtime, size, collisiondetection,
3203                         collision_removal, vertical, texture, animation, glow);
3204 }
3205
3206 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3207         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3208         float minexptime, float maxexptime, float minsize, float maxsize,
3209         bool collisiondetection, bool collision_removal,
3210         ServerActiveObject *attached, bool vertical, const std::string &texture,
3211         const std::string &playername, const struct TileAnimationParams &animation,
3212         u8 glow)
3213 {
3214         // m_env will be NULL if the server is initializing
3215         if (!m_env)
3216                 return -1;
3217
3218         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3219         if (playername != "") {
3220                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3221                 if (!player)
3222                         return -1;
3223                 peer_id = player->peer_id;
3224                 proto_ver = player->protocol_version;
3225         }
3226
3227         u16 attached_id = attached ? attached->getId() : 0;
3228
3229         u32 id;
3230         if (attached_id == 0)
3231                 id = m_env->addParticleSpawner(spawntime);
3232         else
3233                 id = m_env->addParticleSpawner(spawntime, attached_id);
3234
3235         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3236                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3237                 minexptime, maxexptime, minsize, maxsize,
3238                 collisiondetection, collision_removal, attached_id, vertical,
3239                 texture, id, animation, glow);
3240
3241         return id;
3242 }
3243
3244 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3245 {
3246         // m_env will be NULL if the server is initializing
3247         if (!m_env)
3248                 throw ServerError("Can't delete particle spawners during initialisation!");
3249
3250         u16 peer_id = PEER_ID_INEXISTENT;
3251         if (playername != "") {
3252                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3253                 if (!player)
3254                         return;
3255                 peer_id = player->peer_id;
3256         }
3257
3258         m_env->deleteParticleSpawner(id);
3259         SendDeleteParticleSpawner(peer_id, id);
3260 }
3261
3262 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3263 {
3264         if(m_detached_inventories.count(name) > 0){
3265                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3266                 delete m_detached_inventories[name];
3267         } else {
3268                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3269         }
3270         Inventory *inv = new Inventory(m_itemdef);
3271         sanity_check(inv);
3272         m_detached_inventories[name] = inv;
3273         m_detached_inventories_player[name] = player;
3274         //TODO find a better way to do this
3275         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3276         return inv;
3277 }
3278
3279 // actions: time-reversed list
3280 // Return value: success/failure
3281 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3282                 std::list<std::string> *log)
3283 {
3284         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3285         ServerMap *map = (ServerMap*)(&m_env->getMap());
3286
3287         // Fail if no actions to handle
3288         if(actions.empty()){
3289                 log->push_back("Nothing to do.");
3290                 return false;
3291         }
3292
3293         int num_tried = 0;
3294         int num_failed = 0;
3295
3296         for(std::list<RollbackAction>::const_iterator
3297                         i = actions.begin();
3298                         i != actions.end(); ++i)
3299         {
3300                 const RollbackAction &action = *i;
3301                 num_tried++;
3302                 bool success = action.applyRevert(map, this, this);
3303                 if(!success){
3304                         num_failed++;
3305                         std::ostringstream os;
3306                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3307                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3308                         if(log)
3309                                 log->push_back(os.str());
3310                 }else{
3311                         std::ostringstream os;
3312                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3313                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3314                         if(log)
3315                                 log->push_back(os.str());
3316                 }
3317         }
3318
3319         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3320                         <<" failed"<<std::endl;
3321
3322         // Call it done if less than half failed
3323         return num_failed <= num_tried/2;
3324 }
3325
3326 // IGameDef interface
3327 // Under envlock
3328 IItemDefManager *Server::getItemDefManager()
3329 {
3330         return m_itemdef;
3331 }
3332
3333 INodeDefManager *Server::getNodeDefManager()
3334 {
3335         return m_nodedef;
3336 }
3337
3338 ICraftDefManager *Server::getCraftDefManager()
3339 {
3340         return m_craftdef;
3341 }
3342
3343 u16 Server::allocateUnknownNodeId(const std::string &name)
3344 {
3345         return m_nodedef->allocateDummy(name);
3346 }
3347
3348 MtEventManager *Server::getEventManager()
3349 {
3350         return m_event;
3351 }
3352
3353 IWritableItemDefManager *Server::getWritableItemDefManager()
3354 {
3355         return m_itemdef;
3356 }
3357
3358 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3359 {
3360         return m_nodedef;
3361 }
3362
3363 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3364 {
3365         return m_craftdef;
3366 }
3367
3368 const ModSpec *Server::getModSpec(const std::string &modname) const
3369 {
3370         std::vector<ModSpec>::const_iterator it;
3371         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3372                 const ModSpec &mod = *it;
3373                 if (mod.name == modname)
3374                         return &mod;
3375         }
3376         return NULL;
3377 }
3378
3379 void Server::getModNames(std::vector<std::string> &modlist)
3380 {
3381         std::vector<ModSpec>::iterator it;
3382         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3383                 modlist.push_back(it->name);
3384 }
3385
3386 std::string Server::getBuiltinLuaPath()
3387 {
3388         return porting::path_share + DIR_DELIM + "builtin";
3389 }
3390
3391 std::string Server::getModStoragePath() const
3392 {
3393         return m_path_world + DIR_DELIM + "mod_storage";
3394 }
3395
3396 v3f Server::findSpawnPos()
3397 {
3398         ServerMap &map = m_env->getServerMap();
3399         v3f nodeposf;
3400         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3401                 return nodeposf * BS;
3402         }
3403
3404         bool is_good = false;
3405
3406         // Try to find a good place a few times
3407         for(s32 i = 0; i < 4000 && !is_good; i++) {
3408                 s32 range = 1 + i;
3409                 // We're going to try to throw the player to this position
3410                 v2s16 nodepos2d = v2s16(
3411                                 -range + (myrand() % (range * 2)),
3412                                 -range + (myrand() % (range * 2)));
3413
3414                 // Get spawn level at point
3415                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3416                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3417                 // the mapgen to signify an unsuitable spawn position
3418                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3419                         continue;
3420
3421                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3422
3423                 s32 air_count = 0;
3424                 for (s32 i = 0; i < 10; i++) {
3425                         v3s16 blockpos = getNodeBlockPos(nodepos);
3426                         map.emergeBlock(blockpos, true);
3427                         content_t c = map.getNodeNoEx(nodepos).getContent();
3428                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3429                                 air_count++;
3430                                 if (air_count >= 2) {
3431                                         nodeposf = intToFloat(nodepos, BS);
3432                                         // Don't spawn the player outside map boundaries
3433                                         if (objectpos_over_limit(nodeposf))
3434                                                 continue;
3435                                         is_good = true;
3436                                         break;
3437                                 }
3438                         }
3439                         nodepos.Y++;
3440                 }
3441         }
3442
3443         return nodeposf;
3444 }
3445
3446 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3447 {
3448         bool newplayer = false;
3449
3450         /*
3451                 Try to get an existing player
3452         */
3453         RemotePlayer *player = m_env->getPlayer(name);
3454
3455         // If player is already connected, cancel
3456         if (player != NULL && player->peer_id != 0) {
3457                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3458                 return NULL;
3459         }
3460
3461         /*
3462                 If player with the wanted peer_id already exists, cancel.
3463         */
3464         if (m_env->getPlayer(peer_id) != NULL) {
3465                 infostream<<"emergePlayer(): Player with wrong name but same"
3466                                 " peer_id already exists"<<std::endl;
3467                 return NULL;
3468         }
3469
3470         // Create a new player active object
3471         PlayerSAO *playersao = new PlayerSAO(m_env, peer_id, isSingleplayer());
3472         player = m_env->loadPlayer(name, playersao);
3473
3474         // Create player if it doesn't exist
3475         if (!player) {
3476                 newplayer = true;
3477                 player = new RemotePlayer(name, this->idef());
3478                 // Set player position
3479                 infostream<<"Server: Finding spawn place for player \""
3480                                 <<name<<"\""<<std::endl;
3481                 playersao->setBasePosition(findSpawnPos());
3482
3483                 // Make sure the player is saved
3484                 player->setModified(true);
3485
3486                 // Add player to environment
3487                 m_env->addPlayer(player);
3488         } else {
3489                 // If the player exists, ensure that they respawn inside legal bounds
3490                 // This fixes an assert crash when the player can't be added
3491                 // to the environment
3492                 if (objectpos_over_limit(playersao->getBasePosition())) {
3493                         actionstream << "Respawn position for player \""
3494                                 << name << "\" outside limits, resetting" << std::endl;
3495                         playersao->setBasePosition(findSpawnPos());
3496                 }
3497         }
3498
3499         playersao->initialize(player, getPlayerEffectivePrivs(player->getName()));
3500
3501         player->protocol_version = proto_version;
3502
3503         /* Clean up old HUD elements from previous sessions */
3504         player->clearHud();
3505
3506         /* Add object to environment */
3507         m_env->addActiveObject(playersao);
3508
3509         /* Run scripts */
3510         if (newplayer) {
3511                 m_script->on_newplayer(playersao);
3512         }
3513
3514         return playersao;
3515 }
3516
3517 bool Server::registerModStorage(ModMetadata *storage)
3518 {
3519         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3520                 errorstream << "Unable to register same mod storage twice. Storage name: "
3521                                 << storage->getModName() << std::endl;
3522                 return false;
3523         }
3524
3525         m_mod_storages[storage->getModName()] = storage;
3526         return true;
3527 }
3528
3529 void Server::unregisterModStorage(const std::string &name)
3530 {
3531         UNORDERED_MAP<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3532         if (it != m_mod_storages.end()) {
3533                 // Save unconditionaly on unregistration
3534                 it->second->save(getModStoragePath());
3535                 m_mod_storages.erase(name);
3536         }
3537 }
3538
3539 void dedicated_server_loop(Server &server, bool &kill)
3540 {
3541         DSTACK(FUNCTION_NAME);
3542
3543         verbosestream<<"dedicated_server_loop()"<<std::endl;
3544
3545         IntervalLimiter m_profiler_interval;
3546
3547         static const float steplen = g_settings->getFloat("dedicated_server_step");
3548         static const float profiler_print_interval =
3549                         g_settings->getFloat("profiler_print_interval");
3550
3551         for(;;) {
3552                 // This is kind of a hack but can be done like this
3553                 // because server.step() is very light
3554                 {
3555                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3556                         sleep_ms((int)(steplen*1000.0));
3557                 }
3558                 server.step(steplen);
3559
3560                 if (server.getShutdownRequested() || kill)
3561                         break;
3562
3563                 /*
3564                         Profiler
3565                 */
3566                 if (profiler_print_interval != 0) {
3567                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3568                         {
3569                                 infostream<<"Profiler:"<<std::endl;
3570                                 g_profiler->print(infostream);
3571                                 g_profiler->clear();
3572                         }
3573                 }
3574         }
3575
3576         infostream << "Dedicated server quitting" << std::endl;
3577 #if USE_CURL
3578         if (g_settings->getBool("server_announce"))
3579                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3580                         server.m_bind_addr.getPort());
3581 #endif
3582 }