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