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