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