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