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