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