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