]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Send cumulated inventory changes only each step (#8856)
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/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)
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                 // Updates are sent in ServerEnvironment::step()
1252         }
1253                 break;
1254         case InventoryLocation::NODEMETA:
1255         {
1256                 MapEditEvent event;
1257                 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1258                 event.p = loc.p;
1259                 m_env->getMap().dispatchEvent(&event);
1260         }
1261                 break;
1262         case InventoryLocation::DETACHED:
1263         {
1264                 // Updates are sent in ServerEnvironment::step()
1265         }
1266                 break;
1267         default:
1268                 sanity_check(false); // abort
1269                 break;
1270         }
1271 }
1272
1273 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1274 {
1275         std::vector<session_t> clients = m_clients.getClientIDs();
1276         m_clients.lock();
1277         // Set the modified blocks unsent for all the clients
1278         for (const session_t client_id : clients) {
1279                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(client_id))
1280                                 client->SetBlocksNotSent(block);
1281         }
1282         m_clients.unlock();
1283 }
1284
1285 void Server::peerAdded(con::Peer *peer)
1286 {
1287         verbosestream<<"Server::peerAdded(): peer->id="
1288                         <<peer->id<<std::endl;
1289
1290         m_peer_change_queue.push(con::PeerChange(con::PEER_ADDED, peer->id, false));
1291 }
1292
1293 void Server::deletingPeer(con::Peer *peer, bool timeout)
1294 {
1295         verbosestream<<"Server::deletingPeer(): peer->id="
1296                         <<peer->id<<", timeout="<<timeout<<std::endl;
1297
1298         m_clients.event(peer->id, CSE_Disconnect);
1299         m_peer_change_queue.push(con::PeerChange(con::PEER_REMOVED, peer->id, timeout));
1300 }
1301
1302 bool Server::getClientConInfo(session_t peer_id, con::rtt_stat_type type, float* retval)
1303 {
1304         *retval = m_con->getPeerStat(peer_id,type);
1305         return *retval != -1;
1306 }
1307
1308 bool Server::getClientInfo(
1309                 session_t    peer_id,
1310                 ClientState* state,
1311                 u32*         uptime,
1312                 u8*          ser_vers,
1313                 u16*         prot_vers,
1314                 u8*          major,
1315                 u8*          minor,
1316                 u8*          patch,
1317                 std::string* vers_string
1318         )
1319 {
1320         *state = m_clients.getClientState(peer_id);
1321         m_clients.lock();
1322         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1323
1324         if (!client) {
1325                 m_clients.unlock();
1326                 return false;
1327         }
1328
1329         *uptime = client->uptime();
1330         *ser_vers = client->serialization_version;
1331         *prot_vers = client->net_proto_version;
1332
1333         *major = client->getMajor();
1334         *minor = client->getMinor();
1335         *patch = client->getPatch();
1336         *vers_string = client->getPatch();
1337
1338         m_clients.unlock();
1339
1340         return true;
1341 }
1342
1343 void Server::handlePeerChanges()
1344 {
1345         while(!m_peer_change_queue.empty())
1346         {
1347                 con::PeerChange c = m_peer_change_queue.front();
1348                 m_peer_change_queue.pop();
1349
1350                 verbosestream<<"Server: Handling peer change: "
1351                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1352                                 <<std::endl;
1353
1354                 switch(c.type)
1355                 {
1356                 case con::PEER_ADDED:
1357                         m_clients.CreateClient(c.peer_id);
1358                         break;
1359
1360                 case con::PEER_REMOVED:
1361                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1362                         break;
1363
1364                 default:
1365                         FATAL_ERROR("Invalid peer change event received!");
1366                         break;
1367                 }
1368         }
1369 }
1370
1371 void Server::printToConsoleOnly(const std::string &text)
1372 {
1373         if (m_admin_chat) {
1374                 m_admin_chat->outgoing_queue.push_back(
1375                         new ChatEventChat("", utf8_to_wide(text)));
1376         } else {
1377                 std::cout << text << std::endl;
1378         }
1379 }
1380
1381 void Server::Send(NetworkPacket *pkt)
1382 {
1383         Send(pkt->getPeerId(), pkt);
1384 }
1385
1386 void Server::Send(session_t peer_id, NetworkPacket *pkt)
1387 {
1388         m_clients.send(peer_id,
1389                 clientCommandFactoryTable[pkt->getCommand()].channel,
1390                 pkt,
1391                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1392 }
1393
1394 void Server::SendMovement(session_t peer_id)
1395 {
1396         std::ostringstream os(std::ios_base::binary);
1397
1398         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1399
1400         pkt << g_settings->getFloat("movement_acceleration_default");
1401         pkt << g_settings->getFloat("movement_acceleration_air");
1402         pkt << g_settings->getFloat("movement_acceleration_fast");
1403         pkt << g_settings->getFloat("movement_speed_walk");
1404         pkt << g_settings->getFloat("movement_speed_crouch");
1405         pkt << g_settings->getFloat("movement_speed_fast");
1406         pkt << g_settings->getFloat("movement_speed_climb");
1407         pkt << g_settings->getFloat("movement_speed_jump");
1408         pkt << g_settings->getFloat("movement_liquid_fluidity");
1409         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1410         pkt << g_settings->getFloat("movement_liquid_sink");
1411         pkt << g_settings->getFloat("movement_gravity");
1412
1413         Send(&pkt);
1414 }
1415
1416 void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
1417 {
1418         if (playersao->isImmortal())
1419                 return;
1420
1421         session_t peer_id = playersao->getPeerID();
1422         bool is_alive = playersao->getHP() > 0;
1423
1424         if (is_alive)
1425                 SendPlayerHP(peer_id);
1426         else
1427                 DiePlayer(peer_id, reason);
1428 }
1429
1430 void Server::SendHP(session_t peer_id, u16 hp)
1431 {
1432         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1433         pkt << hp;
1434         Send(&pkt);
1435 }
1436
1437 void Server::SendBreath(session_t peer_id, u16 breath)
1438 {
1439         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1440         pkt << (u16) breath;
1441         Send(&pkt);
1442 }
1443
1444 void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
1445                 const std::string &custom_reason, bool reconnect)
1446 {
1447         assert(reason < SERVER_ACCESSDENIED_MAX);
1448
1449         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1450         pkt << (u8)reason;
1451         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1452                 pkt << custom_reason;
1453         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1454                         reason == SERVER_ACCESSDENIED_CRASH)
1455                 pkt << custom_reason << (u8)reconnect;
1456         Send(&pkt);
1457 }
1458
1459 void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reason)
1460 {
1461         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1462         pkt << reason;
1463         Send(&pkt);
1464 }
1465
1466 void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
1467                 v3f camera_point_target)
1468 {
1469         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1470         pkt << set_camera_point_target << camera_point_target;
1471         Send(&pkt);
1472 }
1473
1474 void Server::SendItemDef(session_t peer_id,
1475                 IItemDefManager *itemdef, u16 protocol_version)
1476 {
1477         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1478
1479         /*
1480                 u16 command
1481                 u32 length of the next item
1482                 zlib-compressed serialized ItemDefManager
1483         */
1484         std::ostringstream tmp_os(std::ios::binary);
1485         itemdef->serialize(tmp_os, protocol_version);
1486         std::ostringstream tmp_os2(std::ios::binary);
1487         compressZlib(tmp_os.str(), tmp_os2);
1488         pkt.putLongString(tmp_os2.str());
1489
1490         // Make data buffer
1491         verbosestream << "Server: Sending item definitions to id(" << peer_id
1492                         << "): size=" << pkt.getSize() << std::endl;
1493
1494         Send(&pkt);
1495 }
1496
1497 void Server::SendNodeDef(session_t peer_id,
1498         const NodeDefManager *nodedef, u16 protocol_version)
1499 {
1500         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1501
1502         /*
1503                 u16 command
1504                 u32 length of the next item
1505                 zlib-compressed serialized NodeDefManager
1506         */
1507         std::ostringstream tmp_os(std::ios::binary);
1508         nodedef->serialize(tmp_os, protocol_version);
1509         std::ostringstream tmp_os2(std::ios::binary);
1510         compressZlib(tmp_os.str(), tmp_os2);
1511
1512         pkt.putLongString(tmp_os2.str());
1513
1514         // Make data buffer
1515         verbosestream << "Server: Sending node definitions to id(" << peer_id
1516                         << "): size=" << pkt.getSize() << std::endl;
1517
1518         Send(&pkt);
1519 }
1520
1521 /*
1522         Non-static send methods
1523 */
1524
1525 void Server::SendInventory(PlayerSAO *sao, bool incremental)
1526 {
1527         RemotePlayer *player = sao->getPlayer();
1528
1529         // Do not send new format to old clients
1530         incremental &= player->protocol_version >= 38;
1531
1532         UpdateCrafting(player);
1533
1534         /*
1535                 Serialize it
1536         */
1537
1538         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, sao->getPeerID());
1539
1540         std::ostringstream os(std::ios::binary);
1541         sao->getInventory()->serialize(os, incremental);
1542         sao->getInventory()->setModified(false);
1543         player->setModified(true);
1544
1545         const std::string &s = os.str();
1546         pkt.putRawString(s.c_str(), s.size());
1547         Send(&pkt);
1548 }
1549
1550 void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
1551 {
1552         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1553         u8 version = 1;
1554         u8 type = message.type;
1555         pkt << version << type << std::wstring(L"") << message.message << (u64)message.timestamp;
1556
1557         if (peer_id != PEER_ID_INEXISTENT) {
1558                 RemotePlayer *player = m_env->getPlayer(peer_id);
1559                 if (!player)
1560                         return;
1561
1562                 Send(&pkt);
1563         } else {
1564                 m_clients.sendToAll(&pkt);
1565         }
1566 }
1567
1568 void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
1569         const std::string &formname)
1570 {
1571         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1572         if (formspec.empty()){
1573                 //the client should close the formspec
1574                 //but make sure there wasn't another one open in meantime
1575                 const auto it = m_formspec_state_data.find(peer_id);
1576                 if (it != m_formspec_state_data.end() && it->second == formname) {
1577                         m_formspec_state_data.erase(peer_id);
1578                 }
1579                 pkt.putLongString("");
1580         } else {
1581                 m_formspec_state_data[peer_id] = formname;
1582                 pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1583         }
1584         pkt << formname;
1585
1586         Send(&pkt);
1587 }
1588
1589 // Spawns a particle on peer with peer_id
1590 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
1591                                 v3f pos, v3f velocity, v3f acceleration,
1592                                 float expirationtime, float size, bool collisiondetection,
1593                                 bool collision_removal, bool object_collision,
1594                                 bool vertical, const std::string &texture,
1595                                 const struct TileAnimationParams &animation, u8 glow)
1596 {
1597         static thread_local const float radius =
1598                         g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1599
1600         if (peer_id == PEER_ID_INEXISTENT) {
1601                 std::vector<session_t> clients = m_clients.getClientIDs();
1602
1603                 for (const session_t client_id : clients) {
1604                         RemotePlayer *player = m_env->getPlayer(client_id);
1605                         if (!player)
1606                                 continue;
1607
1608                         PlayerSAO *sao = player->getPlayerSAO();
1609                         if (!sao)
1610                                 continue;
1611
1612                         // Do not send to distant clients
1613                         if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
1614                                 continue;
1615
1616                         SendSpawnParticle(client_id, player->protocol_version,
1617                                         pos, velocity, acceleration,
1618                                         expirationtime, size, collisiondetection, collision_removal,
1619                                         object_collision, vertical, texture, animation, glow);
1620                 }
1621                 return;
1622         }
1623
1624         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1625
1626         pkt << pos << velocity << acceleration << expirationtime
1627                         << size << collisiondetection;
1628         pkt.putLongString(texture);
1629         pkt << vertical;
1630         pkt << collision_removal;
1631         // This is horrible but required (why are there two ways to serialize pkts?)
1632         std::ostringstream os(std::ios_base::binary);
1633         animation.serialize(os, protocol_version);
1634         pkt.putRawString(os.str());
1635         pkt << glow;
1636         pkt << object_collision;
1637
1638         Send(&pkt);
1639 }
1640
1641 // Adds a ParticleSpawner on peer with peer_id
1642 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
1643         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1644         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1645         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1646         bool object_collision, u16 attached_id, bool vertical, const std::string &texture, u32 id,
1647         const struct TileAnimationParams &animation, u8 glow)
1648 {
1649         if (peer_id == PEER_ID_INEXISTENT) {
1650                 // This sucks and should be replaced:
1651                 std::vector<session_t> clients = m_clients.getClientIDs();
1652                 for (const session_t client_id : clients) {
1653                         RemotePlayer *player = m_env->getPlayer(client_id);
1654                         if (!player)
1655                                 continue;
1656                         SendAddParticleSpawner(client_id, player->protocol_version,
1657                                         amount, spawntime, minpos, maxpos,
1658                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1659                                         minsize, maxsize, collisiondetection, collision_removal,
1660                                         object_collision, attached_id, vertical, texture, id,
1661                                         animation, glow);
1662                 }
1663                 return;
1664         }
1665
1666         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1667
1668         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1669                         << minacc << maxacc << minexptime << maxexptime << minsize
1670                         << maxsize << collisiondetection;
1671
1672         pkt.putLongString(texture);
1673
1674         pkt << id << vertical;
1675         pkt << collision_removal;
1676         pkt << attached_id;
1677         // This is horrible but required
1678         std::ostringstream os(std::ios_base::binary);
1679         animation.serialize(os, protocol_version);
1680         pkt.putRawString(os.str());
1681         pkt << glow;
1682         pkt << object_collision;
1683
1684         Send(&pkt);
1685 }
1686
1687 void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
1688 {
1689         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
1690
1691         // Ugly error in this packet
1692         pkt << id;
1693
1694         if (peer_id != PEER_ID_INEXISTENT)
1695                 Send(&pkt);
1696         else
1697                 m_clients.sendToAll(&pkt);
1698
1699 }
1700
1701 void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
1702 {
1703         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1704
1705         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1706                         << form->text << form->number << form->item << form->dir
1707                         << form->align << form->offset << form->world_pos << form->size;
1708
1709         Send(&pkt);
1710 }
1711
1712 void Server::SendHUDRemove(session_t peer_id, u32 id)
1713 {
1714         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1715         pkt << id;
1716         Send(&pkt);
1717 }
1718
1719 void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
1720 {
1721         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1722         pkt << id << (u8) stat;
1723
1724         switch (stat) {
1725                 case HUD_STAT_POS:
1726                 case HUD_STAT_SCALE:
1727                 case HUD_STAT_ALIGN:
1728                 case HUD_STAT_OFFSET:
1729                         pkt << *(v2f *) value;
1730                         break;
1731                 case HUD_STAT_NAME:
1732                 case HUD_STAT_TEXT:
1733                         pkt << *(std::string *) value;
1734                         break;
1735                 case HUD_STAT_WORLD_POS:
1736                         pkt << *(v3f *) value;
1737                         break;
1738                 case HUD_STAT_SIZE:
1739                         pkt << *(v2s32 *) value;
1740                         break;
1741                 case HUD_STAT_NUMBER:
1742                 case HUD_STAT_ITEM:
1743                 case HUD_STAT_DIR:
1744                 default:
1745                         pkt << *(u32 *) value;
1746                         break;
1747         }
1748
1749         Send(&pkt);
1750 }
1751
1752 void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
1753 {
1754         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1755
1756         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1757
1758         pkt << flags << mask;
1759
1760         Send(&pkt);
1761 }
1762
1763 void Server::SendHUDSetParam(session_t peer_id, u16 param, const std::string &value)
1764 {
1765         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1766         pkt << param << value;
1767         Send(&pkt);
1768 }
1769
1770 void Server::SendSetSky(session_t peer_id, const video::SColor &bgcolor,
1771                 const std::string &type, const std::vector<std::string> &params,
1772                 bool &clouds)
1773 {
1774         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1775         pkt << bgcolor << type << (u16) params.size();
1776
1777         for (const std::string &param : params)
1778                 pkt << param;
1779
1780         pkt << clouds;
1781
1782         Send(&pkt);
1783 }
1784
1785 void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
1786 {
1787         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1788         pkt << params.density << params.color_bright << params.color_ambient
1789                         << params.height << params.thickness << params.speed;
1790         Send(&pkt);
1791 }
1792
1793 void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
1794                 float ratio)
1795 {
1796         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1797                         1 + 2, peer_id);
1798
1799         pkt << do_override << (u16) (ratio * 65535);
1800
1801         Send(&pkt);
1802 }
1803
1804 void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
1805 {
1806         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1807         pkt << time << time_speed;
1808
1809         if (peer_id == PEER_ID_INEXISTENT) {
1810                 m_clients.sendToAll(&pkt);
1811         }
1812         else {
1813                 Send(&pkt);
1814         }
1815 }
1816
1817 void Server::SendPlayerHP(session_t peer_id)
1818 {
1819         PlayerSAO *playersao = getPlayerSAO(peer_id);
1820         // In some rare case if the player is disconnected
1821         // while Lua call l_punch, for example, this can be NULL
1822         if (!playersao)
1823                 return;
1824
1825         SendHP(peer_id, playersao->getHP());
1826         m_script->player_event(playersao,"health_changed");
1827
1828         // Send to other clients
1829         std::string str = gob_cmd_punched(playersao->getHP());
1830         ActiveObjectMessage aom(playersao->getId(), true, str);
1831         playersao->m_messages_out.push(aom);
1832 }
1833
1834 void Server::SendPlayerBreath(PlayerSAO *sao)
1835 {
1836         assert(sao);
1837
1838         m_script->player_event(sao, "breath_changed");
1839         SendBreath(sao->getPeerID(), sao->getBreath());
1840 }
1841
1842 void Server::SendMovePlayer(session_t peer_id)
1843 {
1844         RemotePlayer *player = m_env->getPlayer(peer_id);
1845         assert(player);
1846         PlayerSAO *sao = player->getPlayerSAO();
1847         assert(sao);
1848
1849         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1850         pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
1851
1852         {
1853                 v3f pos = sao->getBasePosition();
1854                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1855                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1856                                 << " pitch=" << sao->getLookPitch()
1857                                 << " yaw=" << sao->getRotation().Y
1858                                 << std::endl;
1859         }
1860
1861         Send(&pkt);
1862 }
1863
1864 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1865                 f32 animation_speed)
1866 {
1867         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1868                 peer_id);
1869
1870         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1871                         << animation_frames[3] << animation_speed;
1872
1873         Send(&pkt);
1874 }
1875
1876 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1877 {
1878         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1879         pkt << first << third;
1880         Send(&pkt);
1881 }
1882
1883 void Server::SendPlayerPrivileges(session_t peer_id)
1884 {
1885         RemotePlayer *player = m_env->getPlayer(peer_id);
1886         assert(player);
1887         if(player->getPeerId() == PEER_ID_INEXISTENT)
1888                 return;
1889
1890         std::set<std::string> privs;
1891         m_script->getAuth(player->getName(), NULL, &privs);
1892
1893         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1894         pkt << (u16) privs.size();
1895
1896         for (const std::string &priv : privs) {
1897                 pkt << priv;
1898         }
1899
1900         Send(&pkt);
1901 }
1902
1903 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1904 {
1905         RemotePlayer *player = m_env->getPlayer(peer_id);
1906         assert(player);
1907         if (player->getPeerId() == PEER_ID_INEXISTENT)
1908                 return;
1909
1910         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1911         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1912         Send(&pkt);
1913 }
1914
1915 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1916 {
1917         RemotePlayer *player = m_env->getPlayer(peer_id);
1918         assert(player);
1919         if (player->getPeerId() == PEER_ID_INEXISTENT)
1920                 return;
1921
1922         NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1923         pkt << FORMSPEC_VERSION_STRING + player->formspec_prepend;
1924         Send(&pkt);
1925 }
1926
1927 u32 Server::SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas)
1928 {
1929         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1930         pkt.putRawString(datas.c_str(), datas.size());
1931         Send(&pkt);
1932         return pkt.getSize();
1933 }
1934
1935 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
1936                 bool reliable)
1937 {
1938         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1939                         datas.size(), peer_id);
1940
1941         pkt.putRawString(datas.c_str(), datas.size());
1942
1943         m_clients.send(pkt.getPeerId(),
1944                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1945                         &pkt, reliable);
1946 }
1947
1948 void Server::SendCSMRestrictionFlags(session_t peer_id)
1949 {
1950         NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
1951                 sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
1952         pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
1953         Send(&pkt);
1954 }
1955
1956 void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
1957 {
1958         NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
1959         pkt << added_vel;
1960         Send(&pkt);
1961 }
1962
1963 s32 Server::playSound(const SimpleSoundSpec &spec,
1964                 const ServerSoundParams &params)
1965 {
1966         // Find out initial position of sound
1967         bool pos_exists = false;
1968         v3f pos = params.getPos(m_env, &pos_exists);
1969         // If position is not found while it should be, cancel sound
1970         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1971                 return -1;
1972
1973         // Filter destination clients
1974         std::vector<session_t> dst_clients;
1975         if(!params.to_player.empty()) {
1976                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
1977                 if(!player){
1978                         infostream<<"Server::playSound: Player \""<<params.to_player
1979                                         <<"\" not found"<<std::endl;
1980                         return -1;
1981                 }
1982                 if (player->getPeerId() == PEER_ID_INEXISTENT) {
1983                         infostream<<"Server::playSound: Player \""<<params.to_player
1984                                         <<"\" not connected"<<std::endl;
1985                         return -1;
1986                 }
1987                 dst_clients.push_back(player->getPeerId());
1988         } else {
1989                 std::vector<session_t> clients = m_clients.getClientIDs();
1990
1991                 for (const session_t client_id : clients) {
1992                         RemotePlayer *player = m_env->getPlayer(client_id);
1993                         if (!player)
1994                                 continue;
1995
1996                         PlayerSAO *sao = player->getPlayerSAO();
1997                         if (!sao)
1998                                 continue;
1999
2000                         if (pos_exists) {
2001                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2002                                                 params.max_hear_distance)
2003                                         continue;
2004                         }
2005                         dst_clients.push_back(client_id);
2006                 }
2007         }
2008
2009         if(dst_clients.empty())
2010                 return -1;
2011
2012         // Create the sound
2013         s32 id = m_next_sound_id++;
2014         // The sound will exist as a reference in m_playing_sounds
2015         m_playing_sounds[id] = ServerPlayingSound();
2016         ServerPlayingSound &psound = m_playing_sounds[id];
2017         psound.params = params;
2018         psound.spec = spec;
2019
2020         float gain = params.gain * spec.gain;
2021         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2022         pkt << id << spec.name << gain
2023                         << (u8) params.type << pos << params.object
2024                         << params.loop << params.fade << params.pitch;
2025
2026         // Backwards compability
2027         bool play_sound = gain > 0;
2028
2029         for (const u16 dst_client : dst_clients) {
2030                 if (play_sound || m_clients.getProtocolVersion(dst_client) >= 32) {
2031                         psound.clients.insert(dst_client);
2032                         m_clients.send(dst_client, 0, &pkt, true);
2033                 }
2034         }
2035         return id;
2036 }
2037 void Server::stopSound(s32 handle)
2038 {
2039         // Get sound reference
2040         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2041                 m_playing_sounds.find(handle);
2042         if (i == m_playing_sounds.end())
2043                 return;
2044         ServerPlayingSound &psound = i->second;
2045
2046         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2047         pkt << handle;
2048
2049         for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2050                         si != psound.clients.end(); ++si) {
2051                 // Send as reliable
2052                 m_clients.send(*si, 0, &pkt, true);
2053         }
2054         // Remove sound reference
2055         m_playing_sounds.erase(i);
2056 }
2057
2058 void Server::fadeSound(s32 handle, float step, float gain)
2059 {
2060         // Get sound reference
2061         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2062                 m_playing_sounds.find(handle);
2063         if (i == m_playing_sounds.end())
2064                 return;
2065
2066         ServerPlayingSound &psound = i->second;
2067         psound.params.gain = gain;
2068
2069         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2070         pkt << handle << step << gain;
2071
2072         // Backwards compability
2073         bool play_sound = gain > 0;
2074         ServerPlayingSound compat_psound = psound;
2075         compat_psound.clients.clear();
2076
2077         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2078         compat_pkt << handle;
2079
2080         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2081                         it != psound.clients.end();) {
2082                 if (m_clients.getProtocolVersion(*it) >= 32) {
2083                         // Send as reliable
2084                         m_clients.send(*it, 0, &pkt, true);
2085                         ++it;
2086                 } else {
2087                         compat_psound.clients.insert(*it);
2088                         // Stop old sound
2089                         m_clients.send(*it, 0, &compat_pkt, true);
2090                         psound.clients.erase(it++);
2091                 }
2092         }
2093
2094         // Remove sound reference
2095         if (!play_sound || psound.clients.empty())
2096                 m_playing_sounds.erase(i);
2097
2098         if (play_sound && !compat_psound.clients.empty()) {
2099                 // Play new sound volume on older clients
2100                 playSound(compat_psound.spec, compat_psound.params);
2101         }
2102 }
2103
2104 void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
2105                 float far_d_nodes)
2106 {
2107         float maxd = far_d_nodes * BS;
2108         v3f p_f = intToFloat(p, BS);
2109         v3s16 block_pos = getNodeBlockPos(p);
2110
2111         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2112         pkt << p;
2113
2114         std::vector<session_t> clients = m_clients.getClientIDs();
2115         m_clients.lock();
2116
2117         for (session_t client_id : clients) {
2118                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2119                 if (!client)
2120                         continue;
2121
2122                 RemotePlayer *player = m_env->getPlayer(client_id);
2123                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2124
2125                 // If player is far away, only set modified blocks not sent
2126                 if (!client->isBlockSent(block_pos) || (sao &&
2127                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2128                         if (far_players)
2129                                 far_players->emplace(client_id);
2130                         else
2131                                 client->SetBlockNotSent(block_pos);
2132                         continue;
2133                 }
2134
2135                 // Send as reliable
2136                 m_clients.send(client_id, 0, &pkt, true);
2137         }
2138
2139         m_clients.unlock();
2140 }
2141
2142 void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
2143                 float far_d_nodes, bool remove_metadata)
2144 {
2145         float maxd = far_d_nodes * BS;
2146         v3f p_f = intToFloat(p, BS);
2147         v3s16 block_pos = getNodeBlockPos(p);
2148
2149         NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2150         pkt << p << n.param0 << n.param1 << n.param2
2151                         << (u8) (remove_metadata ? 0 : 1);
2152
2153         std::vector<session_t> clients = m_clients.getClientIDs();
2154         m_clients.lock();
2155
2156         for (session_t client_id : clients) {
2157                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2158                 if (!client)
2159                         continue;
2160
2161                 RemotePlayer *player = m_env->getPlayer(client_id);
2162                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2163
2164                 // If player is far away, only set modified blocks not sent
2165                 if (!client->isBlockSent(block_pos) || (sao &&
2166                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2167                         if (far_players)
2168                                 far_players->emplace(client_id);
2169                         else
2170                                 client->SetBlockNotSent(block_pos);
2171                         continue;
2172                 }
2173
2174                 // Send as reliable
2175                 m_clients.send(client_id, 0, &pkt, true);
2176         }
2177
2178         m_clients.unlock();
2179 }
2180
2181 void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes)
2182 {
2183         float maxd = far_d_nodes * BS;
2184         NodeMetadataList meta_updates_list(false);
2185         std::vector<session_t> clients = m_clients.getClientIDs();
2186
2187         m_clients.lock();
2188
2189         for (session_t i : clients) {
2190                 RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2191                 if (!client)
2192                         continue;
2193
2194                 ServerActiveObject *player = m_env->getActiveObject(i);
2195                 v3f player_pos = player ? player->getBasePosition() : v3f();
2196
2197                 for (const v3s16 &pos : meta_updates) {
2198                         NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
2199
2200                         if (!meta)
2201                                 continue;
2202
2203                         v3s16 block_pos = getNodeBlockPos(pos);
2204                         if (!client->isBlockSent(block_pos) || (player &&
2205                                         player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) {
2206                                 client->SetBlockNotSent(block_pos);
2207                                 continue;
2208                         }
2209
2210                         // Add the change to send list
2211                         meta_updates_list.set(pos, meta);
2212                 }
2213                 if (meta_updates_list.size() == 0)
2214                         continue;
2215
2216                 // Send the meta changes
2217                 std::ostringstream os(std::ios::binary);
2218                 meta_updates_list.serialize(os, client->net_proto_version, false, true);
2219                 std::ostringstream oss(std::ios::binary);
2220                 compressZlib(os.str(), oss);
2221
2222                 NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0);
2223                 pkt.putLongString(oss.str());
2224                 m_clients.send(i, 0, &pkt, true);
2225
2226                 meta_updates_list.clear();
2227         }
2228
2229         m_clients.unlock();
2230 }
2231
2232 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2233                 u16 net_proto_version)
2234 {
2235         /*
2236                 Create a packet with the block in the right format
2237         */
2238
2239         std::ostringstream os(std::ios_base::binary);
2240         block->serialize(os, ver, false);
2241         block->serializeNetworkSpecific(os);
2242         std::string s = os.str();
2243
2244         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2245
2246         pkt << block->getPos();
2247         pkt.putRawString(s.c_str(), s.size());
2248         Send(&pkt);
2249 }
2250
2251 void Server::SendBlocks(float dtime)
2252 {
2253         MutexAutoLock envlock(m_env_mutex);
2254         //TODO check if one big lock could be faster then multiple small ones
2255
2256         std::vector<PrioritySortedBlockTransfer> queue;
2257
2258         u32 total_sending = 0;
2259
2260         {
2261                 ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
2262
2263                 std::vector<session_t> clients = m_clients.getClientIDs();
2264
2265                 m_clients.lock();
2266                 for (const session_t client_id : clients) {
2267                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2268
2269                         if (!client)
2270                                 continue;
2271
2272                         total_sending += client->getSendingCount();
2273                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2274                 }
2275                 m_clients.unlock();
2276         }
2277
2278         // Sort.
2279         // Lowest priority number comes first.
2280         // Lowest is most important.
2281         std::sort(queue.begin(), queue.end());
2282
2283         m_clients.lock();
2284
2285         // Maximal total count calculation
2286         // The per-client block sends is halved with the maximal online users
2287         u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2288                 g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2289
2290         ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
2291         Map &map = m_env->getMap();
2292
2293         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2294                 if (total_sending >= max_blocks_to_send)
2295                         break;
2296
2297                 MapBlock *block = map.getBlockNoCreateNoEx(block_to_send.pos);
2298                 if (!block)
2299                         continue;
2300
2301                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2302                                 CS_Active);
2303                 if (!client)
2304                         continue;
2305
2306                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2307                                 client->net_proto_version);
2308
2309                 client->SentBlock(block_to_send.pos);
2310                 total_sending++;
2311         }
2312         m_clients.unlock();
2313 }
2314
2315 bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos)
2316 {
2317         MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2318         if (!block)
2319                 return false;
2320
2321         m_clients.lock();
2322         RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active);
2323         if (!client || client->isBlockSent(blockpos)) {
2324                 m_clients.unlock();
2325                 return false;
2326         }
2327         SendBlockNoLock(peer_id, block, client->serialization_version,
2328                         client->net_proto_version);
2329         m_clients.unlock();
2330
2331         return true;
2332 }
2333
2334 void Server::fillMediaCache()
2335 {
2336         infostream<<"Server: Calculating media file checksums"<<std::endl;
2337
2338         // Collect all media file paths
2339         std::vector<std::string> paths;
2340         m_modmgr->getModsMediaPaths(paths);
2341         fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2342         fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2343
2344         // Collect media file information from paths into cache
2345         for (const std::string &mediapath : paths) {
2346                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2347                 for (const fs::DirListNode &dln : dirlist) {
2348                         if (dln.dir) // Ignode dirs
2349                                 continue;
2350                         std::string filename = dln.name;
2351                         // If name contains illegal characters, ignore the file
2352                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2353                                 infostream<<"Server: ignoring illegal file name: \""
2354                                                 << filename << "\"" << std::endl;
2355                                 continue;
2356                         }
2357                         // If name is not in a supported format, ignore it
2358                         const char *supported_ext[] = {
2359                                 ".png", ".jpg", ".bmp", ".tga",
2360                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2361                                 ".ogg",
2362                                 ".x", ".b3d", ".md2", ".obj",
2363                                 // Custom translation file format
2364                                 ".tr",
2365                                 NULL
2366                         };
2367                         if (removeStringEnd(filename, supported_ext).empty()){
2368                                 infostream << "Server: ignoring unsupported file extension: \""
2369                                                 << filename << "\"" << std::endl;
2370                                 continue;
2371                         }
2372                         // Ok, attempt to load the file and add to cache
2373                         std::string filepath;
2374                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2375
2376                         // Read data
2377                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2378                         if (!fis.good()) {
2379                                 errorstream << "Server::fillMediaCache(): Could not open \""
2380                                                 << filename << "\" for reading" << std::endl;
2381                                 continue;
2382                         }
2383                         std::ostringstream tmp_os(std::ios_base::binary);
2384                         bool bad = false;
2385                         for(;;) {
2386                                 char buf[1024];
2387                                 fis.read(buf, 1024);
2388                                 std::streamsize len = fis.gcount();
2389                                 tmp_os.write(buf, len);
2390                                 if (fis.eof())
2391                                         break;
2392                                 if (!fis.good()) {
2393                                         bad = true;
2394                                         break;
2395                                 }
2396                         }
2397                         if(bad) {
2398                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2399                                                 << filename << "\"" << std::endl;
2400                                 continue;
2401                         }
2402                         if(tmp_os.str().length() == 0) {
2403                                 errorstream << "Server::fillMediaCache(): Empty file \""
2404                                                 << filepath << "\"" << std::endl;
2405                                 continue;
2406                         }
2407
2408                         SHA1 sha1;
2409                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2410
2411                         unsigned char *digest = sha1.getDigest();
2412                         std::string sha1_base64 = base64_encode(digest, 20);
2413                         std::string sha1_hex = hex_encode((char*)digest, 20);
2414                         free(digest);
2415
2416                         // Put in list
2417                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2418                         verbosestream << "Server: " << sha1_hex << " is " << filename
2419                                         << std::endl;
2420                 }
2421         }
2422 }
2423
2424 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2425 {
2426         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2427                 << std::endl;
2428
2429         // Make packet
2430         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2431
2432         u16 media_sent = 0;
2433         std::string lang_suffix;
2434         lang_suffix.append(".").append(lang_code).append(".tr");
2435         for (const auto &i : m_media) {
2436                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2437                         continue;
2438                 media_sent++;
2439         }
2440
2441         pkt << media_sent;
2442
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                 pkt << i.first << i.second.sha1_digest;
2447         }
2448
2449         pkt << g_settings->get("remote_media");
2450         Send(&pkt);
2451 }
2452
2453 struct SendableMedia
2454 {
2455         std::string name;
2456         std::string path;
2457         std::string data;
2458
2459         SendableMedia(const std::string &name_="", const std::string &path_="",
2460                       const std::string &data_=""):
2461                 name(name_),
2462                 path(path_),
2463                 data(data_)
2464         {}
2465 };
2466
2467 void Server::sendRequestedMedia(session_t peer_id,
2468                 const std::vector<std::string> &tosend)
2469 {
2470         verbosestream<<"Server::sendRequestedMedia(): "
2471                         <<"Sending files to client"<<std::endl;
2472
2473         /* Read files */
2474
2475         // Put 5kB in one bunch (this is not accurate)
2476         u32 bytes_per_bunch = 5000;
2477
2478         std::vector< std::vector<SendableMedia> > file_bunches;
2479         file_bunches.emplace_back();
2480
2481         u32 file_size_bunch_total = 0;
2482
2483         for (const std::string &name : tosend) {
2484                 if (m_media.find(name) == m_media.end()) {
2485                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2486                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2487                         continue;
2488                 }
2489
2490                 //TODO get path + name
2491                 std::string tpath = m_media[name].path;
2492
2493                 // Read data
2494                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2495                 if(!fis.good()){
2496                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2497                                         <<tpath<<"\" for reading"<<std::endl;
2498                         continue;
2499                 }
2500                 std::ostringstream tmp_os(std::ios_base::binary);
2501                 bool bad = false;
2502                 for(;;) {
2503                         char buf[1024];
2504                         fis.read(buf, 1024);
2505                         std::streamsize len = fis.gcount();
2506                         tmp_os.write(buf, len);
2507                         file_size_bunch_total += len;
2508                         if(fis.eof())
2509                                 break;
2510                         if(!fis.good()) {
2511                                 bad = true;
2512                                 break;
2513                         }
2514                 }
2515                 if (bad) {
2516                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2517                                         <<name<<"\""<<std::endl;
2518                         continue;
2519                 }
2520                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2521                                 <<tname<<"\""<<std::endl;*/
2522                 // Put in list
2523                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2524
2525                 // Start next bunch if got enough data
2526                 if(file_size_bunch_total >= bytes_per_bunch) {
2527                         file_bunches.emplace_back();
2528                         file_size_bunch_total = 0;
2529                 }
2530
2531         }
2532
2533         /* Create and send packets */
2534
2535         u16 num_bunches = file_bunches.size();
2536         for (u16 i = 0; i < num_bunches; i++) {
2537                 /*
2538                         u16 command
2539                         u16 total number of texture bunches
2540                         u16 index of this bunch
2541                         u32 number of files in this bunch
2542                         for each file {
2543                                 u16 length of name
2544                                 string name
2545                                 u32 length of data
2546                                 data
2547                         }
2548                 */
2549
2550                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2551                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2552
2553                 for (const SendableMedia &j : file_bunches[i]) {
2554                         pkt << j.name;
2555                         pkt.putLongString(j.data);
2556                 }
2557
2558                 verbosestream << "Server::sendRequestedMedia(): bunch "
2559                                 << i << "/" << num_bunches
2560                                 << " files=" << file_bunches[i].size()
2561                                 << " size="  << pkt.getSize() << std::endl;
2562                 Send(&pkt);
2563         }
2564 }
2565
2566 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
2567 {
2568         const auto &inv_it = m_detached_inventories.find(name);
2569         const auto &player_it = m_detached_inventories_player.find(name);
2570
2571         if (player_it == m_detached_inventories_player.end() ||
2572                         player_it->second.empty()) {
2573                 // OK. Send to everyone
2574         } else {
2575                 if (!m_env)
2576                         return; // Mods are not done loading
2577
2578                 RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
2579                 if (!p)
2580                         return; // Player is offline
2581
2582                 if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
2583                         return; // Caller requested send to a different player, so don't send.
2584
2585                 peer_id = p->getPeerId();
2586         }
2587
2588         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2589         pkt << name;
2590
2591         if (inv_it == m_detached_inventories.end()) {
2592                 pkt << false; // Remove inventory
2593         } else {
2594                 pkt << true; // Update inventory
2595
2596                 // Serialization & NetworkPacket isn't a love story
2597                 std::ostringstream os(std::ios_base::binary);
2598                 inv_it->second->serialize(os);
2599                 inv_it->second->setModified(false);
2600
2601                 const std::string &os_str = os.str();
2602                 pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
2603                 pkt.putRawString(os_str);
2604         }
2605
2606         if (peer_id == PEER_ID_INEXISTENT)
2607                 m_clients.sendToAll(&pkt);
2608         else
2609                 Send(&pkt);
2610 }
2611
2612 void Server::sendDetachedInventories(session_t peer_id, bool incremental)
2613 {
2614         for (const auto &detached_inventory : m_detached_inventories) {
2615                 const std::string &name = detached_inventory.first;
2616                 if (incremental) {
2617                         Inventory *inv = detached_inventory.second;
2618                         if (!inv || !inv->checkModified())
2619                                 continue;
2620                 }
2621
2622                 sendDetachedInventory(name, peer_id);
2623         }
2624 }
2625
2626 /*
2627         Something random
2628 */
2629
2630 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2631 {
2632         PlayerSAO *playersao = getPlayerSAO(peer_id);
2633         // In some rare cases this can be NULL -- if the player is disconnected
2634         // when a Lua function modifies l_punch, for example
2635         if (!playersao)
2636                 return;
2637
2638         infostream << "Server::DiePlayer(): Player "
2639                         << playersao->getPlayer()->getName()
2640                         << " dies" << std::endl;
2641
2642         playersao->setHP(0, reason);
2643         playersao->clearParentAttachment();
2644
2645         // Trigger scripted stuff
2646         m_script->on_dieplayer(playersao, reason);
2647
2648         SendPlayerHP(peer_id);
2649         SendDeathscreen(peer_id, false, v3f(0,0,0));
2650 }
2651
2652 void Server::RespawnPlayer(session_t peer_id)
2653 {
2654         PlayerSAO *playersao = getPlayerSAO(peer_id);
2655         assert(playersao);
2656
2657         infostream << "Server::RespawnPlayer(): Player "
2658                         << playersao->getPlayer()->getName()
2659                         << " respawns" << std::endl;
2660
2661         playersao->setHP(playersao->accessObjectProperties()->hp_max,
2662                         PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2663         playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2664
2665         bool repositioned = m_script->on_respawnplayer(playersao);
2666         if (!repositioned) {
2667                 // setPos will send the new position to client
2668                 playersao->setPos(findSpawnPos());
2669         }
2670
2671         SendPlayerHP(peer_id);
2672 }
2673
2674
2675 void Server::DenySudoAccess(session_t peer_id)
2676 {
2677         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2678         Send(&pkt);
2679 }
2680
2681
2682 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2683                 const std::string &str_reason, bool reconnect)
2684 {
2685         SendAccessDenied(peer_id, reason, str_reason, reconnect);
2686
2687         m_clients.event(peer_id, CSE_SetDenied);
2688         DisconnectPeer(peer_id);
2689 }
2690
2691
2692 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2693                 const std::string &custom_reason)
2694 {
2695         SendAccessDenied(peer_id, reason, custom_reason);
2696         m_clients.event(peer_id, CSE_SetDenied);
2697         DisconnectPeer(peer_id);
2698 }
2699
2700 // 13/03/15: remove this function when protocol version 25 will become
2701 // the minimum version for MT users, maybe in 1 year
2702 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2703 {
2704         SendAccessDenied_Legacy(peer_id, reason);
2705         m_clients.event(peer_id, CSE_SetDenied);
2706         DisconnectPeer(peer_id);
2707 }
2708
2709 void Server::DisconnectPeer(session_t peer_id)
2710 {
2711         m_modchannel_mgr->leaveAllChannels(peer_id);
2712         m_con->DisconnectPeer(peer_id);
2713 }
2714
2715 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2716 {
2717         if (!forSudoMode) {
2718                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2719
2720                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2721
2722                 // Right now, the auth mechs don't change between login and sudo mode.
2723                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2724                 client->allowed_sudo_mechs = sudo_auth_mechs;
2725
2726                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2727                                 << g_settings->getFloat("dedicated_server_step")
2728                                 << sudo_auth_mechs;
2729
2730                 Send(&resp_pkt);
2731                 m_clients.event(peer_id, CSE_AuthAccept);
2732         } else {
2733                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2734
2735                 // We only support SRP right now
2736                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2737
2738                 resp_pkt << sudo_auth_mechs;
2739                 Send(&resp_pkt);
2740                 m_clients.event(peer_id, CSE_SudoSuccess);
2741         }
2742 }
2743
2744 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2745 {
2746         std::wstring message;
2747         {
2748                 /*
2749                         Clear references to playing sounds
2750                 */
2751                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2752                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2753                         ServerPlayingSound &psound = i->second;
2754                         psound.clients.erase(peer_id);
2755                         if (psound.clients.empty())
2756                                 m_playing_sounds.erase(i++);
2757                         else
2758                                 ++i;
2759                 }
2760
2761                 // clear formspec info so the next client can't abuse the current state
2762                 m_formspec_state_data.erase(peer_id);
2763
2764                 RemotePlayer *player = m_env->getPlayer(peer_id);
2765
2766                 /* Run scripts and remove from environment */
2767                 if (player) {
2768                         PlayerSAO *playersao = player->getPlayerSAO();
2769                         assert(playersao);
2770
2771                         playersao->clearChildAttachments();
2772                         playersao->clearParentAttachment();
2773
2774                         // inform connected clients
2775                         const std::string &player_name = player->getName();
2776                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2777                         // (u16) 1 + std::string represents a vector serialization representation
2778                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
2779                         m_clients.sendToAll(&notice);
2780                         // run scripts
2781                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2782
2783                         playersao->disconnected();
2784                 }
2785
2786                 /*
2787                         Print out action
2788                 */
2789                 {
2790                         if (player && reason != CDR_DENY) {
2791                                 std::ostringstream os(std::ios_base::binary);
2792                                 std::vector<session_t> clients = m_clients.getClientIDs();
2793
2794                                 for (const session_t client_id : clients) {
2795                                         // Get player
2796                                         RemotePlayer *player = m_env->getPlayer(client_id);
2797                                         if (!player)
2798                                                 continue;
2799
2800                                         // Get name of player
2801                                         os << player->getName() << " ";
2802                                 }
2803
2804                                 std::string name = player->getName();
2805                                 actionstream << name << " "
2806                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2807                                                 << " List of players: " << os.str() << std::endl;
2808                                 if (m_admin_chat)
2809                                         m_admin_chat->outgoing_queue.push_back(
2810                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2811                         }
2812                 }
2813                 {
2814                         MutexAutoLock env_lock(m_env_mutex);
2815                         m_clients.DeleteClient(peer_id);
2816                 }
2817         }
2818
2819         // Send leave chat message to all remaining clients
2820         if (!message.empty()) {
2821                 SendChatMessage(PEER_ID_INEXISTENT,
2822                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2823         }
2824 }
2825
2826 void Server::UpdateCrafting(RemotePlayer *player)
2827 {
2828         InventoryList *clist = player->inventory.getList("craft");
2829         if (!clist || clist->getSize() == 0)
2830                 return;
2831
2832         if (!clist->checkModified()) {
2833                 verbosestream << "Skip Server::UpdateCrafting(): list unmodified" << std::endl;
2834                 return;
2835         }
2836
2837         // Get a preview for crafting
2838         ItemStack preview;
2839         InventoryLocation loc;
2840         loc.setPlayer(player->getName());
2841         std::vector<ItemStack> output_replacements;
2842         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2843         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2844                         clist, loc);
2845
2846         InventoryList *plist = player->inventory.getList("craftpreview");
2847         if (plist && plist->getSize() >= 1) {
2848                 // Put the new preview in
2849                 plist->changeItem(0, preview);
2850         }
2851 }
2852
2853 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2854 {
2855         if (evt->type == CET_NICK_ADD) {
2856                 // The terminal informed us of its nick choice
2857                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2858                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2859                         errorstream << "You haven't set up an account." << std::endl
2860                                 << "Please log in using the client as '"
2861                                 << m_admin_nick << "' with a secure password." << std::endl
2862                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2863                                 << "and everybody can claim the user account instead of you," << std::endl
2864                                 << "giving them full control over this server." << std::endl;
2865                 }
2866         } else {
2867                 assert(evt->type == CET_CHAT);
2868                 handleAdminChat((ChatEventChat *)evt);
2869         }
2870 }
2871
2872 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2873         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2874 {
2875         // If something goes wrong, this player is to blame
2876         RollbackScopeActor rollback_scope(m_rollback,
2877                         std::string("player:") + name);
2878
2879         if (g_settings->getBool("strip_color_codes"))
2880                 wmessage = unescape_enriched(wmessage);
2881
2882         if (player) {
2883                 switch (player->canSendChatMessage()) {
2884                 case RPLAYER_CHATRESULT_FLOODING: {
2885                         std::wstringstream ws;
2886                         ws << L"You cannot send more messages. You are limited to "
2887                                         << g_settings->getFloat("chat_message_limit_per_10sec")
2888                                         << L" messages per 10 seconds.";
2889                         return ws.str();
2890                 }
2891                 case RPLAYER_CHATRESULT_KICK:
2892                         DenyAccess_Legacy(player->getPeerId(),
2893                                         L"You have been kicked due to message flooding.");
2894                         return L"";
2895                 case RPLAYER_CHATRESULT_OK:
2896                         break;
2897                 default:
2898                         FATAL_ERROR("Unhandled chat filtering result found.");
2899                 }
2900         }
2901
2902         if (m_max_chatmessage_length > 0
2903                         && wmessage.length() > m_max_chatmessage_length) {
2904                 return L"Your message exceed the maximum chat message limit set on the server. "
2905                                 L"It was refused. Send a shorter message";
2906         }
2907
2908         auto message = trim(wide_to_utf8(wmessage));
2909         if (message.find_first_of("\n\r") != std::wstring::npos) {
2910                 return L"New lines are not permitted in chat messages";
2911         }
2912
2913         // Run script hook, exit if script ate the chat message
2914         if (m_script->on_chat_message(name, message))
2915                 return L"";
2916
2917         // Line to send
2918         std::wstring line;
2919         // Whether to send line to the player that sent the message, or to all players
2920         bool broadcast_line = true;
2921
2922         if (check_shout_priv && !checkPriv(name, "shout")) {
2923                 line += L"-!- You don't have permission to shout.";
2924                 broadcast_line = false;
2925         } else {
2926                 line += narrow_to_wide(m_script->formatChatMessage(name,
2927                                 wide_to_narrow(wmessage)));
2928         }
2929
2930         /*
2931                 Tell calling method to send the message to sender
2932         */
2933         if (!broadcast_line)
2934                 return line;
2935
2936         /*
2937                 Send the message to others
2938         */
2939         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2940
2941         std::vector<session_t> clients = m_clients.getClientIDs();
2942
2943         /*
2944                 Send the message back to the inital sender
2945                 if they are using protocol version >= 29
2946         */
2947
2948         session_t peer_id_to_avoid_sending =
2949                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
2950
2951         if (player && player->protocol_version >= 29)
2952                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2953
2954         for (u16 cid : clients) {
2955                 if (cid != peer_id_to_avoid_sending)
2956                         SendChatMessage(cid, ChatMessage(line));
2957         }
2958         return L"";
2959 }
2960
2961 void Server::handleAdminChat(const ChatEventChat *evt)
2962 {
2963         std::string name = evt->nick;
2964         std::wstring wname = utf8_to_wide(name);
2965         std::wstring wmessage = evt->evt_msg;
2966
2967         std::wstring answer = handleChat(name, wname, wmessage);
2968
2969         // If asked to send answer to sender
2970         if (!answer.empty()) {
2971                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2972         }
2973 }
2974
2975 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
2976 {
2977         RemoteClient *client = getClientNoEx(peer_id,state_min);
2978         if(!client)
2979                 throw ClientNotFoundException("Client not found");
2980
2981         return client;
2982 }
2983 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
2984 {
2985         return m_clients.getClientNoEx(peer_id, state_min);
2986 }
2987
2988 std::string Server::getPlayerName(session_t peer_id)
2989 {
2990         RemotePlayer *player = m_env->getPlayer(peer_id);
2991         if (!player)
2992                 return "[id="+itos(peer_id)+"]";
2993         return player->getName();
2994 }
2995
2996 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
2997 {
2998         RemotePlayer *player = m_env->getPlayer(peer_id);
2999         if (!player)
3000                 return NULL;
3001         return player->getPlayerSAO();
3002 }
3003
3004 std::wstring Server::getStatusString()
3005 {
3006         std::wostringstream os(std::ios_base::binary);
3007         os << L"# Server: ";
3008         // Version
3009         os << L"version=" << narrow_to_wide(g_version_string);
3010         // Uptime
3011         os << L", uptime=" << m_uptime.get();
3012         // Max lag estimate
3013         os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
3014
3015         // Information about clients
3016         bool first = true;
3017         os << L", clients={";
3018         if (m_env) {
3019                 std::vector<session_t> clients = m_clients.getClientIDs();
3020                 for (session_t client_id : clients) {
3021                         RemotePlayer *player = m_env->getPlayer(client_id);
3022
3023                         // Get name of player
3024                         std::wstring name = L"unknown";
3025                         if (player)
3026                                 name = narrow_to_wide(player->getName());
3027
3028                         // Add name to information string
3029                         if (!first)
3030                                 os << L", ";
3031                         else
3032                                 first = false;
3033
3034                         os << name;
3035                 }
3036         }
3037         os << L"}";
3038
3039         if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3040                 os << std::endl << L"# Server: " << " WARNING: Map saving is disabled.";
3041
3042         if (!g_settings->get("motd").empty())
3043                 os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd"));
3044
3045         return os.str();
3046 }
3047
3048 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3049 {
3050         std::set<std::string> privs;
3051         m_script->getAuth(name, NULL, &privs);
3052         return privs;
3053 }
3054
3055 bool Server::checkPriv(const std::string &name, const std::string &priv)
3056 {
3057         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3058         return (privs.count(priv) != 0);
3059 }
3060
3061 void Server::reportPrivsModified(const std::string &name)
3062 {
3063         if (name.empty()) {
3064                 std::vector<session_t> clients = m_clients.getClientIDs();
3065                 for (const session_t client_id : clients) {
3066                         RemotePlayer *player = m_env->getPlayer(client_id);
3067                         reportPrivsModified(player->getName());
3068                 }
3069         } else {
3070                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3071                 if (!player)
3072                         return;
3073                 SendPlayerPrivileges(player->getPeerId());
3074                 PlayerSAO *sao = player->getPlayerSAO();
3075                 if(!sao)
3076                         return;
3077                 sao->updatePrivileges(
3078                                 getPlayerEffectivePrivs(name),
3079                                 isSingleplayer());
3080         }
3081 }
3082
3083 void Server::reportInventoryFormspecModified(const std::string &name)
3084 {
3085         RemotePlayer *player = m_env->getPlayer(name.c_str());
3086         if (!player)
3087                 return;
3088         SendPlayerInventoryFormspec(player->getPeerId());
3089 }
3090
3091 void Server::reportFormspecPrependModified(const std::string &name)
3092 {
3093         RemotePlayer *player = m_env->getPlayer(name.c_str());
3094         if (!player)
3095                 return;
3096         SendPlayerFormspecPrepend(player->getPeerId());
3097 }
3098
3099 void Server::setIpBanned(const std::string &ip, const std::string &name)
3100 {
3101         m_banmanager->add(ip, name);
3102 }
3103
3104 void Server::unsetIpBanned(const std::string &ip_or_name)
3105 {
3106         m_banmanager->remove(ip_or_name);
3107 }
3108
3109 std::string Server::getBanDescription(const std::string &ip_or_name)
3110 {
3111         return m_banmanager->getBanDescription(ip_or_name);
3112 }
3113
3114 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3115 {
3116         // m_env will be NULL if the server is initializing
3117         if (!m_env)
3118                 return;
3119
3120         if (m_admin_nick == name && !m_admin_nick.empty()) {
3121                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3122         }
3123
3124         RemotePlayer *player = m_env->getPlayer(name);
3125         if (!player) {
3126                 return;
3127         }
3128
3129         if (player->getPeerId() == PEER_ID_INEXISTENT)
3130                 return;
3131
3132         SendChatMessage(player->getPeerId(), ChatMessage(msg));
3133 }
3134
3135 bool Server::showFormspec(const char *playername, const std::string &formspec,
3136         const std::string &formname)
3137 {
3138         // m_env will be NULL if the server is initializing
3139         if (!m_env)
3140                 return false;
3141
3142         RemotePlayer *player = m_env->getPlayer(playername);
3143         if (!player)
3144                 return false;
3145
3146         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3147         return true;
3148 }
3149
3150 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3151 {
3152         if (!player)
3153                 return -1;
3154
3155         u32 id = player->addHud(form);
3156
3157         SendHUDAdd(player->getPeerId(), id, form);
3158
3159         return id;
3160 }
3161
3162 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3163         if (!player)
3164                 return false;
3165
3166         HudElement* todel = player->removeHud(id);
3167
3168         if (!todel)
3169                 return false;
3170
3171         delete todel;
3172
3173         SendHUDRemove(player->getPeerId(), id);
3174         return true;
3175 }
3176
3177 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3178 {
3179         if (!player)
3180                 return false;
3181
3182         SendHUDChange(player->getPeerId(), id, stat, data);
3183         return true;
3184 }
3185
3186 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3187 {
3188         if (!player)
3189                 return false;
3190
3191         SendHUDSetFlags(player->getPeerId(), flags, mask);
3192         player->hud_flags &= ~mask;
3193         player->hud_flags |= flags;
3194
3195         PlayerSAO* playersao = player->getPlayerSAO();
3196
3197         if (!playersao)
3198                 return false;
3199
3200         m_script->player_event(playersao, "hud_changed");
3201         return true;
3202 }
3203
3204 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3205 {
3206         if (!player)
3207                 return false;
3208
3209         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3210                 return false;
3211
3212         player->setHotbarItemcount(hotbar_itemcount);
3213         std::ostringstream os(std::ios::binary);
3214         writeS32(os, hotbar_itemcount);
3215         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3216         return true;
3217 }
3218
3219 void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
3220 {
3221         if (!player)
3222                 return;
3223
3224         player->setHotbarImage(name);
3225         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3226 }
3227
3228 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
3229 {
3230         if (!player)
3231                 return;
3232
3233         player->setHotbarSelectedImage(name);
3234         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3235 }
3236
3237 Address Server::getPeerAddress(session_t peer_id)
3238 {
3239         return m_con->GetPeerAddress(peer_id);
3240 }
3241
3242 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3243                 v2s32 animation_frames[4], f32 frame_speed)
3244 {
3245         sanity_check(player);
3246         player->setLocalAnimations(animation_frames, frame_speed);
3247         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3248 }
3249
3250 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3251 {
3252         sanity_check(player);
3253         player->eye_offset_first = first;
3254         player->eye_offset_third = third;
3255         SendEyeOffset(player->getPeerId(), first, third);
3256 }
3257
3258 void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3259         const std::string &type, const std::vector<std::string> &params,
3260         bool &clouds)
3261 {
3262         sanity_check(player);
3263         player->setSky(bgcolor, type, params, clouds);
3264         SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
3265 }
3266
3267 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3268 {
3269         sanity_check(player);
3270         player->setCloudParams(params);
3271         SendCloudParams(player->getPeerId(), params);
3272 }
3273
3274 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3275         float ratio)
3276 {
3277         if (!player)
3278                 return false;
3279
3280         player->overrideDayNightRatio(do_override, ratio);
3281         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3282         return true;
3283 }
3284
3285 void Server::notifyPlayers(const std::wstring &msg)
3286 {
3287         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3288 }
3289
3290 void Server::spawnParticle(const std::string &playername, v3f pos,
3291         v3f velocity, v3f acceleration,
3292         float expirationtime, float size, bool
3293         collisiondetection, bool collision_removal, bool object_collision,
3294         bool vertical, const std::string &texture,
3295         const struct TileAnimationParams &animation, u8 glow)
3296 {
3297         // m_env will be NULL if the server is initializing
3298         if (!m_env)
3299                 return;
3300
3301         session_t peer_id = PEER_ID_INEXISTENT;
3302         u16 proto_ver = 0;
3303         if (!playername.empty()) {
3304                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3305                 if (!player)
3306                         return;
3307                 peer_id = player->getPeerId();
3308                 proto_ver = player->protocol_version;
3309         }
3310
3311         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3312                         expirationtime, size, collisiondetection, collision_removal,
3313                         object_collision, vertical, texture, animation, glow);
3314 }
3315
3316 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3317         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3318         float minexptime, float maxexptime, float minsize, float maxsize,
3319         bool collisiondetection, bool collision_removal, bool object_collision,
3320         ServerActiveObject *attached, bool vertical, const std::string &texture,
3321         const std::string &playername, const struct TileAnimationParams &animation,
3322         u8 glow)
3323 {
3324         // m_env will be NULL if the server is initializing
3325         if (!m_env)
3326                 return -1;
3327
3328         session_t peer_id = PEER_ID_INEXISTENT;
3329         u16 proto_ver = 0;
3330         if (!playername.empty()) {
3331                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3332                 if (!player)
3333                         return -1;
3334                 peer_id = player->getPeerId();
3335                 proto_ver = player->protocol_version;
3336         }
3337
3338         u16 attached_id = attached ? attached->getId() : 0;
3339
3340         u32 id;
3341         if (attached_id == 0)
3342                 id = m_env->addParticleSpawner(spawntime);
3343         else
3344                 id = m_env->addParticleSpawner(spawntime, attached_id);
3345
3346         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3347                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3348                 minexptime, maxexptime, minsize, maxsize, collisiondetection,
3349                 collision_removal, object_collision, attached_id, vertical,
3350                 texture, id, animation, glow);
3351
3352         return id;
3353 }
3354
3355 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3356 {
3357         // m_env will be NULL if the server is initializing
3358         if (!m_env)
3359                 throw ServerError("Can't delete particle spawners during initialisation!");
3360
3361         session_t peer_id = PEER_ID_INEXISTENT;
3362         if (!playername.empty()) {
3363                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3364                 if (!player)
3365                         return;
3366                 peer_id = player->getPeerId();
3367         }
3368
3369         m_env->deleteParticleSpawner(id);
3370         SendDeleteParticleSpawner(peer_id, id);
3371 }
3372
3373 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3374 {
3375         if(m_detached_inventories.count(name) > 0){
3376                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3377                 delete m_detached_inventories[name];
3378         } else {
3379                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3380         }
3381         Inventory *inv = new Inventory(m_itemdef);
3382         sanity_check(inv);
3383         m_detached_inventories[name] = inv;
3384         if (!player.empty())
3385                 m_detached_inventories_player[name] = player;
3386
3387         //TODO find a better way to do this
3388         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3389         return inv;
3390 }
3391
3392 bool Server::removeDetachedInventory(const std::string &name)
3393 {
3394         const auto &inv_it = m_detached_inventories.find(name);
3395         if (inv_it == m_detached_inventories.end())
3396                 return false;
3397
3398         delete inv_it->second;
3399         m_detached_inventories.erase(inv_it);
3400
3401         if (!m_env) // Mods are not done loading
3402                 return true;
3403
3404         const auto &player_it = m_detached_inventories_player.find(name);
3405         if (player_it != m_detached_inventories_player.end()) {
3406                 RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());
3407
3408                 if (player && player->getPeerId() != PEER_ID_INEXISTENT)
3409                         sendDetachedInventory(name, player->getPeerId());
3410
3411                 m_detached_inventories_player.erase(player_it);
3412         } else {
3413                 // Notify all players about the change
3414                 sendDetachedInventory(name, PEER_ID_INEXISTENT);
3415         }
3416         return true;
3417 }
3418
3419 // actions: time-reversed list
3420 // Return value: success/failure
3421 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3422                 std::list<std::string> *log)
3423 {
3424         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3425         ServerMap *map = (ServerMap*)(&m_env->getMap());
3426
3427         // Fail if no actions to handle
3428         if (actions.empty()) {
3429                 assert(log);
3430                 log->push_back("Nothing to do.");
3431                 return false;
3432         }
3433
3434         int num_tried = 0;
3435         int num_failed = 0;
3436
3437         for (const RollbackAction &action : actions) {
3438                 num_tried++;
3439                 bool success = action.applyRevert(map, this, this);
3440                 if(!success){
3441                         num_failed++;
3442                         std::ostringstream os;
3443                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3444                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3445                         if (log)
3446                                 log->push_back(os.str());
3447                 }else{
3448                         std::ostringstream os;
3449                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3450                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3451                         if (log)
3452                                 log->push_back(os.str());
3453                 }
3454         }
3455
3456         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3457                         <<" failed"<<std::endl;
3458
3459         // Call it done if less than half failed
3460         return num_failed <= num_tried/2;
3461 }
3462
3463 // IGameDef interface
3464 // Under envlock
3465 IItemDefManager *Server::getItemDefManager()
3466 {
3467         return m_itemdef;
3468 }
3469
3470 const NodeDefManager *Server::getNodeDefManager()
3471 {
3472         return m_nodedef;
3473 }
3474
3475 ICraftDefManager *Server::getCraftDefManager()
3476 {
3477         return m_craftdef;
3478 }
3479
3480 u16 Server::allocateUnknownNodeId(const std::string &name)
3481 {
3482         return m_nodedef->allocateDummy(name);
3483 }
3484
3485 IWritableItemDefManager *Server::getWritableItemDefManager()
3486 {
3487         return m_itemdef;
3488 }
3489
3490 NodeDefManager *Server::getWritableNodeDefManager()
3491 {
3492         return m_nodedef;
3493 }
3494
3495 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3496 {
3497         return m_craftdef;
3498 }
3499
3500 const std::vector<ModSpec> & Server::getMods() const
3501 {
3502         return m_modmgr->getMods();
3503 }
3504
3505 const ModSpec *Server::getModSpec(const std::string &modname) const
3506 {
3507         return m_modmgr->getModSpec(modname);
3508 }
3509
3510 void Server::getModNames(std::vector<std::string> &modlist)
3511 {
3512         m_modmgr->getModNames(modlist);
3513 }
3514
3515 std::string Server::getBuiltinLuaPath()
3516 {
3517         return porting::path_share + DIR_DELIM + "builtin";
3518 }
3519
3520 std::string Server::getModStoragePath() const
3521 {
3522         return m_path_world + DIR_DELIM + "mod_storage";
3523 }
3524
3525 v3f Server::findSpawnPos()
3526 {
3527         ServerMap &map = m_env->getServerMap();
3528         v3f nodeposf;
3529         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
3530                 return nodeposf * BS;
3531
3532         bool is_good = false;
3533         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3534         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3535
3536         // Try to find a good place a few times
3537         for (s32 i = 0; i < 4000 && !is_good; i++) {
3538                 s32 range = MYMIN(1 + i, range_max);
3539                 // We're going to try to throw the player to this position
3540                 v2s16 nodepos2d = v2s16(
3541                         -range + (myrand() % (range * 2)),
3542                         -range + (myrand() % (range * 2)));
3543                 // Get spawn level at point
3544                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3545                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
3546                 // signify an unsuitable spawn position, or if outside limits.
3547                 if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
3548                                 spawn_level <= -MAX_MAP_GENERATION_LIMIT)
3549                         continue;
3550
3551                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3552                 // Consecutive empty nodes
3553                 s32 air_count = 0;
3554
3555                 // Search upwards from 'spawn level' for 2 consecutive empty nodes, to
3556                 // avoid obstructions in already-generated mapblocks.
3557                 // In ungenerated mapblocks consisting of 'ignore' nodes, there will be
3558                 // no obstructions, but mapgen decorations are generated after spawn so
3559                 // the player may end up inside one.
3560                 for (s32 i = 0; i < 8; i++) {
3561                         v3s16 blockpos = getNodeBlockPos(nodepos);
3562                         map.emergeBlock(blockpos, true);
3563                         content_t c = map.getNode(nodepos).getContent();
3564
3565                         // In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
3566                         // In ungenerated mapblocks allow spawn in 'ignore' nodes.
3567                         if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
3568                                 air_count++;
3569                                 if (air_count >= 2) {
3570                                         // Spawn in lower empty node
3571                                         nodepos.Y--;
3572                                         nodeposf = intToFloat(nodepos, BS);
3573                                         // Don't spawn the player outside map boundaries
3574                                         if (objectpos_over_limit(nodeposf))
3575                                                 // Exit this loop, positions above are probably over limit
3576                                                 break;
3577
3578                                         // Good position found, cause an exit from main loop
3579                                         is_good = true;
3580                                         break;
3581                                 }
3582                         } else {
3583                                 air_count = 0;
3584                         }
3585                         nodepos.Y++;
3586                 }
3587         }
3588
3589         if (is_good)
3590                 return nodeposf;
3591
3592         // No suitable spawn point found, return fallback 0,0,0
3593         return v3f(0.0f, 0.0f, 0.0f);
3594 }
3595
3596 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3597 {
3598         if (delay == 0.0f) {
3599         // No delay, shutdown immediately
3600                 m_shutdown_state.is_requested = true;
3601                 // only print to the infostream, a chat message saying
3602                 // "Server Shutting Down" is sent when the server destructs.
3603                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3604         } else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3605                 // Negative delay, cancel shutdown if requested
3606                 m_shutdown_state.reset();
3607                 std::wstringstream ws;
3608
3609                 ws << L"*** Server shutdown canceled.";
3610
3611                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3612                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3613                 // m_shutdown_* are already handled, skip.
3614                 return;
3615         } else if (delay > 0.0f) {
3616         // Positive delay, tell the clients when the server will shut down
3617                 std::wstringstream ws;
3618
3619                 ws << L"*** Server shutting down in "
3620                                 << duration_to_string(myround(delay)).c_str()
3621                                 << ".";
3622
3623                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3624                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3625         }
3626
3627         m_shutdown_state.trigger(delay, msg, reconnect);
3628 }
3629
3630 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3631 {
3632         /*
3633                 Try to get an existing player
3634         */
3635         RemotePlayer *player = m_env->getPlayer(name);
3636
3637         // If player is already connected, cancel
3638         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3639                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3640                 return NULL;
3641         }
3642
3643         /*
3644                 If player with the wanted peer_id already exists, cancel.
3645         */
3646         if (m_env->getPlayer(peer_id)) {
3647                 infostream<<"emergePlayer(): Player with wrong name but same"
3648                                 " peer_id already exists"<<std::endl;
3649                 return NULL;
3650         }
3651
3652         if (!player) {
3653                 player = new RemotePlayer(name, idef());
3654         }
3655
3656         bool newplayer = false;
3657
3658         // Load player
3659         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3660
3661         // Complete init with server parts
3662         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3663         player->protocol_version = proto_version;
3664
3665         /* Run scripts */
3666         if (newplayer) {
3667                 m_script->on_newplayer(playersao);
3668         }
3669
3670         return playersao;
3671 }
3672
3673 bool Server::registerModStorage(ModMetadata *storage)
3674 {
3675         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3676                 errorstream << "Unable to register same mod storage twice. Storage name: "
3677                                 << storage->getModName() << std::endl;
3678                 return false;
3679         }
3680
3681         m_mod_storages[storage->getModName()] = storage;
3682         return true;
3683 }
3684
3685 void Server::unregisterModStorage(const std::string &name)
3686 {
3687         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3688         if (it != m_mod_storages.end()) {
3689                 // Save unconditionaly on unregistration
3690                 it->second->save(getModStoragePath());
3691                 m_mod_storages.erase(name);
3692         }
3693 }
3694
3695 void dedicated_server_loop(Server &server, bool &kill)
3696 {
3697         verbosestream<<"dedicated_server_loop()"<<std::endl;
3698
3699         IntervalLimiter m_profiler_interval;
3700
3701         static thread_local const float steplen =
3702                         g_settings->getFloat("dedicated_server_step");
3703         static thread_local const float profiler_print_interval =
3704                         g_settings->getFloat("profiler_print_interval");
3705
3706         for(;;) {
3707                 // This is kind of a hack but can be done like this
3708                 // because server.step() is very light
3709                 sleep_ms((int)(steplen*1000.0));
3710                 server.step(steplen);
3711
3712                 if (server.isShutdownRequested() || kill)
3713                         break;
3714
3715                 /*
3716                         Profiler
3717                 */
3718                 if (profiler_print_interval != 0) {
3719                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3720                         {
3721                                 infostream<<"Profiler:"<<std::endl;
3722                                 g_profiler->print(infostream);
3723                                 g_profiler->clear();
3724                         }
3725                 }
3726         }
3727
3728         infostream << "Dedicated server quitting" << std::endl;
3729 #if USE_CURL
3730         if (g_settings->getBool("server_announce"))
3731                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3732                         server.m_bind_addr.getPort());
3733 #endif
3734 }
3735
3736 /*
3737  * Mod channels
3738  */
3739
3740
3741 bool Server::joinModChannel(const std::string &channel)
3742 {
3743         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3744                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3745 }
3746
3747 bool Server::leaveModChannel(const std::string &channel)
3748 {
3749         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3750 }
3751
3752 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3753 {
3754         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3755                 return false;
3756
3757         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3758         return true;
3759 }
3760
3761 ModChannel* Server::getModChannel(const std::string &channel)
3762 {
3763         return m_modchannel_mgr->getModChannel(channel);
3764 }
3765
3766 void Server::broadcastModChannelMessage(const std::string &channel,
3767                 const std::string &message, session_t from_peer)
3768 {
3769         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3770         if (peers.empty())
3771                 return;
3772
3773         if (message.size() > STRING_MAX_LEN) {
3774                 warningstream << "ModChannel message too long, dropping before sending "
3775                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3776                                 << channel << ")" << std::endl;
3777                 return;
3778         }
3779
3780         std::string sender;
3781         if (from_peer != PEER_ID_SERVER) {
3782                 sender = getPlayerName(from_peer);
3783         }
3784
3785         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3786                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3787         resp_pkt << channel << sender << message;
3788         for (session_t peer_id : peers) {
3789                 // Ignore sender
3790                 if (peer_id == from_peer)
3791                         continue;
3792
3793                 Send(peer_id, &resp_pkt);
3794         }
3795
3796         if (from_peer != PEER_ID_SERVER) {
3797                 m_script->on_modchannel_message(channel, sender, message);
3798         }
3799 }