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