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