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