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