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