]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Merge pull request #35 from arydevy/patch-1
[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.find_first_of("\n\r") != std::wstring::npos) {
3005                 return L"Newlines are not permitted in chat messages";
3006         }
3007
3008         // Run script hook, exit if script ate the chat message
3009         if (m_script->on_chat_message(name, message))
3010                 return L"";
3011
3012         // Line to send
3013         std::wstring line;
3014         // Whether to send line to the player that sent the message, or to all players
3015         bool broadcast_line = true;
3016
3017         if (check_shout_priv && !checkPriv(name, "shout")) {
3018                 line += L"-!- You don't have permission to shout.";
3019                 broadcast_line = false;
3020         } else {
3021                 /*
3022                         Workaround for fixing chat on Android. Lua doesn't handle
3023                         the Cyrillic alphabet and some characters on older Android devices
3024                 */
3025 #ifdef __ANDROID__
3026                 line += L"<" + utf8_to_wide(name) + L"> " + wmessage;
3027 #else
3028                 line += utf8_to_wide(m_script->formatChatMessage(name,
3029                                 wide_to_utf8(wmessage)));
3030 #endif
3031         }
3032
3033         /*
3034                 Tell calling method to send the message to sender
3035         */
3036         if (!broadcast_line)
3037                 return line;
3038
3039         /*
3040                 Send the message to others
3041         */
3042         actionstream << "CHAT: " << wide_to_utf8(unescape_enriched(line)) << std::endl;
3043
3044         ChatMessage chatmsg(line);
3045
3046         std::vector<session_t> clients = m_clients.getClientIDs();
3047         for (u16 cid : clients)
3048                 SendChatMessage(cid, chatmsg);
3049
3050         return L"";
3051 }
3052
3053 void Server::handleAdminChat(const ChatEventChat *evt)
3054 {
3055         std::string name = evt->nick;
3056         std::wstring wmessage = evt->evt_msg;
3057
3058         std::wstring answer = handleChat(name, wmessage);
3059
3060         // If asked to send answer to sender
3061         if (!answer.empty()) {
3062                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
3063         }
3064 }
3065
3066 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
3067 {
3068         RemoteClient *client = getClientNoEx(peer_id,state_min);
3069         if(!client)
3070                 throw ClientNotFoundException("Client not found");
3071
3072         return client;
3073 }
3074 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
3075 {
3076         return m_clients.getClientNoEx(peer_id, state_min);
3077 }
3078
3079 std::string Server::getPlayerName(session_t peer_id)
3080 {
3081         RemotePlayer *player = m_env->getPlayer(peer_id);
3082         if (!player)
3083                 return "[id="+itos(peer_id)+"]";
3084         return player->getName();
3085 }
3086
3087 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
3088 {
3089         RemotePlayer *player = m_env->getPlayer(peer_id);
3090         if (!player)
3091                 return NULL;
3092         return player->getPlayerSAO();
3093 }
3094
3095 std::string Server::getStatusString()
3096 {
3097         std::ostringstream os(std::ios_base::binary);
3098         os << "# Server: ";
3099         // Version
3100         os << "version=" << g_version_string;
3101         // Uptime
3102         os << ", uptime=" << m_uptime_counter->get();
3103         // Max lag estimate
3104         os << ", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
3105
3106         // Information about clients
3107         bool first = true;
3108         os << ", clients={";
3109         if (m_env) {
3110                 std::vector<session_t> clients = m_clients.getClientIDs();
3111                 for (session_t client_id : clients) {
3112                         RemotePlayer *player = m_env->getPlayer(client_id);
3113
3114                         // Get name of player
3115                         const char *name = player ? player->getName() : "<unknown>";
3116
3117                         // Add name to information string
3118                         if (!first)
3119                                 os << ", ";
3120                         else
3121                                 first = false;
3122                         os << name;
3123                 }
3124         }
3125         os << "}";
3126
3127         if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3128                 os << std::endl << "# Server: " << " WARNING: Map saving is disabled.";
3129
3130         if (!g_settings->get("motd").empty())
3131                 os << std::endl << "# Server: " << g_settings->get("motd");
3132
3133         return os.str();
3134 }
3135
3136 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3137 {
3138         std::set<std::string> privs;
3139         m_script->getAuth(name, NULL, &privs);
3140         return privs;
3141 }
3142
3143 bool Server::checkPriv(const std::string &name, const std::string &priv)
3144 {
3145         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3146         return (privs.count(priv) != 0);
3147 }
3148
3149 void Server::reportPrivsModified(const std::string &name)
3150 {
3151         if (name.empty()) {
3152                 std::vector<session_t> clients = m_clients.getClientIDs();
3153                 for (const session_t client_id : clients) {
3154                         RemotePlayer *player = m_env->getPlayer(client_id);
3155                         reportPrivsModified(player->getName());
3156                 }
3157         } else {
3158                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3159                 if (!player)
3160                         return;
3161                 SendPlayerPrivileges(player->getPeerId());
3162                 PlayerSAO *sao = player->getPlayerSAO();
3163                 if(!sao)
3164                         return;
3165                 sao->updatePrivileges(
3166                                 getPlayerEffectivePrivs(name),
3167                                 isSingleplayer());
3168         }
3169 }
3170
3171 void Server::reportInventoryFormspecModified(const std::string &name)
3172 {
3173         RemotePlayer *player = m_env->getPlayer(name.c_str());
3174         if (!player)
3175                 return;
3176         SendPlayerInventoryFormspec(player->getPeerId());
3177 }
3178
3179 void Server::reportFormspecPrependModified(const std::string &name)
3180 {
3181         RemotePlayer *player = m_env->getPlayer(name.c_str());
3182         if (!player)
3183                 return;
3184         SendPlayerFormspecPrepend(player->getPeerId());
3185 }
3186
3187 void Server::setIpBanned(const std::string &ip, const std::string &name)
3188 {
3189         m_banmanager->add(ip, name);
3190 }
3191
3192 void Server::unsetIpBanned(const std::string &ip_or_name)
3193 {
3194         m_banmanager->remove(ip_or_name);
3195 }
3196
3197 std::string Server::getBanDescription(const std::string &ip_or_name)
3198 {
3199         return m_banmanager->getBanDescription(ip_or_name);
3200 }
3201
3202 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3203 {
3204         // m_env will be NULL if the server is initializing
3205         if (!m_env)
3206                 return;
3207
3208         if (m_admin_nick == name && !m_admin_nick.empty()) {
3209                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3210         }
3211
3212         RemotePlayer *player = m_env->getPlayer(name);
3213         if (!player) {
3214                 return;
3215         }
3216
3217         if (player->getPeerId() == PEER_ID_INEXISTENT)
3218                 return;
3219
3220         SendChatMessage(player->getPeerId(), ChatMessage(msg));
3221 }
3222
3223 bool Server::showFormspec(const char *playername, const std::string &formspec,
3224         const std::string &formname)
3225 {
3226         // m_env will be NULL if the server is initializing
3227         if (!m_env)
3228                 return false;
3229
3230         RemotePlayer *player = m_env->getPlayer(playername);
3231         if (!player)
3232                 return false;
3233
3234         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3235         return true;
3236 }
3237
3238 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3239 {
3240         if (!player)
3241                 return -1;
3242
3243         u32 id = player->addHud(form);
3244
3245         SendHUDAdd(player->getPeerId(), id, form);
3246
3247         return id;
3248 }
3249
3250 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3251         if (!player)
3252                 return false;
3253
3254         HudElement* todel = player->removeHud(id);
3255
3256         if (!todel)
3257                 return false;
3258
3259         delete todel;
3260
3261         SendHUDRemove(player->getPeerId(), id);
3262         return true;
3263 }
3264
3265 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3266 {
3267         if (!player)
3268                 return false;
3269
3270         SendHUDChange(player->getPeerId(), id, stat, data);
3271         return true;
3272 }
3273
3274 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3275 {
3276         if (!player)
3277                 return false;
3278
3279         SendHUDSetFlags(player->getPeerId(), flags, mask);
3280         player->hud_flags &= ~mask;
3281         player->hud_flags |= flags;
3282
3283         PlayerSAO* playersao = player->getPlayerSAO();
3284
3285         if (!playersao)
3286                 return false;
3287
3288         m_script->player_event(playersao, "hud_changed");
3289         return true;
3290 }
3291
3292 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3293 {
3294         if (!player)
3295                 return false;
3296
3297         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3298                 return false;
3299
3300         player->setHotbarItemcount(hotbar_itemcount);
3301         std::ostringstream os(std::ios::binary);
3302         writeS32(os, hotbar_itemcount);
3303         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3304         return true;
3305 }
3306
3307 void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
3308 {
3309         if (!player)
3310                 return;
3311
3312         player->setHotbarImage(name);
3313         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3314 }
3315
3316 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
3317 {
3318         if (!player)
3319                 return;
3320
3321         player->setHotbarSelectedImage(name);
3322         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3323 }
3324
3325 Address Server::getPeerAddress(session_t peer_id)
3326 {
3327         // Note that this is only set after Init was received in Server::handleCommand_Init
3328         return getClient(peer_id, CS_Invalid)->getAddress();
3329 }
3330
3331 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3332                 v2s32 animation_frames[4], f32 frame_speed)
3333 {
3334         sanity_check(player);
3335         player->setLocalAnimations(animation_frames, frame_speed);
3336         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3337 }
3338
3339 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3340 {
3341         sanity_check(player);
3342         player->eye_offset_first = first;
3343         player->eye_offset_third = third;
3344         SendEyeOffset(player->getPeerId(), first, third);
3345 }
3346
3347 void Server::setSky(RemotePlayer *player, const SkyboxParams &params)
3348 {
3349         sanity_check(player);
3350         player->setSky(params);
3351         SendSetSky(player->getPeerId(), params);
3352 }
3353
3354 void Server::setSun(RemotePlayer *player, const SunParams &params)
3355 {
3356         sanity_check(player);
3357         player->setSun(params);
3358         SendSetSun(player->getPeerId(), params);
3359 }
3360
3361 void Server::setMoon(RemotePlayer *player, const MoonParams &params)
3362 {
3363         sanity_check(player);
3364         player->setMoon(params);
3365         SendSetMoon(player->getPeerId(), params);
3366 }
3367
3368 void Server::setStars(RemotePlayer *player, const StarParams &params)
3369 {
3370         sanity_check(player);
3371         player->setStars(params);
3372         SendSetStars(player->getPeerId(), params);
3373 }
3374
3375 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3376 {
3377         sanity_check(player);
3378         player->setCloudParams(params);
3379         SendCloudParams(player->getPeerId(), params);
3380 }
3381
3382 void Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3383         float ratio)
3384 {
3385         sanity_check(player);
3386         player->overrideDayNightRatio(do_override, ratio);
3387         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3388 }
3389
3390 void Server::notifyPlayers(const std::wstring &msg)
3391 {
3392         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3393 }
3394
3395 void Server::spawnParticle(const std::string &playername,
3396         const ParticleParameters &p)
3397 {
3398         // m_env will be NULL if the server is initializing
3399         if (!m_env)
3400                 return;
3401
3402         session_t peer_id = PEER_ID_INEXISTENT;
3403         u16 proto_ver = 0;
3404         if (!playername.empty()) {
3405                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3406                 if (!player)
3407                         return;
3408                 peer_id = player->getPeerId();
3409                 proto_ver = player->protocol_version;
3410         }
3411
3412         SendSpawnParticle(peer_id, proto_ver, p);
3413 }
3414
3415 u32 Server::addParticleSpawner(const ParticleSpawnerParameters &p,
3416         ServerActiveObject *attached, const std::string &playername)
3417 {
3418         // m_env will be NULL if the server is initializing
3419         if (!m_env)
3420                 return -1;
3421
3422         session_t peer_id = PEER_ID_INEXISTENT;
3423         u16 proto_ver = 0;
3424         if (!playername.empty()) {
3425                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3426                 if (!player)
3427                         return -1;
3428                 peer_id = player->getPeerId();
3429                 proto_ver = player->protocol_version;
3430         }
3431
3432         u16 attached_id = attached ? attached->getId() : 0;
3433
3434         u32 id;
3435         if (attached_id == 0)
3436                 id = m_env->addParticleSpawner(p.time);
3437         else
3438                 id = m_env->addParticleSpawner(p.time, attached_id);
3439
3440         SendAddParticleSpawner(peer_id, proto_ver, p, attached_id, id);
3441         return id;
3442 }
3443
3444 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3445 {
3446         // m_env will be NULL if the server is initializing
3447         if (!m_env)
3448                 throw ServerError("Can't delete particle spawners during initialisation!");
3449
3450         session_t peer_id = PEER_ID_INEXISTENT;
3451         if (!playername.empty()) {
3452                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3453                 if (!player)
3454                         return;
3455                 peer_id = player->getPeerId();
3456         }
3457
3458         m_env->deleteParticleSpawner(id);
3459         SendDeleteParticleSpawner(peer_id, id);
3460 }
3461
3462 bool Server::dynamicAddMedia(const std::string &filepath,
3463         std::vector<RemotePlayer*> &sent_to)
3464 {
3465         std::string filename = fs::GetFilenameFromPath(filepath.c_str());
3466         if (m_media.find(filename) != m_media.end()) {
3467                 errorstream << "Server::dynamicAddMedia(): file \"" << filename
3468                         << "\" already exists in media cache" << std::endl;
3469                 return false;
3470         }
3471
3472         // Load the file and add it to our media cache
3473         std::string filedata, raw_hash;
3474         bool ok = addMediaFile(filename, filepath, &filedata, &raw_hash);
3475         if (!ok)
3476                 return false;
3477
3478         // Push file to existing clients
3479         NetworkPacket pkt(TOCLIENT_MEDIA_PUSH, 0);
3480         pkt << raw_hash << filename << (bool) true;
3481         pkt.putLongString(filedata);
3482
3483         m_clients.lock();
3484         for (auto &pair : m_clients.getClientList()) {
3485                 if (pair.second->getState() < CS_DefinitionsSent)
3486                         continue;
3487                 if (pair.second->net_proto_version < 39)
3488                         continue;
3489
3490                 if (auto player = m_env->getPlayer(pair.second->peer_id))
3491                         sent_to.emplace_back(player);
3492                 /*
3493                         FIXME: this is a very awful hack
3494                         The network layer only guarantees ordered delivery inside a channel.
3495                         Since the very next packet could be one that uses the media, we have
3496                         to push the media over ALL channels to ensure it is processed before
3497                         it is used.
3498                         In practice this means we have to send it twice:
3499                         - channel 1 (HUD)
3500                         - channel 0 (everything else: e.g. play_sound, object messages)
3501                 */
3502                 m_clients.send(pair.second->peer_id, 1, &pkt, true);
3503                 m_clients.send(pair.second->peer_id, 0, &pkt, true);
3504         }
3505         m_clients.unlock();
3506
3507         return true;
3508 }
3509
3510 // actions: time-reversed list
3511 // Return value: success/failure
3512 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3513                 std::list<std::string> *log)
3514 {
3515         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3516         ServerMap *map = (ServerMap*)(&m_env->getMap());
3517
3518         // Fail if no actions to handle
3519         if (actions.empty()) {
3520                 assert(log);
3521                 log->push_back("Nothing to do.");
3522                 return false;
3523         }
3524
3525         int num_tried = 0;
3526         int num_failed = 0;
3527
3528         for (const RollbackAction &action : actions) {
3529                 num_tried++;
3530                 bool success = action.applyRevert(map, m_inventory_mgr.get(), this);
3531                 if(!success){
3532                         num_failed++;
3533                         std::ostringstream os;
3534                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3535                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3536                         if (log)
3537                                 log->push_back(os.str());
3538                 }else{
3539                         std::ostringstream os;
3540                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3541                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3542                         if (log)
3543                                 log->push_back(os.str());
3544                 }
3545         }
3546
3547         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3548                         <<" failed"<<std::endl;
3549
3550         // Call it done if less than half failed
3551         return num_failed <= num_tried/2;
3552 }
3553
3554 // IGameDef interface
3555 // Under envlock
3556 IItemDefManager *Server::getItemDefManager()
3557 {
3558         return m_itemdef;
3559 }
3560
3561 const NodeDefManager *Server::getNodeDefManager()
3562 {
3563         return m_nodedef;
3564 }
3565
3566 ICraftDefManager *Server::getCraftDefManager()
3567 {
3568         return m_craftdef;
3569 }
3570
3571 u16 Server::allocateUnknownNodeId(const std::string &name)
3572 {
3573         return m_nodedef->allocateDummy(name);
3574 }
3575
3576 IWritableItemDefManager *Server::getWritableItemDefManager()
3577 {
3578         return m_itemdef;
3579 }
3580
3581 NodeDefManager *Server::getWritableNodeDefManager()
3582 {
3583         return m_nodedef;
3584 }
3585
3586 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3587 {
3588         return m_craftdef;
3589 }
3590
3591 const std::vector<ModSpec> & Server::getMods() const
3592 {
3593         return m_modmgr->getMods();
3594 }
3595
3596 const ModSpec *Server::getModSpec(const std::string &modname) const
3597 {
3598         return m_modmgr->getModSpec(modname);
3599 }
3600
3601 void Server::getModNames(std::vector<std::string> &modlist)
3602 {
3603         m_modmgr->getModNames(modlist);
3604 }
3605
3606 std::string Server::getBuiltinLuaPath()
3607 {
3608         return porting::path_share + DIR_DELIM + "builtin";
3609 }
3610
3611 std::string Server::getModStoragePath() const
3612 {
3613         return m_path_world + DIR_DELIM + "mod_storage";
3614 }
3615
3616 v3f Server::findSpawnPos()
3617 {
3618         ServerMap &map = m_env->getServerMap();
3619         v3f nodeposf;
3620         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
3621                 return nodeposf * BS;
3622
3623         bool is_good = false;
3624         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3625         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3626
3627         // Try to find a good place a few times
3628         for (s32 i = 0; i < 4000 && !is_good; i++) {
3629                 s32 range = MYMIN(1 + i, range_max);
3630                 // We're going to try to throw the player to this position
3631                 v2s16 nodepos2d = v2s16(
3632                         -range + (myrand() % (range * 2)),
3633                         -range + (myrand() % (range * 2)));
3634                 // Get spawn level at point
3635                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3636                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
3637                 // signify an unsuitable spawn position, or if outside limits.
3638                 if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
3639                                 spawn_level <= -MAX_MAP_GENERATION_LIMIT)
3640                         continue;
3641
3642                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3643                 // Consecutive empty nodes
3644                 s32 air_count = 0;
3645
3646                 // Search upwards from 'spawn level' for 2 consecutive empty nodes, to
3647                 // avoid obstructions in already-generated mapblocks.
3648                 // In ungenerated mapblocks consisting of 'ignore' nodes, there will be
3649                 // no obstructions, but mapgen decorations are generated after spawn so
3650                 // the player may end up inside one.
3651                 for (s32 i = 0; i < 8; i++) {
3652                         v3s16 blockpos = getNodeBlockPos(nodepos);
3653                         map.emergeBlock(blockpos, true);
3654                         content_t c = map.getNode(nodepos).getContent();
3655
3656                         // In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
3657                         // In ungenerated mapblocks allow spawn in 'ignore' nodes.
3658                         if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
3659                                 air_count++;
3660                                 if (air_count >= 2) {
3661                                         // Spawn in lower empty node
3662                                         nodepos.Y--;
3663                                         nodeposf = intToFloat(nodepos, BS);
3664                                         // Don't spawn the player outside map boundaries
3665                                         if (objectpos_over_limit(nodeposf))
3666                                                 // Exit this loop, positions above are probably over limit
3667                                                 break;
3668
3669                                         // Good position found, cause an exit from main loop
3670                                         is_good = true;
3671                                         break;
3672                                 }
3673                         } else {
3674                                 air_count = 0;
3675                         }
3676                         nodepos.Y++;
3677                 }
3678         }
3679
3680         if (is_good)
3681                 return nodeposf;
3682
3683         // No suitable spawn point found, return fallback 0,0,0
3684         return v3f(0.0f, 0.0f, 0.0f);
3685 }
3686
3687 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3688 {
3689         if (delay == 0.0f) {
3690         // No delay, shutdown immediately
3691                 m_shutdown_state.is_requested = true;
3692                 // only print to the infostream, a chat message saying
3693                 // "Server Shutting Down" is sent when the server destructs.
3694                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3695         } else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3696                 // Negative delay, cancel shutdown if requested
3697                 m_shutdown_state.reset();
3698                 std::wstringstream ws;
3699
3700                 ws << L"*** Server shutdown canceled.";
3701
3702                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3703                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3704                 // m_shutdown_* are already handled, skip.
3705                 return;
3706         } else if (delay > 0.0f) {
3707         // Positive delay, tell the clients when the server will shut down
3708                 std::wstringstream ws;
3709
3710                 ws << L"*** Server shutting down in "
3711                                 << duration_to_string(myround(delay)).c_str()
3712                                 << ".";
3713
3714                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3715                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3716         }
3717
3718         m_shutdown_state.trigger(delay, msg, reconnect);
3719 }
3720
3721 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3722 {
3723         /*
3724                 Try to get an existing player
3725         */
3726         RemotePlayer *player = m_env->getPlayer(name);
3727
3728         // If player is already connected, cancel
3729         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3730                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3731                 return NULL;
3732         }
3733
3734         /*
3735                 If player with the wanted peer_id already exists, cancel.
3736         */
3737         if (m_env->getPlayer(peer_id)) {
3738                 infostream<<"emergePlayer(): Player with wrong name but same"
3739                                 " peer_id already exists"<<std::endl;
3740                 return NULL;
3741         }
3742
3743         if (!player) {
3744                 player = new RemotePlayer(name, idef());
3745         }
3746
3747         bool newplayer = false;
3748
3749         // Load player
3750         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3751
3752         // Complete init with server parts
3753         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3754         player->protocol_version = proto_version;
3755
3756         /* Run scripts */
3757         if (newplayer) {
3758                 m_script->on_newplayer(playersao);
3759         }
3760
3761         return playersao;
3762 }
3763
3764 bool Server::registerModStorage(ModMetadata *storage)
3765 {
3766         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3767                 errorstream << "Unable to register same mod storage twice. Storage name: "
3768                                 << storage->getModName() << std::endl;
3769                 return false;
3770         }
3771
3772         m_mod_storages[storage->getModName()] = storage;
3773         return true;
3774 }
3775
3776 void Server::unregisterModStorage(const std::string &name)
3777 {
3778         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3779         if (it != m_mod_storages.end()) {
3780                 // Save unconditionaly on unregistration
3781                 it->second->save(getModStoragePath());
3782                 m_mod_storages.erase(name);
3783         }
3784 }
3785
3786 void dedicated_server_loop(Server &server, bool &kill)
3787 {
3788         verbosestream<<"dedicated_server_loop()"<<std::endl;
3789
3790         IntervalLimiter m_profiler_interval;
3791
3792         static thread_local const float steplen =
3793                         g_settings->getFloat("dedicated_server_step");
3794         static thread_local const float profiler_print_interval =
3795                         g_settings->getFloat("profiler_print_interval");
3796
3797         /*
3798          * The dedicated server loop only does time-keeping (in Server::step) and
3799          * provides a way to main.cpp to kill the server externally (bool &kill).
3800          */
3801
3802         for(;;) {
3803                 // This is kind of a hack but can be done like this
3804                 // because server.step() is very light
3805                 sleep_ms((int)(steplen*1000.0));
3806                 server.step(steplen);
3807
3808                 if (server.isShutdownRequested() || kill)
3809                         break;
3810
3811                 /*
3812                         Profiler
3813                 */
3814                 if (profiler_print_interval != 0) {
3815                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3816                         {
3817                                 infostream<<"Profiler:"<<std::endl;
3818                                 g_profiler->print(infostream);
3819                                 g_profiler->clear();
3820                         }
3821                 }
3822         }
3823
3824         infostream << "Dedicated server quitting" << std::endl;
3825 #if USE_CURL
3826         if (g_settings->getBool("server_announce"))
3827                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3828                         server.m_bind_addr.getPort());
3829 #endif
3830 }
3831
3832 /*
3833  * Mod channels
3834  */
3835
3836
3837 bool Server::joinModChannel(const std::string &channel)
3838 {
3839         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3840                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3841 }
3842
3843 bool Server::leaveModChannel(const std::string &channel)
3844 {
3845         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3846 }
3847
3848 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3849 {
3850         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3851                 return false;
3852
3853         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3854         return true;
3855 }
3856
3857 ModChannel* Server::getModChannel(const std::string &channel)
3858 {
3859         return m_modchannel_mgr->getModChannel(channel);
3860 }
3861
3862 void Server::broadcastModChannelMessage(const std::string &channel,
3863                 const std::string &message, session_t from_peer)
3864 {
3865         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3866         if (peers.empty())
3867                 return;
3868
3869         if (message.size() > STRING_MAX_LEN) {
3870                 warningstream << "ModChannel message too long, dropping before sending "
3871                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3872                                 << channel << ")" << std::endl;
3873                 return;
3874         }
3875
3876         std::string sender;
3877         if (from_peer != PEER_ID_SERVER) {
3878                 sender = getPlayerName(from_peer);
3879         }
3880
3881         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3882                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3883         resp_pkt << channel << sender << message;
3884         for (session_t peer_id : peers) {
3885                 // Ignore sender
3886                 if (peer_id == from_peer)
3887                         continue;
3888
3889                 Send(peer_id, &resp_pkt);
3890         }
3891
3892         if (from_peer != PEER_ID_SERVER) {
3893                 m_script->on_modchannel_message(channel, sender, message);
3894         }
3895 }
3896
3897 Translations *Server::getTranslationLanguage(const std::string &lang_code)
3898 {
3899         if (lang_code.empty())
3900                 return nullptr;
3901
3902         auto it = server_translations.find(lang_code);
3903         if (it != server_translations.end())
3904                 return &it->second; // Already loaded
3905
3906         // [] will create an entry
3907         auto *translations = &server_translations[lang_code];
3908
3909         std::string suffix = "." + lang_code + ".tr";
3910         for (const auto &i : m_media) {
3911                 if (str_ends_with(i.first, suffix)) {
3912                         std::string data;
3913                         if (fs::ReadFile(i.second.path, data)) {
3914                                 translations->loadTranslation(data);
3915                         }
3916                 }
3917         }
3918
3919         return translations;
3920 }