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