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