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