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