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