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