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