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