Have the server send the player list to the client (#5924)
[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                 RemoteClientMap 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 (RemoteClientMap::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 (std::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                 std::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                         std::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                 RemoteClientMap clients = m_clients.getClientList();
805                 // Route data to every client
806                 for (std::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 (std::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 (std::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         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2116                 m_playing_sounds.find(handle);
2117         if (i == m_playing_sounds.end())
2118                 return;
2119         ServerPlayingSound &psound = i->second;
2120
2121         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2122         pkt << handle;
2123
2124         for (std::unordered_set<u16>::const_iterator si = psound.clients.begin();
2125                         si != psound.clients.end(); ++si) {
2126                 // Send as reliable
2127                 m_clients.send(*si, 0, &pkt, true);
2128         }
2129         // Remove sound reference
2130         m_playing_sounds.erase(i);
2131 }
2132
2133 void Server::fadeSound(s32 handle, float step, float gain)
2134 {
2135         // Get sound reference
2136         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2137                 m_playing_sounds.find(handle);
2138         if (i == m_playing_sounds.end())
2139                 return;
2140
2141         ServerPlayingSound &psound = i->second;
2142         psound.params.gain = gain;
2143
2144         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2145         pkt << handle << step << gain;
2146
2147         // Backwards compability
2148         bool play_sound = gain > 0;
2149         ServerPlayingSound compat_psound = psound;
2150         compat_psound.clients.clear();
2151
2152         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2153         compat_pkt << handle;
2154
2155         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2156                         it != psound.clients.end();) {
2157                 if (m_clients.getProtocolVersion(*it) >= 32) {
2158                         // Send as reliable
2159                         m_clients.send(*it, 0, &pkt, true);
2160                         ++it;
2161                 } else {
2162                         compat_psound.clients.insert(*it);
2163                         // Stop old sound
2164                         m_clients.send(*it, 0, &compat_pkt, true);
2165                         psound.clients.erase(it++);
2166                 }
2167         }
2168
2169         // Remove sound reference
2170         if (!play_sound || psound.clients.size() == 0)
2171                 m_playing_sounds.erase(i);
2172
2173         if (play_sound && compat_psound.clients.size() > 0) {
2174                 // Play new sound volume on older clients
2175                 playSound(compat_psound.spec, compat_psound.params);
2176         }
2177 }
2178
2179 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2180         std::vector<u16> *far_players, float far_d_nodes)
2181 {
2182         float maxd = far_d_nodes*BS;
2183         v3f p_f = intToFloat(p, BS);
2184
2185         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2186         pkt << p;
2187
2188         std::vector<u16> clients = m_clients.getClientIDs();
2189         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2190                 if (far_players) {
2191                         // Get player
2192                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2193                                 PlayerSAO *sao = player->getPlayerSAO();
2194                                 if (!sao)
2195                                         continue;
2196
2197                                 // If player is far away, only set modified blocks not sent
2198                                 v3f player_pos = sao->getBasePosition();
2199                                 if (player_pos.getDistanceFrom(p_f) > maxd) {
2200                                         far_players->push_back(*i);
2201                                         continue;
2202                                 }
2203                         }
2204                 }
2205
2206                 // Send as reliable
2207                 m_clients.send(*i, 0, &pkt, true);
2208         }
2209 }
2210
2211 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2212                 std::vector<u16> *far_players, float far_d_nodes,
2213                 bool remove_metadata)
2214 {
2215         float maxd = far_d_nodes*BS;
2216         v3f p_f = intToFloat(p, BS);
2217
2218         std::vector<u16> clients = m_clients.getClientIDs();
2219         for(std::vector<u16>::iterator i = clients.begin();     i != clients.end(); ++i) {
2220                 if (far_players) {
2221                         // Get player
2222                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2223                                 PlayerSAO *sao = player->getPlayerSAO();
2224                                 if (!sao)
2225                                         continue;
2226
2227                                 // If player is far away, only set modified blocks not sent
2228                                 v3f player_pos = sao->getBasePosition();
2229                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2230                                         far_players->push_back(*i);
2231                                         continue;
2232                                 }
2233                         }
2234                 }
2235
2236                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2237                 m_clients.lock();
2238                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2239                 if (client != 0) {
2240                         pkt << p << n.param0 << n.param1 << n.param2
2241                                         << (u8) (remove_metadata ? 0 : 1);
2242                 }
2243                 m_clients.unlock();
2244
2245                 // Send as reliable
2246                 if (pkt.getSize() > 0)
2247                         m_clients.send(*i, 0, &pkt, true);
2248         }
2249 }
2250
2251 void Server::setBlockNotSent(v3s16 p)
2252 {
2253         std::vector<u16> clients = m_clients.getClientIDs();
2254         m_clients.lock();
2255         for(std::vector<u16>::iterator i = clients.begin();
2256                 i != clients.end(); ++i) {
2257                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2258                 client->SetBlockNotSent(p);
2259         }
2260         m_clients.unlock();
2261 }
2262
2263 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2264 {
2265         DSTACK(FUNCTION_NAME);
2266
2267         v3s16 p = block->getPos();
2268
2269         /*
2270                 Create a packet with the block in the right format
2271         */
2272
2273         std::ostringstream os(std::ios_base::binary);
2274         block->serialize(os, ver, false);
2275         block->serializeNetworkSpecific(os);
2276         std::string s = os.str();
2277
2278         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2279
2280         pkt << p;
2281         pkt.putRawString(s.c_str(), s.size());
2282         Send(&pkt);
2283 }
2284
2285 void Server::SendBlocks(float dtime)
2286 {
2287         DSTACK(FUNCTION_NAME);
2288
2289         MutexAutoLock envlock(m_env_mutex);
2290         //TODO check if one big lock could be faster then multiple small ones
2291
2292         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2293
2294         std::vector<PrioritySortedBlockTransfer> queue;
2295
2296         s32 total_sending = 0;
2297
2298         {
2299                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2300
2301                 std::vector<u16> clients = m_clients.getClientIDs();
2302
2303                 m_clients.lock();
2304                 for(std::vector<u16>::iterator i = clients.begin();
2305                         i != clients.end(); ++i) {
2306                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2307
2308                         if (client == NULL)
2309                                 continue;
2310
2311                         total_sending += client->SendingCount();
2312                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2313                 }
2314                 m_clients.unlock();
2315         }
2316
2317         // Sort.
2318         // Lowest priority number comes first.
2319         // Lowest is most important.
2320         std::sort(queue.begin(), queue.end());
2321
2322         m_clients.lock();
2323         for(u32 i=0; i<queue.size(); i++)
2324         {
2325                 //TODO: Calculate limit dynamically
2326                 if(total_sending >= g_settings->getS32
2327                                 ("max_simultaneous_block_sends_server_total"))
2328                         break;
2329
2330                 PrioritySortedBlockTransfer q = queue[i];
2331
2332                 MapBlock *block = NULL;
2333                 try
2334                 {
2335                         block = m_env->getMap().getBlockNoCreate(q.pos);
2336                 }
2337                 catch(InvalidPositionException &e)
2338                 {
2339                         continue;
2340                 }
2341
2342                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2343
2344                 if(!client)
2345                         continue;
2346
2347                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2348
2349                 client->SentBlock(q.pos);
2350                 total_sending++;
2351         }
2352         m_clients.unlock();
2353 }
2354
2355 void Server::fillMediaCache()
2356 {
2357         DSTACK(FUNCTION_NAME);
2358
2359         infostream<<"Server: Calculating media file checksums"<<std::endl;
2360
2361         // Collect all media file paths
2362         std::vector<std::string> paths;
2363         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2364                         i != m_mods.end(); ++i) {
2365                 const ModSpec &mod = *i;
2366                 paths.push_back(mod.path + DIR_DELIM + "textures");
2367                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2368                 paths.push_back(mod.path + DIR_DELIM + "media");
2369                 paths.push_back(mod.path + DIR_DELIM + "models");
2370         }
2371         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2372
2373         // Collect media file information from paths into cache
2374         for(std::vector<std::string>::iterator i = paths.begin();
2375                         i != paths.end(); ++i) {
2376                 std::string mediapath = *i;
2377                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2378                 for (u32 j = 0; j < dirlist.size(); j++) {
2379                         if (dirlist[j].dir) // Ignode dirs
2380                                 continue;
2381                         std::string filename = dirlist[j].name;
2382                         // If name contains illegal characters, ignore the file
2383                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2384                                 infostream<<"Server: ignoring illegal file name: \""
2385                                                 << filename << "\"" << std::endl;
2386                                 continue;
2387                         }
2388                         // If name is not in a supported format, ignore it
2389                         const char *supported_ext[] = {
2390                                 ".png", ".jpg", ".bmp", ".tga",
2391                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2392                                 ".ogg",
2393                                 ".x", ".b3d", ".md2", ".obj",
2394                                 NULL
2395                         };
2396                         if (removeStringEnd(filename, supported_ext) == ""){
2397                                 infostream << "Server: ignoring unsupported file extension: \""
2398                                                 << filename << "\"" << std::endl;
2399                                 continue;
2400                         }
2401                         // Ok, attempt to load the file and add to cache
2402                         std::string filepath = mediapath + DIR_DELIM + filename;
2403                         // Read data
2404                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2405                         if (!fis.good()) {
2406                                 errorstream << "Server::fillMediaCache(): Could not open \""
2407                                                 << filename << "\" for reading" << std::endl;
2408                                 continue;
2409                         }
2410                         std::ostringstream tmp_os(std::ios_base::binary);
2411                         bool bad = false;
2412                         for(;;) {
2413                                 char buf[1024];
2414                                 fis.read(buf, 1024);
2415                                 std::streamsize len = fis.gcount();
2416                                 tmp_os.write(buf, len);
2417                                 if (fis.eof())
2418                                         break;
2419                                 if (!fis.good()) {
2420                                         bad = true;
2421                                         break;
2422                                 }
2423                         }
2424                         if(bad) {
2425                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2426                                                 << filename << "\"" << std::endl;
2427                                 continue;
2428                         }
2429                         if(tmp_os.str().length() == 0) {
2430                                 errorstream << "Server::fillMediaCache(): Empty file \""
2431                                                 << filepath << "\"" << std::endl;
2432                                 continue;
2433                         }
2434
2435                         SHA1 sha1;
2436                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2437
2438                         unsigned char *digest = sha1.getDigest();
2439                         std::string sha1_base64 = base64_encode(digest, 20);
2440                         std::string sha1_hex = hex_encode((char*)digest, 20);
2441                         free(digest);
2442
2443                         // Put in list
2444                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2445                         verbosestream << "Server: " << sha1_hex << " is " << filename
2446                                         << std::endl;
2447                 }
2448         }
2449 }
2450
2451 void Server::sendMediaAnnouncement(u16 peer_id)
2452 {
2453         DSTACK(FUNCTION_NAME);
2454
2455         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2456                 << std::endl;
2457
2458         // Make packet
2459         std::ostringstream os(std::ios_base::binary);
2460
2461         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2462         pkt << (u16) m_media.size();
2463
2464         for (std::unordered_map<std::string, MediaInfo>::iterator i = m_media.begin();
2465                         i != m_media.end(); ++i) {
2466                 pkt << i->first << i->second.sha1_digest;
2467         }
2468
2469         pkt << g_settings->get("remote_media");
2470         Send(&pkt);
2471 }
2472
2473 struct SendableMedia
2474 {
2475         std::string name;
2476         std::string path;
2477         std::string data;
2478
2479         SendableMedia(const std::string &name_="", const std::string &path_="",
2480                       const std::string &data_=""):
2481                 name(name_),
2482                 path(path_),
2483                 data(data_)
2484         {}
2485 };
2486
2487 void Server::sendRequestedMedia(u16 peer_id,
2488                 const std::vector<std::string> &tosend)
2489 {
2490         DSTACK(FUNCTION_NAME);
2491
2492         verbosestream<<"Server::sendRequestedMedia(): "
2493                         <<"Sending files to client"<<std::endl;
2494
2495         /* Read files */
2496
2497         // Put 5kB in one bunch (this is not accurate)
2498         u32 bytes_per_bunch = 5000;
2499
2500         std::vector< std::vector<SendableMedia> > file_bunches;
2501         file_bunches.push_back(std::vector<SendableMedia>());
2502
2503         u32 file_size_bunch_total = 0;
2504
2505         for(std::vector<std::string>::const_iterator i = tosend.begin();
2506                         i != tosend.end(); ++i) {
2507                 const std::string &name = *i;
2508
2509                 if (m_media.find(name) == m_media.end()) {
2510                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2511                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2512                         continue;
2513                 }
2514
2515                 //TODO get path + name
2516                 std::string tpath = m_media[name].path;
2517
2518                 // Read data
2519                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2520                 if(fis.good() == false){
2521                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2522                                         <<tpath<<"\" for reading"<<std::endl;
2523                         continue;
2524                 }
2525                 std::ostringstream tmp_os(std::ios_base::binary);
2526                 bool bad = false;
2527                 for(;;) {
2528                         char buf[1024];
2529                         fis.read(buf, 1024);
2530                         std::streamsize len = fis.gcount();
2531                         tmp_os.write(buf, len);
2532                         file_size_bunch_total += len;
2533                         if(fis.eof())
2534                                 break;
2535                         if(!fis.good()) {
2536                                 bad = true;
2537                                 break;
2538                         }
2539                 }
2540                 if(bad) {
2541                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2542                                         <<name<<"\""<<std::endl;
2543                         continue;
2544                 }
2545                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2546                                 <<tname<<"\""<<std::endl;*/
2547                 // Put in list
2548                 file_bunches[file_bunches.size()-1].push_back(
2549                                 SendableMedia(name, tpath, tmp_os.str()));
2550
2551                 // Start next bunch if got enough data
2552                 if(file_size_bunch_total >= bytes_per_bunch) {
2553                         file_bunches.push_back(std::vector<SendableMedia>());
2554                         file_size_bunch_total = 0;
2555                 }
2556
2557         }
2558
2559         /* Create and send packets */
2560
2561         u16 num_bunches = file_bunches.size();
2562         for(u16 i = 0; i < num_bunches; i++) {
2563                 /*
2564                         u16 command
2565                         u16 total number of texture bunches
2566                         u16 index of this bunch
2567                         u32 number of files in this bunch
2568                         for each file {
2569                                 u16 length of name
2570                                 string name
2571                                 u32 length of data
2572                                 data
2573                         }
2574                 */
2575
2576                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2577                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2578
2579                 for(std::vector<SendableMedia>::iterator
2580                                 j = file_bunches[i].begin();
2581                                 j != file_bunches[i].end(); ++j) {
2582                         pkt << j->name;
2583                         pkt.putLongString(j->data);
2584                 }
2585
2586                 verbosestream << "Server::sendRequestedMedia(): bunch "
2587                                 << i << "/" << num_bunches
2588                                 << " files=" << file_bunches[i].size()
2589                                 << " size="  << pkt.getSize() << std::endl;
2590                 Send(&pkt);
2591         }
2592 }
2593
2594 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2595 {
2596         if(m_detached_inventories.count(name) == 0) {
2597                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2598                 return;
2599         }
2600         Inventory *inv = m_detached_inventories[name];
2601         std::ostringstream os(std::ios_base::binary);
2602
2603         os << serializeString(name);
2604         inv->serialize(os);
2605
2606         // Make data buffer
2607         std::string s = os.str();
2608
2609         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2610         pkt.putRawString(s.c_str(), s.size());
2611
2612         const std::string &check = m_detached_inventories_player[name];
2613         if (peer_id == PEER_ID_INEXISTENT) {
2614                 if (check == "")
2615                         return m_clients.sendToAll(&pkt);
2616                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2617                 if (p)
2618                         m_clients.send(p->peer_id, 0, &pkt, true);
2619         } else {
2620                 if (check == "" || getPlayerName(peer_id) == check)
2621                         Send(&pkt);
2622         }
2623 }
2624
2625 void Server::sendDetachedInventories(u16 peer_id)
2626 {
2627         DSTACK(FUNCTION_NAME);
2628
2629         for(std::map<std::string, Inventory*>::iterator
2630                         i = m_detached_inventories.begin();
2631                         i != m_detached_inventories.end(); ++i) {
2632                 const std::string &name = i->first;
2633                 //Inventory *inv = i->second;
2634                 sendDetachedInventory(name, peer_id);
2635         }
2636 }
2637
2638 /*
2639         Something random
2640 */
2641
2642 void Server::DiePlayer(u16 peer_id)
2643 {
2644         DSTACK(FUNCTION_NAME);
2645         PlayerSAO *playersao = getPlayerSAO(peer_id);
2646         // In some rare cases this can be NULL -- if the player is disconnected
2647         // when a Lua function modifies l_punch, for example
2648         if (!playersao)
2649                 return;
2650
2651         infostream << "Server::DiePlayer(): Player "
2652                         << playersao->getPlayer()->getName()
2653                         << " dies" << std::endl;
2654
2655         playersao->setHP(0);
2656
2657         // Trigger scripted stuff
2658         m_script->on_dieplayer(playersao);
2659
2660         SendPlayerHP(peer_id);
2661         SendDeathscreen(peer_id, false, v3f(0,0,0));
2662 }
2663
2664 void Server::RespawnPlayer(u16 peer_id)
2665 {
2666         DSTACK(FUNCTION_NAME);
2667
2668         PlayerSAO *playersao = getPlayerSAO(peer_id);
2669         assert(playersao);
2670
2671         infostream << "Server::RespawnPlayer(): Player "
2672                         << playersao->getPlayer()->getName()
2673                         << " respawns" << std::endl;
2674
2675         playersao->setHP(PLAYER_MAX_HP);
2676         playersao->setBreath(PLAYER_MAX_BREATH);
2677
2678         bool repositioned = m_script->on_respawnplayer(playersao);
2679         if (!repositioned) {
2680                 // setPos will send the new position to client
2681                 playersao->setPos(findSpawnPos());
2682         }
2683
2684         SendPlayerHP(peer_id);
2685 }
2686
2687
2688 void Server::DenySudoAccess(u16 peer_id)
2689 {
2690         DSTACK(FUNCTION_NAME);
2691
2692         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2693         Send(&pkt);
2694 }
2695
2696
2697 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2698                 const std::string &str_reason, bool reconnect)
2699 {
2700         if (proto_ver >= 25) {
2701                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2702         } else {
2703                 std::wstring wreason = utf8_to_wide(
2704                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2705                         accessDeniedStrings[(u8)reason]);
2706                 SendAccessDenied_Legacy(peer_id, wreason);
2707         }
2708
2709         m_clients.event(peer_id, CSE_SetDenied);
2710         m_con.DisconnectPeer(peer_id);
2711 }
2712
2713
2714 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2715 {
2716         DSTACK(FUNCTION_NAME);
2717
2718         SendAccessDenied(peer_id, reason, custom_reason);
2719         m_clients.event(peer_id, CSE_SetDenied);
2720         m_con.DisconnectPeer(peer_id);
2721 }
2722
2723 // 13/03/15: remove this function when protocol version 25 will become
2724 // the minimum version for MT users, maybe in 1 year
2725 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2726 {
2727         DSTACK(FUNCTION_NAME);
2728
2729         SendAccessDenied_Legacy(peer_id, reason);
2730         m_clients.event(peer_id, CSE_SetDenied);
2731         m_con.DisconnectPeer(peer_id);
2732 }
2733
2734 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2735 {
2736         DSTACK(FUNCTION_NAME);
2737
2738         if (!forSudoMode) {
2739                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2740
2741                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2742
2743                 // Right now, the auth mechs don't change between login and sudo mode.
2744                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2745                 client->allowed_sudo_mechs = sudo_auth_mechs;
2746
2747                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2748                                 << g_settings->getFloat("dedicated_server_step")
2749                                 << sudo_auth_mechs;
2750
2751                 Send(&resp_pkt);
2752                 m_clients.event(peer_id, CSE_AuthAccept);
2753         } else {
2754                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2755
2756                 // We only support SRP right now
2757                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2758
2759                 resp_pkt << sudo_auth_mechs;
2760                 Send(&resp_pkt);
2761                 m_clients.event(peer_id, CSE_SudoSuccess);
2762         }
2763 }
2764
2765 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2766 {
2767         DSTACK(FUNCTION_NAME);
2768         std::wstring message;
2769         {
2770                 /*
2771                         Clear references to playing sounds
2772                 */
2773                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2774                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2775                         ServerPlayingSound &psound = i->second;
2776                         psound.clients.erase(peer_id);
2777                         if (psound.clients.empty())
2778                                 m_playing_sounds.erase(i++);
2779                         else
2780                                 ++i;
2781                 }
2782
2783                 RemotePlayer *player = m_env->getPlayer(peer_id);
2784
2785                 /* Run scripts and remove from environment */
2786                 if (player != NULL) {
2787                         PlayerSAO *playersao = player->getPlayerSAO();
2788                         assert(playersao);
2789
2790                         // inform connected clients
2791                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2792                         // (u16) 1 + std::string represents a vector serialization representation
2793                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
2794                         m_clients.sendToAll(&notice);
2795                         // run scripts
2796                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2797
2798                         playersao->disconnected();
2799                 }
2800
2801                 /*
2802                         Print out action
2803                 */
2804                 {
2805                         if(player != NULL && reason != CDR_DENY) {
2806                                 std::ostringstream os(std::ios_base::binary);
2807                                 std::vector<u16> clients = m_clients.getClientIDs();
2808
2809                                 for(std::vector<u16>::iterator i = clients.begin();
2810                                         i != clients.end(); ++i) {
2811                                         // Get player
2812                                         RemotePlayer *player = m_env->getPlayer(*i);
2813                                         if (!player)
2814                                                 continue;
2815
2816                                         // Get name of player
2817                                         os << player->getName() << " ";
2818                                 }
2819
2820                                 std::string name = player->getName();
2821                                 actionstream << name << " "
2822                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2823                                                 << " List of players: " << os.str() << std::endl;
2824                                 if (m_admin_chat)
2825                                         m_admin_chat->outgoing_queue.push_back(
2826                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2827                         }
2828                 }
2829                 {
2830                         MutexAutoLock env_lock(m_env_mutex);
2831                         m_clients.DeleteClient(peer_id);
2832                 }
2833         }
2834
2835         // Send leave chat message to all remaining clients
2836         if(message.length() != 0)
2837                 SendChatMessage(PEER_ID_INEXISTENT,message);
2838 }
2839
2840 void Server::UpdateCrafting(RemotePlayer *player)
2841 {
2842         DSTACK(FUNCTION_NAME);
2843
2844         // Get a preview for crafting
2845         ItemStack preview;
2846         InventoryLocation loc;
2847         loc.setPlayer(player->getName());
2848         std::vector<ItemStack> output_replacements;
2849         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2850         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2851                         (&player->inventory)->getList("craft"), loc);
2852
2853         // Put the new preview in
2854         InventoryList *plist = player->inventory.getList("craftpreview");
2855         sanity_check(plist);
2856         sanity_check(plist->getSize() >= 1);
2857         plist->changeItem(0, preview);
2858 }
2859
2860 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2861 {
2862         if (evt->type == CET_NICK_ADD) {
2863                 // The terminal informed us of its nick choice
2864                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2865                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2866                         errorstream << "You haven't set up an account." << std::endl
2867                                 << "Please log in using the client as '"
2868                                 << m_admin_nick << "' with a secure password." << std::endl
2869                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2870                                 << "and everybody can claim the user account instead of you," << std::endl
2871                                 << "giving them full control over this server." << std::endl;
2872                 }
2873         } else {
2874                 assert(evt->type == CET_CHAT);
2875                 handleAdminChat((ChatEventChat *)evt);
2876         }
2877 }
2878
2879 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2880         const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
2881 {
2882         // If something goes wrong, this player is to blame
2883         RollbackScopeActor rollback_scope(m_rollback,
2884                 std::string("player:") + name);
2885
2886         if (player) {
2887                 switch (player->canSendChatMessage()) {
2888                         case RPLAYER_CHATRESULT_FLOODING: {
2889                                 std::wstringstream ws;
2890                                 ws << L"You cannot send more messages. You are limited to "
2891                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2892                                    << L" messages per 10 seconds.";
2893                                 return ws.str();
2894                         }
2895                         case RPLAYER_CHATRESULT_KICK:
2896                                 DenyAccess_Legacy(player->peer_id,
2897                                                 L"You have been kicked due to message flooding.");
2898                                 return L"";
2899                         case RPLAYER_CHATRESULT_OK:
2900                                 break;
2901                         default:
2902                                 FATAL_ERROR("Unhandled chat filtering result found.");
2903                 }
2904         }
2905
2906         if (m_max_chatmessage_length > 0
2907                         && wmessage.length() > m_max_chatmessage_length) {
2908                 return L"Your message exceed the maximum chat message limit set on the server. "
2909                                 L"It was refused. Send a shorter message";
2910         }
2911
2912         // Run script hook, exit if script ate the chat message
2913         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2914                 return L"";
2915
2916         // Line to send
2917         std::wstring line;
2918         // Whether to send line to the player that sent the message, or to all players
2919         bool broadcast_line = true;
2920
2921         if (check_shout_priv && !checkPriv(name, "shout")) {
2922                 line += L"-!- You don't have permission to shout.";
2923                 broadcast_line = false;
2924         } else {
2925                 line += L"<";
2926                 line += wname;
2927                 line += L"> ";
2928                 line += wmessage;
2929         }
2930
2931         /*
2932                 Tell calling method to send the message to sender
2933         */
2934         if (!broadcast_line) {
2935                 return line;
2936         } else {
2937                 /*
2938                         Send the message to others
2939                 */
2940                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2941
2942                 std::vector<u16> clients = m_clients.getClientIDs();
2943
2944                 /*
2945                         Send the message back to the inital sender
2946                         if they are using protocol version >= 29
2947                 */
2948
2949                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2950                 if (player && player->protocol_version >= 29)
2951                         peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2952
2953                 for (u16 i = 0; i < clients.size(); i++) {
2954                         u16 cid = clients[i];
2955                         if (cid != peer_id_to_avoid_sending)
2956                                 SendChatMessage(cid, line);
2957                 }
2958         }
2959         return L"";
2960 }
2961
2962 void Server::handleAdminChat(const ChatEventChat *evt)
2963 {
2964         std::string name = evt->nick;
2965         std::wstring wname = utf8_to_wide(name);
2966         std::wstring wmessage = evt->evt_msg;
2967
2968         std::wstring answer = handleChat(name, wname, wmessage);
2969
2970         // If asked to send answer to sender
2971         if (!answer.empty()) {
2972                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2973         }
2974 }
2975
2976 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2977 {
2978         RemoteClient *client = getClientNoEx(peer_id,state_min);
2979         if(!client)
2980                 throw ClientNotFoundException("Client not found");
2981
2982         return client;
2983 }
2984 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2985 {
2986         return m_clients.getClientNoEx(peer_id, state_min);
2987 }
2988
2989 std::string Server::getPlayerName(u16 peer_id)
2990 {
2991         RemotePlayer *player = m_env->getPlayer(peer_id);
2992         if (player == NULL)
2993                 return "[id="+itos(peer_id)+"]";
2994         return player->getName();
2995 }
2996
2997 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2998 {
2999         RemotePlayer *player = m_env->getPlayer(peer_id);
3000         if (player == NULL)
3001                 return NULL;
3002         return player->getPlayerSAO();
3003 }
3004
3005 std::wstring Server::getStatusString()
3006 {
3007         std::wostringstream os(std::ios_base::binary);
3008         os<<L"# Server: ";
3009         // Version
3010         os<<L"version="<<narrow_to_wide(g_version_string);
3011         // Uptime
3012         os<<L", uptime="<<m_uptime.get();
3013         // Max lag estimate
3014         os<<L", max_lag="<<m_env->getMaxLagEstimate();
3015         // Information about clients
3016         bool first = true;
3017         os<<L", clients={";
3018         std::vector<u16> clients = m_clients.getClientIDs();
3019         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
3020                 // Get player
3021                 RemotePlayer *player = m_env->getPlayer(*i);
3022                 // Get name of player
3023                 std::wstring name = L"unknown";
3024                 if (player != NULL)
3025                         name = narrow_to_wide(player->getName());
3026                 // Add name to information string
3027                 if(!first)
3028                         os << L", ";
3029                 else
3030                         first = false;
3031                 os << name;
3032         }
3033         os << L"}";
3034         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
3035                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
3036         if(g_settings->get("motd") != "")
3037                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
3038         return os.str();
3039 }
3040
3041 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3042 {
3043         std::set<std::string> privs;
3044         m_script->getAuth(name, NULL, &privs);
3045         return privs;
3046 }
3047
3048 bool Server::checkPriv(const std::string &name, const std::string &priv)
3049 {
3050         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3051         return (privs.count(priv) != 0);
3052 }
3053
3054 void Server::reportPrivsModified(const std::string &name)
3055 {
3056         if(name == "") {
3057                 std::vector<u16> clients = m_clients.getClientIDs();
3058                 for(std::vector<u16>::iterator i = clients.begin();
3059                                 i != clients.end(); ++i) {
3060                         RemotePlayer *player = m_env->getPlayer(*i);
3061                         reportPrivsModified(player->getName());
3062                 }
3063         } else {
3064                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3065                 if (!player)
3066                         return;
3067                 SendPlayerPrivileges(player->peer_id);
3068                 PlayerSAO *sao = player->getPlayerSAO();
3069                 if(!sao)
3070                         return;
3071                 sao->updatePrivileges(
3072                                 getPlayerEffectivePrivs(name),
3073                                 isSingleplayer());
3074         }
3075 }
3076
3077 void Server::reportInventoryFormspecModified(const std::string &name)
3078 {
3079         RemotePlayer *player = m_env->getPlayer(name.c_str());
3080         if (!player)
3081                 return;
3082         SendPlayerInventoryFormspec(player->peer_id);
3083 }
3084
3085 void Server::setIpBanned(const std::string &ip, const std::string &name)
3086 {
3087         m_banmanager->add(ip, name);
3088 }
3089
3090 void Server::unsetIpBanned(const std::string &ip_or_name)
3091 {
3092         m_banmanager->remove(ip_or_name);
3093 }
3094
3095 std::string Server::getBanDescription(const std::string &ip_or_name)
3096 {
3097         return m_banmanager->getBanDescription(ip_or_name);
3098 }
3099
3100 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3101 {
3102         // m_env will be NULL if the server is initializing
3103         if (!m_env)
3104                 return;
3105
3106         if (m_admin_nick == name && !m_admin_nick.empty()) {
3107                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3108         }
3109
3110         RemotePlayer *player = m_env->getPlayer(name);
3111         if (!player) {
3112                 return;
3113         }
3114
3115         if (player->peer_id == PEER_ID_INEXISTENT)
3116                 return;
3117
3118         SendChatMessage(player->peer_id, msg);
3119 }
3120
3121 bool Server::showFormspec(const char *playername, const std::string &formspec,
3122         const std::string &formname)
3123 {
3124         // m_env will be NULL if the server is initializing
3125         if (!m_env)
3126                 return false;
3127
3128         RemotePlayer *player = m_env->getPlayer(playername);
3129         if (!player)
3130                 return false;
3131
3132         SendShowFormspecMessage(player->peer_id, formspec, formname);
3133         return true;
3134 }
3135
3136 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3137 {
3138         if (!player)
3139                 return -1;
3140
3141         u32 id = player->addHud(form);
3142
3143         SendHUDAdd(player->peer_id, id, form);
3144
3145         return id;
3146 }
3147
3148 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3149         if (!player)
3150                 return false;
3151
3152         HudElement* todel = player->removeHud(id);
3153
3154         if (!todel)
3155                 return false;
3156
3157         delete todel;
3158
3159         SendHUDRemove(player->peer_id, id);
3160         return true;
3161 }
3162
3163 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3164 {
3165         if (!player)
3166                 return false;
3167
3168         SendHUDChange(player->peer_id, id, stat, data);
3169         return true;
3170 }
3171
3172 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3173 {
3174         if (!player)
3175                 return false;
3176
3177         SendHUDSetFlags(player->peer_id, flags, mask);
3178         player->hud_flags &= ~mask;
3179         player->hud_flags |= flags;
3180
3181         PlayerSAO* playersao = player->getPlayerSAO();
3182
3183         if (playersao == NULL)
3184                 return false;
3185
3186         m_script->player_event(playersao, "hud_changed");
3187         return true;
3188 }
3189
3190 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3191 {
3192         if (!player)
3193                 return false;
3194
3195         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3196                 return false;
3197
3198         player->setHotbarItemcount(hotbar_itemcount);
3199         std::ostringstream os(std::ios::binary);
3200         writeS32(os, hotbar_itemcount);
3201         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3202         return true;
3203 }
3204
3205 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3206 {
3207         if (!player)
3208                 return;
3209
3210         player->setHotbarImage(name);
3211         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3212 }
3213
3214 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3215 {
3216         if (!player)
3217                 return "";
3218         return player->getHotbarImage();
3219 }
3220
3221 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3222 {
3223         if (!player)
3224                 return;
3225
3226         player->setHotbarSelectedImage(name);
3227         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3228 }
3229
3230 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3231                 v2s32 animation_frames[4], f32 frame_speed)
3232 {
3233         if (!player)
3234                 return false;
3235
3236         player->setLocalAnimations(animation_frames, frame_speed);
3237         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3238         return true;
3239 }
3240
3241 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3242 {
3243         if (!player)
3244                 return false;
3245
3246         player->eye_offset_first = first;
3247         player->eye_offset_third = third;
3248         SendEyeOffset(player->peer_id, first, third);
3249         return true;
3250 }
3251
3252 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3253         const std::string &type, const std::vector<std::string> &params,
3254         bool &clouds)
3255 {
3256         if (!player)
3257                 return false;
3258
3259         player->setSky(bgcolor, type, params, clouds);
3260         SendSetSky(player->peer_id, bgcolor, type, params, clouds);
3261         return true;
3262 }
3263
3264 bool Server::setClouds(RemotePlayer *player, float density,
3265         const video::SColor &color_bright,
3266         const video::SColor &color_ambient,
3267         float height,
3268         float thickness,
3269         const v2f &speed)
3270 {
3271         if (!player)
3272                 return false;
3273
3274         SendCloudParams(player->peer_id, density,
3275                         color_bright, color_ambient, height,
3276                         thickness, speed);
3277         return true;
3278 }
3279
3280 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3281         float ratio)
3282 {
3283         if (!player)
3284                 return false;
3285
3286         player->overrideDayNightRatio(do_override, ratio);
3287         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3288         return true;
3289 }
3290
3291 void Server::notifyPlayers(const std::wstring &msg)
3292 {
3293         SendChatMessage(PEER_ID_INEXISTENT,msg);
3294 }
3295
3296 void Server::spawnParticle(const std::string &playername, v3f pos,
3297         v3f velocity, v3f acceleration,
3298         float expirationtime, float size, bool
3299         collisiondetection, bool collision_removal,
3300         bool vertical, const std::string &texture,
3301         const struct TileAnimationParams &animation, u8 glow)
3302 {
3303         // m_env will be NULL if the server is initializing
3304         if (!m_env)
3305                 return;
3306
3307         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3308         if (playername != "") {
3309                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3310                 if (!player)
3311                         return;
3312                 peer_id = player->peer_id;
3313                 proto_ver = player->protocol_version;
3314         }
3315
3316         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3317                         expirationtime, size, collisiondetection,
3318                         collision_removal, vertical, texture, animation, glow);
3319 }
3320
3321 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3322         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3323         float minexptime, float maxexptime, float minsize, float maxsize,
3324         bool collisiondetection, bool collision_removal,
3325         ServerActiveObject *attached, bool vertical, const std::string &texture,
3326         const std::string &playername, const struct TileAnimationParams &animation,
3327         u8 glow)
3328 {
3329         // m_env will be NULL if the server is initializing
3330         if (!m_env)
3331                 return -1;
3332
3333         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3334         if (playername != "") {
3335                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3336                 if (!player)
3337                         return -1;
3338                 peer_id = player->peer_id;
3339                 proto_ver = player->protocol_version;
3340         }
3341
3342         u16 attached_id = attached ? attached->getId() : 0;
3343
3344         u32 id;
3345         if (attached_id == 0)
3346                 id = m_env->addParticleSpawner(spawntime);
3347         else
3348                 id = m_env->addParticleSpawner(spawntime, attached_id);
3349
3350         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3351                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3352                 minexptime, maxexptime, minsize, maxsize,
3353                 collisiondetection, collision_removal, attached_id, vertical,
3354                 texture, id, animation, glow);
3355
3356         return id;
3357 }
3358
3359 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3360 {
3361         // m_env will be NULL if the server is initializing
3362         if (!m_env)
3363                 throw ServerError("Can't delete particle spawners during initialisation!");
3364
3365         u16 peer_id = PEER_ID_INEXISTENT;
3366         if (playername != "") {
3367                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3368                 if (!player)
3369                         return;
3370                 peer_id = player->peer_id;
3371         }
3372
3373         m_env->deleteParticleSpawner(id);
3374         SendDeleteParticleSpawner(peer_id, id);
3375 }
3376
3377 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3378 {
3379         if(m_detached_inventories.count(name) > 0){
3380                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3381                 delete m_detached_inventories[name];
3382         } else {
3383                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3384         }
3385         Inventory *inv = new Inventory(m_itemdef);
3386         sanity_check(inv);
3387         m_detached_inventories[name] = inv;
3388         m_detached_inventories_player[name] = player;
3389         //TODO find a better way to do this
3390         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3391         return inv;
3392 }
3393
3394 // actions: time-reversed list
3395 // Return value: success/failure
3396 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3397                 std::list<std::string> *log)
3398 {
3399         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3400         ServerMap *map = (ServerMap*)(&m_env->getMap());
3401
3402         // Fail if no actions to handle
3403         if(actions.empty()){
3404                 log->push_back("Nothing to do.");
3405                 return false;
3406         }
3407
3408         int num_tried = 0;
3409         int num_failed = 0;
3410
3411         for(std::list<RollbackAction>::const_iterator
3412                         i = actions.begin();
3413                         i != actions.end(); ++i)
3414         {
3415                 const RollbackAction &action = *i;
3416                 num_tried++;
3417                 bool success = action.applyRevert(map, this, this);
3418                 if(!success){
3419                         num_failed++;
3420                         std::ostringstream os;
3421                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3422                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3423                         if(log)
3424                                 log->push_back(os.str());
3425                 }else{
3426                         std::ostringstream os;
3427                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3428                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3429                         if(log)
3430                                 log->push_back(os.str());
3431                 }
3432         }
3433
3434         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3435                         <<" failed"<<std::endl;
3436
3437         // Call it done if less than half failed
3438         return num_failed <= num_tried/2;
3439 }
3440
3441 // IGameDef interface
3442 // Under envlock
3443 IItemDefManager *Server::getItemDefManager()
3444 {
3445         return m_itemdef;
3446 }
3447
3448 INodeDefManager *Server::getNodeDefManager()
3449 {
3450         return m_nodedef;
3451 }
3452
3453 ICraftDefManager *Server::getCraftDefManager()
3454 {
3455         return m_craftdef;
3456 }
3457
3458 u16 Server::allocateUnknownNodeId(const std::string &name)
3459 {
3460         return m_nodedef->allocateDummy(name);
3461 }
3462
3463 MtEventManager *Server::getEventManager()
3464 {
3465         return m_event;
3466 }
3467
3468 IWritableItemDefManager *Server::getWritableItemDefManager()
3469 {
3470         return m_itemdef;
3471 }
3472
3473 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3474 {
3475         return m_nodedef;
3476 }
3477
3478 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3479 {
3480         return m_craftdef;
3481 }
3482
3483 const ModSpec *Server::getModSpec(const std::string &modname) const
3484 {
3485         std::vector<ModSpec>::const_iterator it;
3486         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3487                 const ModSpec &mod = *it;
3488                 if (mod.name == modname)
3489                         return &mod;
3490         }
3491         return NULL;
3492 }
3493
3494 void Server::getModNames(std::vector<std::string> &modlist)
3495 {
3496         std::vector<ModSpec>::iterator it;
3497         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3498                 modlist.push_back(it->name);
3499 }
3500
3501 std::string Server::getBuiltinLuaPath()
3502 {
3503         return porting::path_share + DIR_DELIM + "builtin";
3504 }
3505
3506 std::string Server::getModStoragePath() const
3507 {
3508         return m_path_world + DIR_DELIM + "mod_storage";
3509 }
3510
3511 v3f Server::findSpawnPos()
3512 {
3513         ServerMap &map = m_env->getServerMap();
3514         v3f nodeposf;
3515         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3516                 return nodeposf * BS;
3517         }
3518
3519         bool is_good = false;
3520
3521         // Try to find a good place a few times
3522         for(s32 i = 0; i < 4000 && !is_good; i++) {
3523                 s32 range = 1 + i;
3524                 // We're going to try to throw the player to this position
3525                 v2s16 nodepos2d = v2s16(
3526                         -range + (myrand() % (range * 2)),
3527                         -range + (myrand() % (range * 2)));
3528
3529                 // Get spawn level at point
3530                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3531                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3532                 // the mapgen to signify an unsuitable spawn position
3533                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3534                         continue;
3535
3536                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3537
3538                 s32 air_count = 0;
3539                 for (s32 i = 0; i < 10; i++) {
3540                         v3s16 blockpos = getNodeBlockPos(nodepos);
3541                         map.emergeBlock(blockpos, true);
3542                         content_t c = map.getNodeNoEx(nodepos).getContent();
3543                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3544                                 air_count++;
3545                                 if (air_count >= 2) {
3546                                         nodeposf = intToFloat(nodepos, BS);
3547                                         // Don't spawn the player outside map boundaries
3548                                         if (objectpos_over_limit(nodeposf))
3549                                                 continue;
3550                                         is_good = true;
3551                                         break;
3552                                 }
3553                         }
3554                         nodepos.Y++;
3555                 }
3556         }
3557
3558         return nodeposf;
3559 }
3560
3561 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3562 {
3563         m_shutdown_timer = delay;
3564         m_shutdown_msg = msg;
3565         m_shutdown_ask_reconnect = reconnect;
3566
3567         if (delay == 0.0f) {
3568         // No delay, shutdown immediately
3569                 m_shutdown_requested = true;
3570                 // only print to the infostream, a chat message saying
3571                 // "Server Shutting Down" is sent when the server destructs.
3572                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3573         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3574         // Negative delay, cancel shutdown if requested
3575                 m_shutdown_timer = 0.0f;
3576                 m_shutdown_msg = "";
3577                 m_shutdown_ask_reconnect = false;
3578                 m_shutdown_requested = false;
3579                 std::wstringstream ws;
3580
3581                 ws << L"*** Server shutdown canceled.";
3582
3583                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3584                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3585         } else if (delay > 0.0f) {
3586         // Positive delay, tell the clients when the server will shut down
3587                 std::wstringstream ws;
3588
3589                 ws << L"*** Server shutting down in "
3590                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3591                                 << ".";
3592
3593                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3594                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3595         }
3596 }
3597
3598 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3599 {
3600         /*
3601                 Try to get an existing player
3602         */
3603         RemotePlayer *player = m_env->getPlayer(name);
3604
3605         // If player is already connected, cancel
3606         if (player != NULL && player->peer_id != 0) {
3607                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3608                 return NULL;
3609         }
3610
3611         /*
3612                 If player with the wanted peer_id already exists, cancel.
3613         */
3614         if (m_env->getPlayer(peer_id) != NULL) {
3615                 infostream<<"emergePlayer(): Player with wrong name but same"
3616                                 " peer_id already exists"<<std::endl;
3617                 return NULL;
3618         }
3619
3620         if (!player) {
3621                 player = new RemotePlayer(name, idef());
3622         }
3623
3624         bool newplayer = false;
3625
3626         // Load player
3627         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3628
3629         // Complete init with server parts
3630         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3631         player->protocol_version = proto_version;
3632
3633         /* Run scripts */
3634         if (newplayer) {
3635                 m_script->on_newplayer(playersao);
3636         }
3637
3638         return playersao;
3639 }
3640
3641 bool Server::registerModStorage(ModMetadata *storage)
3642 {
3643         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3644                 errorstream << "Unable to register same mod storage twice. Storage name: "
3645                                 << storage->getModName() << std::endl;
3646                 return false;
3647         }
3648
3649         m_mod_storages[storage->getModName()] = storage;
3650         return true;
3651 }
3652
3653 void Server::unregisterModStorage(const std::string &name)
3654 {
3655         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3656         if (it != m_mod_storages.end()) {
3657                 // Save unconditionaly on unregistration
3658                 it->second->save(getModStoragePath());
3659                 m_mod_storages.erase(name);
3660         }
3661 }
3662
3663 void dedicated_server_loop(Server &server, bool &kill)
3664 {
3665         DSTACK(FUNCTION_NAME);
3666
3667         verbosestream<<"dedicated_server_loop()"<<std::endl;
3668
3669         IntervalLimiter m_profiler_interval;
3670
3671         static const float steplen = g_settings->getFloat("dedicated_server_step");
3672         static const float profiler_print_interval =
3673                         g_settings->getFloat("profiler_print_interval");
3674
3675         for(;;) {
3676                 // This is kind of a hack but can be done like this
3677                 // because server.step() is very light
3678                 {
3679                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3680                         sleep_ms((int)(steplen*1000.0));
3681                 }
3682                 server.step(steplen);
3683
3684                 if (server.getShutdownRequested() || kill)
3685                         break;
3686
3687                 /*
3688                         Profiler
3689                 */
3690                 if (profiler_print_interval != 0) {
3691                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3692                         {
3693                                 infostream<<"Profiler:"<<std::endl;
3694                                 g_profiler->print(infostream);
3695                                 g_profiler->clear();
3696                         }
3697                 }
3698         }
3699
3700         infostream << "Dedicated server quitting" << std::endl;
3701 #if USE_CURL
3702         if (g_settings->getBool("server_announce"))
3703                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3704                         server.m_bind_addr.getPort());
3705 #endif
3706 }