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