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