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