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