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