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