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