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