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