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