]> git.lizzy.rs Git - minetest.git/blob - src/server.cpp
Add support for statbar “off state” icons (#9462)
[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 << form->text2;
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                 case HUD_STAT_TEXT2:
1651                         pkt << *(std::string *) value;
1652                         break;
1653                 case HUD_STAT_WORLD_POS:
1654                         pkt << *(v3f *) value;
1655                         break;
1656                 case HUD_STAT_SIZE:
1657                         pkt << *(v2s32 *) value;
1658                         break;
1659                 case HUD_STAT_NUMBER:
1660                 case HUD_STAT_ITEM:
1661                 case HUD_STAT_DIR:
1662                 default:
1663                         pkt << *(u32 *) value;
1664                         break;
1665         }
1666
1667         Send(&pkt);
1668 }
1669
1670 void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
1671 {
1672         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1673
1674         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1675
1676         pkt << flags << mask;
1677
1678         Send(&pkt);
1679 }
1680
1681 void Server::SendHUDSetParam(session_t peer_id, u16 param, const std::string &value)
1682 {
1683         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1684         pkt << param << value;
1685         Send(&pkt);
1686 }
1687
1688 void Server::SendSetSky(session_t peer_id, const SkyboxParams &params)
1689 {
1690         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1691
1692         // Handle prior clients here
1693         if (m_clients.getProtocolVersion(peer_id) < 39) {
1694                 pkt << params.bgcolor << params.type << (u16) params.textures.size();
1695
1696                 for (const std::string& texture : params.textures)
1697                         pkt << texture;
1698
1699                 pkt << params.clouds;
1700         } else { // Handle current clients and future clients
1701                 pkt << params.bgcolor << params.type
1702                 << params.clouds << params.fog_sun_tint
1703                 << params.fog_moon_tint << params.fog_tint_type;
1704
1705                 if (params.type == "skybox") {
1706                         pkt << (u16) params.textures.size();
1707                         for (const std::string &texture : params.textures)
1708                                 pkt << texture;
1709                 } else if (params.type == "regular") {
1710                         pkt << params.sky_color.day_sky << params.sky_color.day_horizon
1711                                 << params.sky_color.dawn_sky << params.sky_color.dawn_horizon
1712                                 << params.sky_color.night_sky << params.sky_color.night_horizon
1713                                 << params.sky_color.indoors;
1714                 }
1715         }
1716
1717         Send(&pkt);
1718 }
1719
1720 void Server::SendSetSun(session_t peer_id, const SunParams &params)
1721 {
1722         NetworkPacket pkt(TOCLIENT_SET_SUN, 0, peer_id);
1723         pkt << params.visible << params.texture
1724                 << params.tonemap << params.sunrise
1725                 << params.sunrise_visible << params.scale;
1726
1727         Send(&pkt);
1728 }
1729 void Server::SendSetMoon(session_t peer_id, const MoonParams &params)
1730 {
1731         NetworkPacket pkt(TOCLIENT_SET_MOON, 0, peer_id);
1732
1733         pkt << params.visible << params.texture
1734                 << params.tonemap << params.scale;
1735
1736         Send(&pkt);
1737 }
1738 void Server::SendSetStars(session_t peer_id, const StarParams &params)
1739 {
1740         NetworkPacket pkt(TOCLIENT_SET_STARS, 0, peer_id);
1741
1742         pkt << params.visible << params.count
1743                 << params.starcolor << params.scale;
1744
1745         Send(&pkt);
1746 }
1747
1748 void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
1749 {
1750         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1751         pkt << params.density << params.color_bright << params.color_ambient
1752                         << params.height << params.thickness << params.speed;
1753         Send(&pkt);
1754 }
1755
1756 void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
1757                 float ratio)
1758 {
1759         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1760                         1 + 2, peer_id);
1761
1762         pkt << do_override << (u16) (ratio * 65535);
1763
1764         Send(&pkt);
1765 }
1766
1767 void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
1768 {
1769         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1770         pkt << time << time_speed;
1771
1772         if (peer_id == PEER_ID_INEXISTENT) {
1773                 m_clients.sendToAll(&pkt);
1774         }
1775         else {
1776                 Send(&pkt);
1777         }
1778 }
1779
1780 void Server::SendPlayerHP(session_t peer_id)
1781 {
1782         PlayerSAO *playersao = getPlayerSAO(peer_id);
1783         assert(playersao);
1784
1785         SendHP(peer_id, playersao->getHP());
1786         m_script->player_event(playersao,"health_changed");
1787
1788         // Send to other clients
1789         playersao->sendPunchCommand();
1790 }
1791
1792 void Server::SendPlayerBreath(PlayerSAO *sao)
1793 {
1794         assert(sao);
1795
1796         m_script->player_event(sao, "breath_changed");
1797         SendBreath(sao->getPeerID(), sao->getBreath());
1798 }
1799
1800 void Server::SendMovePlayer(session_t peer_id)
1801 {
1802         RemotePlayer *player = m_env->getPlayer(peer_id);
1803         assert(player);
1804         PlayerSAO *sao = player->getPlayerSAO();
1805         assert(sao);
1806
1807         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1808         pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
1809
1810         {
1811                 v3f pos = sao->getBasePosition();
1812                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1813                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1814                                 << " pitch=" << sao->getLookPitch()
1815                                 << " yaw=" << sao->getRotation().Y
1816                                 << std::endl;
1817         }
1818
1819         Send(&pkt);
1820 }
1821
1822 void Server::SendPlayerFov(session_t peer_id)
1823 {
1824         NetworkPacket pkt(TOCLIENT_FOV, 4 + 1 + 4, peer_id);
1825
1826         PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov();
1827         pkt << fov_spec.fov << fov_spec.is_multiplier << fov_spec.transition_time;
1828
1829         Send(&pkt);
1830 }
1831
1832 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1833                 f32 animation_speed)
1834 {
1835         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1836                 peer_id);
1837
1838         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1839                         << animation_frames[3] << animation_speed;
1840
1841         Send(&pkt);
1842 }
1843
1844 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1845 {
1846         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1847         pkt << first << third;
1848         Send(&pkt);
1849 }
1850
1851 void Server::SendPlayerPrivileges(session_t peer_id)
1852 {
1853         RemotePlayer *player = m_env->getPlayer(peer_id);
1854         assert(player);
1855         if(player->getPeerId() == PEER_ID_INEXISTENT)
1856                 return;
1857
1858         std::set<std::string> privs;
1859         m_script->getAuth(player->getName(), NULL, &privs);
1860
1861         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1862         pkt << (u16) privs.size();
1863
1864         for (const std::string &priv : privs) {
1865                 pkt << priv;
1866         }
1867
1868         Send(&pkt);
1869 }
1870
1871 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1872 {
1873         RemotePlayer *player = m_env->getPlayer(peer_id);
1874         assert(player);
1875         if (player->getPeerId() == PEER_ID_INEXISTENT)
1876                 return;
1877
1878         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1879         pkt.putLongString(player->inventory_formspec);
1880
1881         Send(&pkt);
1882 }
1883
1884 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1885 {
1886         RemotePlayer *player = m_env->getPlayer(peer_id);
1887         assert(player);
1888         if (player->getPeerId() == PEER_ID_INEXISTENT)
1889                 return;
1890
1891         NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1892         pkt << player->formspec_prepend;
1893         Send(&pkt);
1894 }
1895
1896 void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
1897 {
1898         // Radius inside which objects are active
1899         static thread_local const s16 radius =
1900                 g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
1901
1902         // Radius inside which players are active
1903         static thread_local const bool is_transfer_limited =
1904                 g_settings->exists("unlimited_player_transfer_distance") &&
1905                 !g_settings->getBool("unlimited_player_transfer_distance");
1906
1907         static thread_local const s16 player_transfer_dist =
1908                 g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
1909
1910         s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
1911                 radius : player_transfer_dist;
1912
1913         s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
1914         if (my_radius <= 0)
1915                 my_radius = radius;
1916
1917         std::queue<u16> removed_objects, added_objects;
1918         m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
1919                 client->m_known_objects, removed_objects);
1920         m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
1921                 client->m_known_objects, added_objects);
1922
1923         int removed_count = removed_objects.size();
1924         int added_count   = added_objects.size();
1925
1926         if (removed_objects.empty() && added_objects.empty())
1927                 return;
1928
1929         char buf[4];
1930         std::string data;
1931
1932         // Handle removed objects
1933         writeU16((u8*)buf, removed_objects.size());
1934         data.append(buf, 2);
1935         while (!removed_objects.empty()) {
1936                 // Get object
1937                 u16 id = removed_objects.front();
1938                 ServerActiveObject* obj = m_env->getActiveObject(id);
1939
1940                 // Add to data buffer for sending
1941                 writeU16((u8*)buf, id);
1942                 data.append(buf, 2);
1943
1944                 // Remove from known objects
1945                 client->m_known_objects.erase(id);
1946
1947                 if (obj && obj->m_known_by_count > 0)
1948                         obj->m_known_by_count--;
1949
1950                 removed_objects.pop();
1951         }
1952
1953         // Handle added objects
1954         writeU16((u8*)buf, added_objects.size());
1955         data.append(buf, 2);
1956         while (!added_objects.empty()) {
1957                 // Get object
1958                 u16 id = added_objects.front();
1959                 ServerActiveObject *obj = m_env->getActiveObject(id);
1960                 added_objects.pop();
1961
1962                 if (!obj) {
1963                         warningstream << FUNCTION_NAME << ": NULL object id="
1964                                 << (int)id << std::endl;
1965                         continue;
1966                 }
1967
1968                 // Get object type
1969                 u8 type = obj->getSendType();
1970
1971                 // Add to data buffer for sending
1972                 writeU16((u8*)buf, id);
1973                 data.append(buf, 2);
1974                 writeU8((u8*)buf, type);
1975                 data.append(buf, 1);
1976
1977                 data.append(serializeLongString(
1978                         obj->getClientInitializationData(client->net_proto_version)));
1979
1980                 // Add to known objects
1981                 client->m_known_objects.insert(id);
1982
1983                 obj->m_known_by_count++;
1984         }
1985
1986         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, data.size(), client->peer_id);
1987         pkt.putRawString(data.c_str(), data.size());
1988         Send(&pkt);
1989
1990         verbosestream << "Server::SendActiveObjectRemoveAdd: "
1991                 << removed_count << " removed, " << added_count << " added, "
1992                 << "packet size is " << pkt.getSize() << std::endl;
1993 }
1994
1995 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
1996                 bool reliable)
1997 {
1998         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1999                         datas.size(), peer_id);
2000
2001         pkt.putRawString(datas.c_str(), datas.size());
2002
2003         m_clients.send(pkt.getPeerId(),
2004                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
2005                         &pkt, reliable);
2006 }
2007
2008 void Server::SendCSMRestrictionFlags(session_t peer_id)
2009 {
2010         NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
2011                 sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
2012         pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
2013         Send(&pkt);
2014 }
2015
2016 void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
2017 {
2018         NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
2019         pkt << added_vel;
2020         Send(&pkt);
2021 }
2022
2023 inline s32 Server::nextSoundId()
2024 {
2025         s32 ret = m_next_sound_id;
2026         if (m_next_sound_id == INT32_MAX)
2027                 m_next_sound_id = 0; // signed overflow is undefined
2028         else
2029                 m_next_sound_id++;
2030         return ret;
2031 }
2032
2033 s32 Server::playSound(const SimpleSoundSpec &spec,
2034                 const ServerSoundParams &params, bool ephemeral)
2035 {
2036         // Find out initial position of sound
2037         bool pos_exists = false;
2038         v3f pos = params.getPos(m_env, &pos_exists);
2039         // If position is not found while it should be, cancel sound
2040         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
2041                 return -1;
2042
2043         // Filter destination clients
2044         std::vector<session_t> dst_clients;
2045         if (!params.to_player.empty()) {
2046                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
2047                 if(!player){
2048                         infostream<<"Server::playSound: Player \""<<params.to_player
2049                                         <<"\" not found"<<std::endl;
2050                         return -1;
2051                 }
2052                 if (player->getPeerId() == PEER_ID_INEXISTENT) {
2053                         infostream<<"Server::playSound: Player \""<<params.to_player
2054                                         <<"\" not connected"<<std::endl;
2055                         return -1;
2056                 }
2057                 dst_clients.push_back(player->getPeerId());
2058         } else {
2059                 std::vector<session_t> clients = m_clients.getClientIDs();
2060
2061                 for (const session_t client_id : clients) {
2062                         RemotePlayer *player = m_env->getPlayer(client_id);
2063                         if (!player)
2064                                 continue;
2065                         if (!params.exclude_player.empty() &&
2066                                         params.exclude_player == player->getName())
2067                                 continue;
2068
2069                         PlayerSAO *sao = player->getPlayerSAO();
2070                         if (!sao)
2071                                 continue;
2072
2073                         if (pos_exists) {
2074                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2075                                                 params.max_hear_distance)
2076                                         continue;
2077                         }
2078                         dst_clients.push_back(client_id);
2079                 }
2080         }
2081
2082         if(dst_clients.empty())
2083                 return -1;
2084
2085         // Create the sound
2086         s32 id;
2087         ServerPlayingSound *psound = nullptr;
2088         if (ephemeral) {
2089                 id = -1; // old clients will still use this, so pick a reserved ID
2090         } else {
2091                 id = nextSoundId();
2092                 // The sound will exist as a reference in m_playing_sounds
2093                 m_playing_sounds[id] = ServerPlayingSound();
2094                 psound = &m_playing_sounds[id];
2095                 psound->params = params;
2096                 psound->spec = spec;
2097         }
2098
2099         float gain = params.gain * spec.gain;
2100         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2101         pkt << id << spec.name << gain
2102                         << (u8) params.type << pos << params.object
2103                         << params.loop << params.fade << params.pitch
2104                         << ephemeral;
2105
2106         bool as_reliable = !ephemeral;
2107
2108         for (const u16 dst_client : dst_clients) {
2109                 if (psound)
2110                         psound->clients.insert(dst_client);
2111                 m_clients.send(dst_client, 0, &pkt, as_reliable);
2112         }
2113         return id;
2114 }
2115 void Server::stopSound(s32 handle)
2116 {
2117         // Get sound reference
2118         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2119                 m_playing_sounds.find(handle);
2120         if (i == m_playing_sounds.end())
2121                 return;
2122         ServerPlayingSound &psound = i->second;
2123
2124         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2125         pkt << handle;
2126
2127         for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2128                         si != psound.clients.end(); ++si) {
2129                 // Send as reliable
2130                 m_clients.send(*si, 0, &pkt, true);
2131         }
2132         // Remove sound reference
2133         m_playing_sounds.erase(i);
2134 }
2135
2136 void Server::fadeSound(s32 handle, float step, float gain)
2137 {
2138         // Get sound reference
2139         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2140                 m_playing_sounds.find(handle);
2141         if (i == m_playing_sounds.end())
2142                 return;
2143
2144         ServerPlayingSound &psound = i->second;
2145         psound.params.gain = gain;
2146
2147         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2148         pkt << handle << step << gain;
2149
2150         // Backwards compability
2151         bool play_sound = gain > 0;
2152         ServerPlayingSound compat_psound = psound;
2153         compat_psound.clients.clear();
2154
2155         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2156         compat_pkt << handle;
2157
2158         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2159                         it != psound.clients.end();) {
2160                 if (m_clients.getProtocolVersion(*it) >= 32) {
2161                         // Send as reliable
2162                         m_clients.send(*it, 0, &pkt, true);
2163                         ++it;
2164                 } else {
2165                         compat_psound.clients.insert(*it);
2166                         // Stop old sound
2167                         m_clients.send(*it, 0, &compat_pkt, true);
2168                         psound.clients.erase(it++);
2169                 }
2170         }
2171
2172         // Remove sound reference
2173         if (!play_sound || psound.clients.empty())
2174                 m_playing_sounds.erase(i);
2175
2176         if (play_sound && !compat_psound.clients.empty()) {
2177                 // Play new sound volume on older clients
2178                 playSound(compat_psound.spec, compat_psound.params);
2179         }
2180 }
2181
2182 void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
2183                 float far_d_nodes)
2184 {
2185         float maxd = far_d_nodes * BS;
2186         v3f p_f = intToFloat(p, BS);
2187         v3s16 block_pos = getNodeBlockPos(p);
2188
2189         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2190         pkt << p;
2191
2192         std::vector<session_t> clients = m_clients.getClientIDs();
2193         m_clients.lock();
2194
2195         for (session_t client_id : clients) {
2196                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2197                 if (!client)
2198                         continue;
2199
2200                 RemotePlayer *player = m_env->getPlayer(client_id);
2201                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2202
2203                 // If player is far away, only set modified blocks not sent
2204                 if (!client->isBlockSent(block_pos) || (sao &&
2205                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2206                         if (far_players)
2207                                 far_players->emplace(client_id);
2208                         else
2209                                 client->SetBlockNotSent(block_pos);
2210                         continue;
2211                 }
2212
2213                 // Send as reliable
2214                 m_clients.send(client_id, 0, &pkt, true);
2215         }
2216
2217         m_clients.unlock();
2218 }
2219
2220 void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
2221                 float far_d_nodes, bool remove_metadata)
2222 {
2223         float maxd = far_d_nodes * BS;
2224         v3f p_f = intToFloat(p, BS);
2225         v3s16 block_pos = getNodeBlockPos(p);
2226
2227         NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2228         pkt << p << n.param0 << n.param1 << n.param2
2229                         << (u8) (remove_metadata ? 0 : 1);
2230
2231         std::vector<session_t> clients = m_clients.getClientIDs();
2232         m_clients.lock();
2233
2234         for (session_t client_id : clients) {
2235                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2236                 if (!client)
2237                         continue;
2238
2239                 RemotePlayer *player = m_env->getPlayer(client_id);
2240                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2241
2242                 // If player is far away, only set modified blocks not sent
2243                 if (!client->isBlockSent(block_pos) || (sao &&
2244                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2245                         if (far_players)
2246                                 far_players->emplace(client_id);
2247                         else
2248                                 client->SetBlockNotSent(block_pos);
2249                         continue;
2250                 }
2251
2252                 // Send as reliable
2253                 m_clients.send(client_id, 0, &pkt, true);
2254         }
2255
2256         m_clients.unlock();
2257 }
2258
2259 void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes)
2260 {
2261         float maxd = far_d_nodes * BS;
2262         NodeMetadataList meta_updates_list(false);
2263         std::vector<session_t> clients = m_clients.getClientIDs();
2264
2265         m_clients.lock();
2266
2267         for (session_t i : clients) {
2268                 RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2269                 if (!client)
2270                         continue;
2271
2272                 ServerActiveObject *player = m_env->getActiveObject(i);
2273                 v3f player_pos = player ? player->getBasePosition() : v3f();
2274
2275                 for (const v3s16 &pos : meta_updates) {
2276                         NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
2277
2278                         if (!meta)
2279                                 continue;
2280
2281                         v3s16 block_pos = getNodeBlockPos(pos);
2282                         if (!client->isBlockSent(block_pos) || (player &&
2283                                         player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) {
2284                                 client->SetBlockNotSent(block_pos);
2285                                 continue;
2286                         }
2287
2288                         // Add the change to send list
2289                         meta_updates_list.set(pos, meta);
2290                 }
2291                 if (meta_updates_list.size() == 0)
2292                         continue;
2293
2294                 // Send the meta changes
2295                 std::ostringstream os(std::ios::binary);
2296                 meta_updates_list.serialize(os, client->net_proto_version, false, true);
2297                 std::ostringstream oss(std::ios::binary);
2298                 compressZlib(os.str(), oss);
2299
2300                 NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0);
2301                 pkt.putLongString(oss.str());
2302                 m_clients.send(i, 0, &pkt, true);
2303
2304                 meta_updates_list.clear();
2305         }
2306
2307         m_clients.unlock();
2308 }
2309
2310 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2311                 u16 net_proto_version)
2312 {
2313         /*
2314                 Create a packet with the block in the right format
2315         */
2316
2317         std::ostringstream os(std::ios_base::binary);
2318         block->serialize(os, ver, false);
2319         block->serializeNetworkSpecific(os);
2320         std::string s = os.str();
2321
2322         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2323
2324         pkt << block->getPos();
2325         pkt.putRawString(s.c_str(), s.size());
2326         Send(&pkt);
2327 }
2328
2329 void Server::SendBlocks(float dtime)
2330 {
2331         MutexAutoLock envlock(m_env_mutex);
2332         //TODO check if one big lock could be faster then multiple small ones
2333
2334         std::vector<PrioritySortedBlockTransfer> queue;
2335
2336         u32 total_sending = 0;
2337
2338         {
2339                 ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
2340
2341                 std::vector<session_t> clients = m_clients.getClientIDs();
2342
2343                 m_clients.lock();
2344                 for (const session_t client_id : clients) {
2345                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2346
2347                         if (!client)
2348                                 continue;
2349
2350                         total_sending += client->getSendingCount();
2351                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2352                 }
2353                 m_clients.unlock();
2354         }
2355
2356         // Sort.
2357         // Lowest priority number comes first.
2358         // Lowest is most important.
2359         std::sort(queue.begin(), queue.end());
2360
2361         m_clients.lock();
2362
2363         // Maximal total count calculation
2364         // The per-client block sends is halved with the maximal online users
2365         u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2366                 g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2367
2368         ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
2369         Map &map = m_env->getMap();
2370
2371         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2372                 if (total_sending >= max_blocks_to_send)
2373                         break;
2374
2375                 MapBlock *block = map.getBlockNoCreateNoEx(block_to_send.pos);
2376                 if (!block)
2377                         continue;
2378
2379                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2380                                 CS_Active);
2381                 if (!client)
2382                         continue;
2383
2384                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2385                                 client->net_proto_version);
2386
2387                 client->SentBlock(block_to_send.pos);
2388                 total_sending++;
2389         }
2390         m_clients.unlock();
2391 }
2392
2393 bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos)
2394 {
2395         MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2396         if (!block)
2397                 return false;
2398
2399         m_clients.lock();
2400         RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active);
2401         if (!client || client->isBlockSent(blockpos)) {
2402                 m_clients.unlock();
2403                 return false;
2404         }
2405         SendBlockNoLock(peer_id, block, client->serialization_version,
2406                         client->net_proto_version);
2407         m_clients.unlock();
2408
2409         return true;
2410 }
2411
2412 void Server::fillMediaCache()
2413 {
2414         infostream<<"Server: Calculating media file checksums"<<std::endl;
2415
2416         // Collect all media file paths
2417         std::vector<std::string> paths;
2418         m_modmgr->getModsMediaPaths(paths);
2419         fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2420         fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2421
2422         // Collect media file information from paths into cache
2423         for (const std::string &mediapath : paths) {
2424                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2425                 for (const fs::DirListNode &dln : dirlist) {
2426                         if (dln.dir) // Ignode dirs
2427                                 continue;
2428                         std::string filename = dln.name;
2429                         // If name contains illegal characters, ignore the file
2430                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2431                                 infostream<<"Server: ignoring illegal file name: \""
2432                                                 << filename << "\"" << std::endl;
2433                                 continue;
2434                         }
2435                         // If name is not in a supported format, ignore it
2436                         const char *supported_ext[] = {
2437                                 ".png", ".jpg", ".bmp", ".tga",
2438                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2439                                 ".ogg",
2440                                 ".x", ".b3d", ".md2", ".obj",
2441                                 // Custom translation file format
2442                                 ".tr",
2443                                 NULL
2444                         };
2445                         if (removeStringEnd(filename, supported_ext).empty()){
2446                                 infostream << "Server: ignoring unsupported file extension: \""
2447                                                 << filename << "\"" << std::endl;
2448                                 continue;
2449                         }
2450                         // Ok, attempt to load the file and add to cache
2451                         std::string filepath;
2452                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2453
2454                         // Read data
2455                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2456                         if (!fis.good()) {
2457                                 errorstream << "Server::fillMediaCache(): Could not open \""
2458                                                 << filename << "\" for reading" << std::endl;
2459                                 continue;
2460                         }
2461                         std::ostringstream tmp_os(std::ios_base::binary);
2462                         bool bad = false;
2463                         for(;;) {
2464                                 char buf[1024];
2465                                 fis.read(buf, 1024);
2466                                 std::streamsize len = fis.gcount();
2467                                 tmp_os.write(buf, len);
2468                                 if (fis.eof())
2469                                         break;
2470                                 if (!fis.good()) {
2471                                         bad = true;
2472                                         break;
2473                                 }
2474                         }
2475                         if(bad) {
2476                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2477                                                 << filename << "\"" << std::endl;
2478                                 continue;
2479                         }
2480                         if(tmp_os.str().length() == 0) {
2481                                 errorstream << "Server::fillMediaCache(): Empty file \""
2482                                                 << filepath << "\"" << std::endl;
2483                                 continue;
2484                         }
2485
2486                         SHA1 sha1;
2487                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2488
2489                         unsigned char *digest = sha1.getDigest();
2490                         std::string sha1_base64 = base64_encode(digest, 20);
2491                         std::string sha1_hex = hex_encode((char*)digest, 20);
2492                         free(digest);
2493
2494                         // Put in list
2495                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2496                         verbosestream << "Server: " << sha1_hex << " is " << filename
2497                                         << std::endl;
2498                 }
2499         }
2500 }
2501
2502 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2503 {
2504         // Make packet
2505         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2506
2507         u16 media_sent = 0;
2508         std::string lang_suffix;
2509         lang_suffix.append(".").append(lang_code).append(".tr");
2510         for (const auto &i : m_media) {
2511                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2512                         continue;
2513                 media_sent++;
2514         }
2515
2516         pkt << media_sent;
2517
2518         for (const auto &i : m_media) {
2519                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2520                         continue;
2521                 pkt << i.first << i.second.sha1_digest;
2522         }
2523
2524         pkt << g_settings->get("remote_media");
2525         Send(&pkt);
2526
2527         verbosestream << "Server: Announcing files to id(" << peer_id
2528                 << "): count=" << media_sent << " size=" << pkt.getSize() << std::endl;
2529 }
2530
2531 struct SendableMedia
2532 {
2533         std::string name;
2534         std::string path;
2535         std::string data;
2536
2537         SendableMedia(const std::string &name_="", const std::string &path_="",
2538                       const std::string &data_=""):
2539                 name(name_),
2540                 path(path_),
2541                 data(data_)
2542         {}
2543 };
2544
2545 void Server::sendRequestedMedia(session_t peer_id,
2546                 const std::vector<std::string> &tosend)
2547 {
2548         verbosestream<<"Server::sendRequestedMedia(): "
2549                         <<"Sending files to client"<<std::endl;
2550
2551         /* Read files */
2552
2553         // Put 5kB in one bunch (this is not accurate)
2554         u32 bytes_per_bunch = 5000;
2555
2556         std::vector< std::vector<SendableMedia> > file_bunches;
2557         file_bunches.emplace_back();
2558
2559         u32 file_size_bunch_total = 0;
2560
2561         for (const std::string &name : tosend) {
2562                 if (m_media.find(name) == m_media.end()) {
2563                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2564                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2565                         continue;
2566                 }
2567
2568                 //TODO get path + name
2569                 std::string tpath = m_media[name].path;
2570
2571                 // Read data
2572                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2573                 if(!fis.good()){
2574                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2575                                         <<tpath<<"\" for reading"<<std::endl;
2576                         continue;
2577                 }
2578                 std::ostringstream tmp_os(std::ios_base::binary);
2579                 bool bad = false;
2580                 for(;;) {
2581                         char buf[1024];
2582                         fis.read(buf, 1024);
2583                         std::streamsize len = fis.gcount();
2584                         tmp_os.write(buf, len);
2585                         file_size_bunch_total += len;
2586                         if(fis.eof())
2587                                 break;
2588                         if(!fis.good()) {
2589                                 bad = true;
2590                                 break;
2591                         }
2592                 }
2593                 if (bad) {
2594                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2595                                         <<name<<"\""<<std::endl;
2596                         continue;
2597                 }
2598                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2599                                 <<tname<<"\""<<std::endl;*/
2600                 // Put in list
2601                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2602
2603                 // Start next bunch if got enough data
2604                 if(file_size_bunch_total >= bytes_per_bunch) {
2605                         file_bunches.emplace_back();
2606                         file_size_bunch_total = 0;
2607                 }
2608
2609         }
2610
2611         /* Create and send packets */
2612
2613         u16 num_bunches = file_bunches.size();
2614         for (u16 i = 0; i < num_bunches; i++) {
2615                 /*
2616                         u16 command
2617                         u16 total number of texture bunches
2618                         u16 index of this bunch
2619                         u32 number of files in this bunch
2620                         for each file {
2621                                 u16 length of name
2622                                 string name
2623                                 u32 length of data
2624                                 data
2625                         }
2626                 */
2627
2628                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2629                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2630
2631                 for (const SendableMedia &j : file_bunches[i]) {
2632                         pkt << j.name;
2633                         pkt.putLongString(j.data);
2634                 }
2635
2636                 verbosestream << "Server::sendRequestedMedia(): bunch "
2637                                 << i << "/" << num_bunches
2638                                 << " files=" << file_bunches[i].size()
2639                                 << " size="  << pkt.getSize() << std::endl;
2640                 Send(&pkt);
2641         }
2642 }
2643
2644 void Server::sendDetachedInventory(Inventory *inventory, const std::string &name, session_t peer_id)
2645 {
2646         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2647         pkt << name;
2648
2649         if (!inventory) {
2650                 pkt << false; // Remove inventory
2651         } else {
2652                 pkt << true; // Update inventory
2653
2654                 // Serialization & NetworkPacket isn't a love story
2655                 std::ostringstream os(std::ios_base::binary);
2656                 inventory->serialize(os);
2657                 inventory->setModified(false);
2658
2659                 const std::string &os_str = os.str();
2660                 pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
2661                 pkt.putRawString(os_str);
2662         }
2663
2664         if (peer_id == PEER_ID_INEXISTENT)
2665                 m_clients.sendToAll(&pkt);
2666         else
2667                 Send(&pkt);
2668 }
2669
2670 void Server::sendDetachedInventories(session_t peer_id, bool incremental)
2671 {
2672         // Lookup player name, to filter detached inventories just after
2673         std::string peer_name;
2674         if (peer_id != PEER_ID_INEXISTENT) {
2675                 peer_name = getClient(peer_id, CS_Created)->getName();
2676         }
2677
2678         auto send_cb = [this, peer_id](const std::string &name, Inventory *inv) {
2679                 sendDetachedInventory(inv, name, peer_id);
2680         };
2681
2682         m_inventory_mgr->sendDetachedInventories(peer_name, incremental, send_cb);
2683 }
2684
2685 /*
2686         Something random
2687 */
2688
2689 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2690 {
2691         PlayerSAO *playersao = getPlayerSAO(peer_id);
2692         assert(playersao);
2693
2694         infostream << "Server::DiePlayer(): Player "
2695                         << playersao->getPlayer()->getName()
2696                         << " dies" << std::endl;
2697
2698         playersao->setHP(0, reason);
2699         playersao->clearParentAttachment();
2700
2701         // Trigger scripted stuff
2702         m_script->on_dieplayer(playersao, reason);
2703
2704         SendPlayerHP(peer_id);
2705         SendDeathscreen(peer_id, false, v3f(0,0,0));
2706 }
2707
2708 void Server::RespawnPlayer(session_t peer_id)
2709 {
2710         PlayerSAO *playersao = getPlayerSAO(peer_id);
2711         assert(playersao);
2712
2713         infostream << "Server::RespawnPlayer(): Player "
2714                         << playersao->getPlayer()->getName()
2715                         << " respawns" << std::endl;
2716
2717         playersao->setHP(playersao->accessObjectProperties()->hp_max,
2718                         PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2719         playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2720
2721         bool repositioned = m_script->on_respawnplayer(playersao);
2722         if (!repositioned) {
2723                 // setPos will send the new position to client
2724                 playersao->setPos(findSpawnPos());
2725         }
2726
2727         SendPlayerHP(peer_id);
2728 }
2729
2730
2731 void Server::DenySudoAccess(session_t peer_id)
2732 {
2733         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2734         Send(&pkt);
2735 }
2736
2737
2738 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2739                 const std::string &str_reason, bool reconnect)
2740 {
2741         SendAccessDenied(peer_id, reason, str_reason, reconnect);
2742
2743         m_clients.event(peer_id, CSE_SetDenied);
2744         DisconnectPeer(peer_id);
2745 }
2746
2747
2748 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2749                 const std::string &custom_reason)
2750 {
2751         SendAccessDenied(peer_id, reason, custom_reason);
2752         m_clients.event(peer_id, CSE_SetDenied);
2753         DisconnectPeer(peer_id);
2754 }
2755
2756 // 13/03/15: remove this function when protocol version 25 will become
2757 // the minimum version for MT users, maybe in 1 year
2758 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2759 {
2760         SendAccessDenied_Legacy(peer_id, reason);
2761         m_clients.event(peer_id, CSE_SetDenied);
2762         DisconnectPeer(peer_id);
2763 }
2764
2765 void Server::DisconnectPeer(session_t peer_id)
2766 {
2767         m_modchannel_mgr->leaveAllChannels(peer_id);
2768         m_con->DisconnectPeer(peer_id);
2769 }
2770
2771 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2772 {
2773         if (!forSudoMode) {
2774                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2775
2776                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2777
2778                 // Right now, the auth mechs don't change between login and sudo mode.
2779                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2780                 client->allowed_sudo_mechs = sudo_auth_mechs;
2781
2782                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2783                                 << g_settings->getFloat("dedicated_server_step")
2784                                 << sudo_auth_mechs;
2785
2786                 Send(&resp_pkt);
2787                 m_clients.event(peer_id, CSE_AuthAccept);
2788         } else {
2789                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2790
2791                 // We only support SRP right now
2792                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2793
2794                 resp_pkt << sudo_auth_mechs;
2795                 Send(&resp_pkt);
2796                 m_clients.event(peer_id, CSE_SudoSuccess);
2797         }
2798 }
2799
2800 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2801 {
2802         std::wstring message;
2803         {
2804                 /*
2805                         Clear references to playing sounds
2806                 */
2807                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2808                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2809                         ServerPlayingSound &psound = i->second;
2810                         psound.clients.erase(peer_id);
2811                         if (psound.clients.empty())
2812                                 m_playing_sounds.erase(i++);
2813                         else
2814                                 ++i;
2815                 }
2816
2817                 // clear formspec info so the next client can't abuse the current state
2818                 m_formspec_state_data.erase(peer_id);
2819
2820                 RemotePlayer *player = m_env->getPlayer(peer_id);
2821
2822                 /* Run scripts and remove from environment */
2823                 if (player) {
2824                         PlayerSAO *playersao = player->getPlayerSAO();
2825                         assert(playersao);
2826
2827                         playersao->clearChildAttachments();
2828                         playersao->clearParentAttachment();
2829
2830                         // inform connected clients
2831                         const std::string &player_name = player->getName();
2832                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2833                         // (u16) 1 + std::string represents a vector serialization representation
2834                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
2835                         m_clients.sendToAll(&notice);
2836                         // run scripts
2837                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2838
2839                         playersao->disconnected();
2840                 }
2841
2842                 /*
2843                         Print out action
2844                 */
2845                 {
2846                         if (player && reason != CDR_DENY) {
2847                                 std::ostringstream os(std::ios_base::binary);
2848                                 std::vector<session_t> clients = m_clients.getClientIDs();
2849
2850                                 for (const session_t client_id : clients) {
2851                                         // Get player
2852                                         RemotePlayer *player = m_env->getPlayer(client_id);
2853                                         if (!player)
2854                                                 continue;
2855
2856                                         // Get name of player
2857                                         os << player->getName() << " ";
2858                                 }
2859
2860                                 std::string name = player->getName();
2861                                 actionstream << name << " "
2862                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2863                                                 << " List of players: " << os.str() << std::endl;
2864                                 if (m_admin_chat)
2865                                         m_admin_chat->outgoing_queue.push_back(
2866                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2867                         }
2868                 }
2869                 {
2870                         MutexAutoLock env_lock(m_env_mutex);
2871                         m_clients.DeleteClient(peer_id);
2872                 }
2873         }
2874
2875         // Send leave chat message to all remaining clients
2876         if (!message.empty()) {
2877                 SendChatMessage(PEER_ID_INEXISTENT,
2878                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2879         }
2880 }
2881
2882 void Server::UpdateCrafting(RemotePlayer *player)
2883 {
2884         InventoryList *clist = player->inventory.getList("craft");
2885         if (!clist || clist->getSize() == 0)
2886                 return;
2887
2888         if (!clist->checkModified())
2889                 return;
2890
2891         // Get a preview for crafting
2892         ItemStack preview;
2893         InventoryLocation loc;
2894         loc.setPlayer(player->getName());
2895         std::vector<ItemStack> output_replacements;
2896         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2897         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2898                         clist, loc);
2899
2900         InventoryList *plist = player->inventory.getList("craftpreview");
2901         if (plist && plist->getSize() >= 1) {
2902                 // Put the new preview in
2903                 plist->changeItem(0, preview);
2904         }
2905 }
2906
2907 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2908 {
2909         if (evt->type == CET_NICK_ADD) {
2910                 // The terminal informed us of its nick choice
2911                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2912                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2913                         errorstream << "You haven't set up an account." << std::endl
2914                                 << "Please log in using the client as '"
2915                                 << m_admin_nick << "' with a secure password." << std::endl
2916                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2917                                 << "and everybody can claim the user account instead of you," << std::endl
2918                                 << "giving them full control over this server." << std::endl;
2919                 }
2920         } else {
2921                 assert(evt->type == CET_CHAT);
2922                 handleAdminChat((ChatEventChat *)evt);
2923         }
2924 }
2925
2926 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2927         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2928 {
2929         // If something goes wrong, this player is to blame
2930         RollbackScopeActor rollback_scope(m_rollback,
2931                         std::string("player:") + name);
2932
2933         if (g_settings->getBool("strip_color_codes"))
2934                 wmessage = unescape_enriched(wmessage);
2935
2936         if (player) {
2937                 switch (player->canSendChatMessage()) {
2938                 case RPLAYER_CHATRESULT_FLOODING: {
2939                         std::wstringstream ws;
2940                         ws << L"You cannot send more messages. You are limited to "
2941                                         << g_settings->getFloat("chat_message_limit_per_10sec")
2942                                         << L" messages per 10 seconds.";
2943                         return ws.str();
2944                 }
2945                 case RPLAYER_CHATRESULT_KICK:
2946                         DenyAccess_Legacy(player->getPeerId(),
2947                                         L"You have been kicked due to message flooding.");
2948                         return L"";
2949                 case RPLAYER_CHATRESULT_OK:
2950                         break;
2951                 default:
2952                         FATAL_ERROR("Unhandled chat filtering result found.");
2953                 }
2954         }
2955
2956         if (m_max_chatmessage_length > 0
2957                         && wmessage.length() > m_max_chatmessage_length) {
2958                 return L"Your message exceed the maximum chat message limit set on the server. "
2959                                 L"It was refused. Send a shorter message";
2960         }
2961
2962         auto message = trim(wide_to_utf8(wmessage));
2963         if (message.find_first_of("\n\r") != std::wstring::npos) {
2964                 return L"New lines are not permitted in chat messages";
2965         }
2966
2967         // Run script hook, exit if script ate the chat message
2968         if (m_script->on_chat_message(name, message))
2969                 return L"";
2970
2971         // Line to send
2972         std::wstring line;
2973         // Whether to send line to the player that sent the message, or to all players
2974         bool broadcast_line = true;
2975
2976         if (check_shout_priv && !checkPriv(name, "shout")) {
2977                 line += L"-!- You don't have permission to shout.";
2978                 broadcast_line = false;
2979         } else {
2980                 /*
2981                         Workaround for fixing chat on Android. Lua doesn't handle
2982                         the Cyrillic alphabet and some characters on older Android devices
2983                 */
2984 #ifdef __ANDROID__
2985                 line += L"<" + wname + L"> " + wmessage;
2986 #else
2987                 line += narrow_to_wide(m_script->formatChatMessage(name,
2988                                 wide_to_narrow(wmessage)));
2989 #endif
2990         }
2991
2992         /*
2993                 Tell calling method to send the message to sender
2994         */
2995         if (!broadcast_line)
2996                 return line;
2997
2998         /*
2999                 Send the message to others
3000         */
3001         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
3002
3003         std::vector<session_t> clients = m_clients.getClientIDs();
3004
3005         /*
3006                 Send the message back to the inital sender
3007                 if they are using protocol version >= 29
3008         */
3009
3010         session_t peer_id_to_avoid_sending =
3011                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
3012
3013         if (player && player->protocol_version >= 29)
3014                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
3015
3016         for (u16 cid : clients) {
3017                 if (cid != peer_id_to_avoid_sending)
3018                         SendChatMessage(cid, ChatMessage(line));
3019         }
3020         return L"";
3021 }
3022
3023 void Server::handleAdminChat(const ChatEventChat *evt)
3024 {
3025         std::string name = evt->nick;
3026         std::wstring wname = utf8_to_wide(name);
3027         std::wstring wmessage = evt->evt_msg;
3028
3029         std::wstring answer = handleChat(name, wname, wmessage);
3030
3031         // If asked to send answer to sender
3032         if (!answer.empty()) {
3033                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
3034         }
3035 }
3036
3037 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
3038 {
3039         RemoteClient *client = getClientNoEx(peer_id,state_min);
3040         if(!client)
3041                 throw ClientNotFoundException("Client not found");
3042
3043         return client;
3044 }
3045 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
3046 {
3047         return m_clients.getClientNoEx(peer_id, state_min);
3048 }
3049
3050 std::string Server::getPlayerName(session_t peer_id)
3051 {
3052         RemotePlayer *player = m_env->getPlayer(peer_id);
3053         if (!player)
3054                 return "[id="+itos(peer_id)+"]";
3055         return player->getName();
3056 }
3057
3058 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
3059 {
3060         RemotePlayer *player = m_env->getPlayer(peer_id);
3061         if (!player)
3062                 return NULL;
3063         return player->getPlayerSAO();
3064 }
3065
3066 std::wstring Server::getStatusString()
3067 {
3068         std::wostringstream os(std::ios_base::binary);
3069         os << L"# Server: ";
3070         // Version
3071         os << L"version=" << narrow_to_wide(g_version_string);
3072         // Uptime
3073         os << L", uptime=" << m_uptime_counter->get();
3074         // Max lag estimate
3075         os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
3076
3077         // Information about clients
3078         bool first = true;
3079         os << L", clients={";
3080         if (m_env) {
3081                 std::vector<session_t> clients = m_clients.getClientIDs();
3082                 for (session_t client_id : clients) {
3083                         RemotePlayer *player = m_env->getPlayer(client_id);
3084
3085                         // Get name of player
3086                         std::wstring name = L"unknown";
3087                         if (player)
3088                                 name = narrow_to_wide(player->getName());
3089
3090                         // Add name to information string
3091                         if (!first)
3092                                 os << L", ";
3093                         else
3094                                 first = false;
3095
3096                         os << name;
3097                 }
3098         }
3099         os << L"}";
3100
3101         if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3102                 os << std::endl << L"# Server: " << " WARNING: Map saving is disabled.";
3103
3104         if (!g_settings->get("motd").empty())
3105                 os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd"));
3106
3107         return os.str();
3108 }
3109
3110 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3111 {
3112         std::set<std::string> privs;
3113         m_script->getAuth(name, NULL, &privs);
3114         return privs;
3115 }
3116
3117 bool Server::checkPriv(const std::string &name, const std::string &priv)
3118 {
3119         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3120         return (privs.count(priv) != 0);
3121 }
3122
3123 void Server::reportPrivsModified(const std::string &name)
3124 {
3125         if (name.empty()) {
3126                 std::vector<session_t> clients = m_clients.getClientIDs();
3127                 for (const session_t client_id : clients) {
3128                         RemotePlayer *player = m_env->getPlayer(client_id);
3129                         reportPrivsModified(player->getName());
3130                 }
3131         } else {
3132                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3133                 if (!player)
3134                         return;
3135                 SendPlayerPrivileges(player->getPeerId());
3136                 PlayerSAO *sao = player->getPlayerSAO();
3137                 if(!sao)
3138                         return;
3139                 sao->updatePrivileges(
3140                                 getPlayerEffectivePrivs(name),
3141                                 isSingleplayer());
3142         }
3143 }
3144
3145 void Server::reportInventoryFormspecModified(const std::string &name)
3146 {
3147         RemotePlayer *player = m_env->getPlayer(name.c_str());
3148         if (!player)
3149                 return;
3150         SendPlayerInventoryFormspec(player->getPeerId());
3151 }
3152
3153 void Server::reportFormspecPrependModified(const std::string &name)
3154 {
3155         RemotePlayer *player = m_env->getPlayer(name.c_str());
3156         if (!player)
3157                 return;
3158         SendPlayerFormspecPrepend(player->getPeerId());
3159 }
3160
3161 void Server::setIpBanned(const std::string &ip, const std::string &name)
3162 {
3163         m_banmanager->add(ip, name);
3164 }
3165
3166 void Server::unsetIpBanned(const std::string &ip_or_name)
3167 {
3168         m_banmanager->remove(ip_or_name);
3169 }
3170
3171 std::string Server::getBanDescription(const std::string &ip_or_name)
3172 {
3173         return m_banmanager->getBanDescription(ip_or_name);
3174 }
3175
3176 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3177 {
3178         // m_env will be NULL if the server is initializing
3179         if (!m_env)
3180                 return;
3181
3182         if (m_admin_nick == name && !m_admin_nick.empty()) {
3183                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3184         }
3185
3186         RemotePlayer *player = m_env->getPlayer(name);
3187         if (!player) {
3188                 return;
3189         }
3190
3191         if (player->getPeerId() == PEER_ID_INEXISTENT)
3192                 return;
3193
3194         SendChatMessage(player->getPeerId(), ChatMessage(msg));
3195 }
3196
3197 bool Server::showFormspec(const char *playername, const std::string &formspec,
3198         const std::string &formname)
3199 {
3200         // m_env will be NULL if the server is initializing
3201         if (!m_env)
3202                 return false;
3203
3204         RemotePlayer *player = m_env->getPlayer(playername);
3205         if (!player)
3206                 return false;
3207
3208         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3209         return true;
3210 }
3211
3212 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3213 {
3214         if (!player)
3215                 return -1;
3216
3217         u32 id = player->addHud(form);
3218
3219         SendHUDAdd(player->getPeerId(), id, form);
3220
3221         return id;
3222 }
3223
3224 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3225         if (!player)
3226                 return false;
3227
3228         HudElement* todel = player->removeHud(id);
3229
3230         if (!todel)
3231                 return false;
3232
3233         delete todel;
3234
3235         SendHUDRemove(player->getPeerId(), id);
3236         return true;
3237 }
3238
3239 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3240 {
3241         if (!player)
3242                 return false;
3243
3244         SendHUDChange(player->getPeerId(), id, stat, data);
3245         return true;
3246 }
3247
3248 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3249 {
3250         if (!player)
3251                 return false;
3252
3253         SendHUDSetFlags(player->getPeerId(), flags, mask);
3254         player->hud_flags &= ~mask;
3255         player->hud_flags |= flags;
3256
3257         PlayerSAO* playersao = player->getPlayerSAO();
3258
3259         if (!playersao)
3260                 return false;
3261
3262         m_script->player_event(playersao, "hud_changed");
3263         return true;
3264 }
3265
3266 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3267 {
3268         if (!player)
3269                 return false;
3270
3271         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3272                 return false;
3273
3274         player->setHotbarItemcount(hotbar_itemcount);
3275         std::ostringstream os(std::ios::binary);
3276         writeS32(os, hotbar_itemcount);
3277         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3278         return true;
3279 }
3280
3281 void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
3282 {
3283         if (!player)
3284                 return;
3285
3286         player->setHotbarImage(name);
3287         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3288 }
3289
3290 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
3291 {
3292         if (!player)
3293                 return;
3294
3295         player->setHotbarSelectedImage(name);
3296         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3297 }
3298
3299 Address Server::getPeerAddress(session_t peer_id)
3300 {
3301         return m_con->GetPeerAddress(peer_id);
3302 }
3303
3304 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3305                 v2s32 animation_frames[4], f32 frame_speed)
3306 {
3307         sanity_check(player);
3308         player->setLocalAnimations(animation_frames, frame_speed);
3309         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3310 }
3311
3312 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3313 {
3314         sanity_check(player);
3315         player->eye_offset_first = first;
3316         player->eye_offset_third = third;
3317         SendEyeOffset(player->getPeerId(), first, third);
3318 }
3319
3320 void Server::setSky(RemotePlayer *player, const SkyboxParams &params)
3321 {
3322         sanity_check(player);
3323         player->setSky(params);
3324         SendSetSky(player->getPeerId(), params);
3325 }
3326
3327 void Server::setSun(RemotePlayer *player, const SunParams &params)
3328 {
3329         sanity_check(player);
3330         player->setSun(params);
3331         SendSetSun(player->getPeerId(), params);
3332 }
3333
3334 void Server::setMoon(RemotePlayer *player, const MoonParams &params)
3335 {
3336         sanity_check(player);
3337         player->setMoon(params);
3338         SendSetMoon(player->getPeerId(), params);
3339 }
3340
3341 void Server::setStars(RemotePlayer *player, const StarParams &params)
3342 {
3343         sanity_check(player);
3344         player->setStars(params);
3345         SendSetStars(player->getPeerId(), params);
3346 }
3347
3348 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3349 {
3350         sanity_check(player);
3351         player->setCloudParams(params);
3352         SendCloudParams(player->getPeerId(), params);
3353 }
3354
3355 void Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3356         float ratio)
3357 {
3358         sanity_check(player);
3359         player->overrideDayNightRatio(do_override, ratio);
3360         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3361 }
3362
3363 void Server::notifyPlayers(const std::wstring &msg)
3364 {
3365         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3366 }
3367
3368 void Server::spawnParticle(const std::string &playername, v3f pos,
3369         v3f velocity, v3f acceleration,
3370         float expirationtime, float size, bool
3371         collisiondetection, bool collision_removal, bool object_collision,
3372         bool vertical, const std::string &texture,
3373         const struct TileAnimationParams &animation, u8 glow)
3374 {
3375         // m_env will be NULL if the server is initializing
3376         if (!m_env)
3377                 return;
3378
3379         session_t peer_id = PEER_ID_INEXISTENT;
3380         u16 proto_ver = 0;
3381         if (!playername.empty()) {
3382                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3383                 if (!player)
3384                         return;
3385                 peer_id = player->getPeerId();
3386                 proto_ver = player->protocol_version;
3387         }
3388
3389         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3390                         expirationtime, size, collisiondetection, collision_removal,
3391                         object_collision, vertical, texture, animation, glow);
3392 }
3393
3394 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3395         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3396         float minexptime, float maxexptime, float minsize, float maxsize,
3397         bool collisiondetection, bool collision_removal, bool object_collision,
3398         ServerActiveObject *attached, bool vertical, const std::string &texture,
3399         const std::string &playername, const struct TileAnimationParams &animation,
3400         u8 glow)
3401 {
3402         // m_env will be NULL if the server is initializing
3403         if (!m_env)
3404                 return -1;
3405
3406         session_t peer_id = PEER_ID_INEXISTENT;
3407         u16 proto_ver = 0;
3408         if (!playername.empty()) {
3409                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3410                 if (!player)
3411                         return -1;
3412                 peer_id = player->getPeerId();
3413                 proto_ver = player->protocol_version;
3414         }
3415
3416         u16 attached_id = attached ? attached->getId() : 0;
3417
3418         u32 id;
3419         if (attached_id == 0)
3420                 id = m_env->addParticleSpawner(spawntime);
3421         else
3422                 id = m_env->addParticleSpawner(spawntime, attached_id);
3423
3424         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3425                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3426                 minexptime, maxexptime, minsize, maxsize, collisiondetection,
3427                 collision_removal, object_collision, attached_id, vertical,
3428                 texture, id, animation, glow);
3429
3430         return id;
3431 }
3432
3433 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3434 {
3435         // m_env will be NULL if the server is initializing
3436         if (!m_env)
3437                 throw ServerError("Can't delete particle spawners during initialisation!");
3438
3439         session_t peer_id = PEER_ID_INEXISTENT;
3440         if (!playername.empty()) {
3441                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3442                 if (!player)
3443                         return;
3444                 peer_id = player->getPeerId();
3445         }
3446
3447         m_env->deleteParticleSpawner(id);
3448         SendDeleteParticleSpawner(peer_id, id);
3449 }
3450
3451 // actions: time-reversed list
3452 // Return value: success/failure
3453 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3454                 std::list<std::string> *log)
3455 {
3456         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3457         ServerMap *map = (ServerMap*)(&m_env->getMap());
3458
3459         // Fail if no actions to handle
3460         if (actions.empty()) {
3461                 assert(log);
3462                 log->push_back("Nothing to do.");
3463                 return false;
3464         }
3465
3466         int num_tried = 0;
3467         int num_failed = 0;
3468
3469         for (const RollbackAction &action : actions) {
3470                 num_tried++;
3471                 bool success = action.applyRevert(map, m_inventory_mgr.get(), this);
3472                 if(!success){
3473                         num_failed++;
3474                         std::ostringstream os;
3475                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3476                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3477                         if (log)
3478                                 log->push_back(os.str());
3479                 }else{
3480                         std::ostringstream os;
3481                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3482                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3483                         if (log)
3484                                 log->push_back(os.str());
3485                 }
3486         }
3487
3488         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3489                         <<" failed"<<std::endl;
3490
3491         // Call it done if less than half failed
3492         return num_failed <= num_tried/2;
3493 }
3494
3495 // IGameDef interface
3496 // Under envlock
3497 IItemDefManager *Server::getItemDefManager()
3498 {
3499         return m_itemdef;
3500 }
3501
3502 const NodeDefManager *Server::getNodeDefManager()
3503 {
3504         return m_nodedef;
3505 }
3506
3507 ICraftDefManager *Server::getCraftDefManager()
3508 {
3509         return m_craftdef;
3510 }
3511
3512 u16 Server::allocateUnknownNodeId(const std::string &name)
3513 {
3514         return m_nodedef->allocateDummy(name);
3515 }
3516
3517 IWritableItemDefManager *Server::getWritableItemDefManager()
3518 {
3519         return m_itemdef;
3520 }
3521
3522 NodeDefManager *Server::getWritableNodeDefManager()
3523 {
3524         return m_nodedef;
3525 }
3526
3527 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3528 {
3529         return m_craftdef;
3530 }
3531
3532 const std::vector<ModSpec> & Server::getMods() const
3533 {
3534         return m_modmgr->getMods();
3535 }
3536
3537 const ModSpec *Server::getModSpec(const std::string &modname) const
3538 {
3539         return m_modmgr->getModSpec(modname);
3540 }
3541
3542 void Server::getModNames(std::vector<std::string> &modlist)
3543 {
3544         m_modmgr->getModNames(modlist);
3545 }
3546
3547 std::string Server::getBuiltinLuaPath()
3548 {
3549         return porting::path_share + DIR_DELIM + "builtin";
3550 }
3551
3552 std::string Server::getModStoragePath() const
3553 {
3554         return m_path_world + DIR_DELIM + "mod_storage";
3555 }
3556
3557 v3f Server::findSpawnPos()
3558 {
3559         ServerMap &map = m_env->getServerMap();
3560         v3f nodeposf;
3561         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
3562                 return nodeposf * BS;
3563
3564         bool is_good = false;
3565         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3566         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3567
3568         // Try to find a good place a few times
3569         for (s32 i = 0; i < 4000 && !is_good; i++) {
3570                 s32 range = MYMIN(1 + i, range_max);
3571                 // We're going to try to throw the player to this position
3572                 v2s16 nodepos2d = v2s16(
3573                         -range + (myrand() % (range * 2)),
3574                         -range + (myrand() % (range * 2)));
3575                 // Get spawn level at point
3576                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3577                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
3578                 // signify an unsuitable spawn position, or if outside limits.
3579                 if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
3580                                 spawn_level <= -MAX_MAP_GENERATION_LIMIT)
3581                         continue;
3582
3583                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3584                 // Consecutive empty nodes
3585                 s32 air_count = 0;
3586
3587                 // Search upwards from 'spawn level' for 2 consecutive empty nodes, to
3588                 // avoid obstructions in already-generated mapblocks.
3589                 // In ungenerated mapblocks consisting of 'ignore' nodes, there will be
3590                 // no obstructions, but mapgen decorations are generated after spawn so
3591                 // the player may end up inside one.
3592                 for (s32 i = 0; i < 8; i++) {
3593                         v3s16 blockpos = getNodeBlockPos(nodepos);
3594                         map.emergeBlock(blockpos, true);
3595                         content_t c = map.getNode(nodepos).getContent();
3596
3597                         // In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
3598                         // In ungenerated mapblocks allow spawn in 'ignore' nodes.
3599                         if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
3600                                 air_count++;
3601                                 if (air_count >= 2) {
3602                                         // Spawn in lower empty node
3603                                         nodepos.Y--;
3604                                         nodeposf = intToFloat(nodepos, BS);
3605                                         // Don't spawn the player outside map boundaries
3606                                         if (objectpos_over_limit(nodeposf))
3607                                                 // Exit this loop, positions above are probably over limit
3608                                                 break;
3609
3610                                         // Good position found, cause an exit from main loop
3611                                         is_good = true;
3612                                         break;
3613                                 }
3614                         } else {
3615                                 air_count = 0;
3616                         }
3617                         nodepos.Y++;
3618                 }
3619         }
3620
3621         if (is_good)
3622                 return nodeposf;
3623
3624         // No suitable spawn point found, return fallback 0,0,0
3625         return v3f(0.0f, 0.0f, 0.0f);
3626 }
3627
3628 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3629 {
3630         if (delay == 0.0f) {
3631         // No delay, shutdown immediately
3632                 m_shutdown_state.is_requested = true;
3633                 // only print to the infostream, a chat message saying
3634                 // "Server Shutting Down" is sent when the server destructs.
3635                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3636         } else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3637                 // Negative delay, cancel shutdown if requested
3638                 m_shutdown_state.reset();
3639                 std::wstringstream ws;
3640
3641                 ws << L"*** Server shutdown canceled.";
3642
3643                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3644                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3645                 // m_shutdown_* are already handled, skip.
3646                 return;
3647         } else if (delay > 0.0f) {
3648         // Positive delay, tell the clients when the server will shut down
3649                 std::wstringstream ws;
3650
3651                 ws << L"*** Server shutting down in "
3652                                 << duration_to_string(myround(delay)).c_str()
3653                                 << ".";
3654
3655                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3656                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3657         }
3658
3659         m_shutdown_state.trigger(delay, msg, reconnect);
3660 }
3661
3662 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3663 {
3664         /*
3665                 Try to get an existing player
3666         */
3667         RemotePlayer *player = m_env->getPlayer(name);
3668
3669         // If player is already connected, cancel
3670         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3671                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3672                 return NULL;
3673         }
3674
3675         /*
3676                 If player with the wanted peer_id already exists, cancel.
3677         */
3678         if (m_env->getPlayer(peer_id)) {
3679                 infostream<<"emergePlayer(): Player with wrong name but same"
3680                                 " peer_id already exists"<<std::endl;
3681                 return NULL;
3682         }
3683
3684         if (!player) {
3685                 player = new RemotePlayer(name, idef());
3686         }
3687
3688         bool newplayer = false;
3689
3690         // Load player
3691         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3692
3693         // Complete init with server parts
3694         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3695         player->protocol_version = proto_version;
3696
3697         /* Run scripts */
3698         if (newplayer) {
3699                 m_script->on_newplayer(playersao);
3700         }
3701
3702         return playersao;
3703 }
3704
3705 bool Server::registerModStorage(ModMetadata *storage)
3706 {
3707         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3708                 errorstream << "Unable to register same mod storage twice. Storage name: "
3709                                 << storage->getModName() << std::endl;
3710                 return false;
3711         }
3712
3713         m_mod_storages[storage->getModName()] = storage;
3714         return true;
3715 }
3716
3717 void Server::unregisterModStorage(const std::string &name)
3718 {
3719         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3720         if (it != m_mod_storages.end()) {
3721                 // Save unconditionaly on unregistration
3722                 it->second->save(getModStoragePath());
3723                 m_mod_storages.erase(name);
3724         }
3725 }
3726
3727 void dedicated_server_loop(Server &server, bool &kill)
3728 {
3729         verbosestream<<"dedicated_server_loop()"<<std::endl;
3730
3731         IntervalLimiter m_profiler_interval;
3732
3733         static thread_local const float steplen =
3734                         g_settings->getFloat("dedicated_server_step");
3735         static thread_local const float profiler_print_interval =
3736                         g_settings->getFloat("profiler_print_interval");
3737
3738         /*
3739          * The dedicated server loop only does time-keeping (in Server::step) and
3740          * provides a way to main.cpp to kill the server externally (bool &kill).
3741          */
3742
3743         for(;;) {
3744                 // This is kind of a hack but can be done like this
3745                 // because server.step() is very light
3746                 sleep_ms((int)(steplen*1000.0));
3747                 server.step(steplen);
3748
3749                 if (server.isShutdownRequested() || kill)
3750                         break;
3751
3752                 /*
3753                         Profiler
3754                 */
3755                 if (profiler_print_interval != 0) {
3756                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3757                         {
3758                                 infostream<<"Profiler:"<<std::endl;
3759                                 g_profiler->print(infostream);
3760                                 g_profiler->clear();
3761                         }
3762                 }
3763         }
3764
3765         infostream << "Dedicated server quitting" << std::endl;
3766 #if USE_CURL
3767         if (g_settings->getBool("server_announce"))
3768                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3769                         server.m_bind_addr.getPort());
3770 #endif
3771 }
3772
3773 /*
3774  * Mod channels
3775  */
3776
3777
3778 bool Server::joinModChannel(const std::string &channel)
3779 {
3780         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3781                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3782 }
3783
3784 bool Server::leaveModChannel(const std::string &channel)
3785 {
3786         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3787 }
3788
3789 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3790 {
3791         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3792                 return false;
3793
3794         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3795         return true;
3796 }
3797
3798 ModChannel* Server::getModChannel(const std::string &channel)
3799 {
3800         return m_modchannel_mgr->getModChannel(channel);
3801 }
3802
3803 void Server::broadcastModChannelMessage(const std::string &channel,
3804                 const std::string &message, session_t from_peer)
3805 {
3806         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3807         if (peers.empty())
3808                 return;
3809
3810         if (message.size() > STRING_MAX_LEN) {
3811                 warningstream << "ModChannel message too long, dropping before sending "
3812                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3813                                 << channel << ")" << std::endl;
3814                 return;
3815         }
3816
3817         std::string sender;
3818         if (from_peer != PEER_ID_SERVER) {
3819                 sender = getPlayerName(from_peer);
3820         }
3821
3822         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3823                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3824         resp_pkt << channel << sender << message;
3825         for (session_t peer_id : peers) {
3826                 // Ignore sender
3827                 if (peer_id == from_peer)
3828                         continue;
3829
3830                 Send(peer_id, &resp_pkt);
3831         }
3832
3833         if (from_peer != PEER_ID_SERVER) {
3834                 m_script->on_modchannel_message(channel, sender, message);
3835         }
3836 }
3837
3838 void Server::loadTranslationLanguage(const std::string &lang_code)
3839 {
3840         if (g_server_translations->count(lang_code))
3841                 return; // Already loaded
3842
3843         std::string suffix = "." + lang_code + ".tr";
3844         for (const auto &i : m_media) {
3845                 if (str_ends_with(i.first, suffix)) {
3846                         std::ifstream t(i.second.path);
3847                         std::string data((std::istreambuf_iterator<char>(t)),
3848                         std::istreambuf_iterator<char>());
3849
3850                         (*g_server_translations)[lang_code].loadTranslation(data);
3851                 }
3852         }
3853 }