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