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