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