Add support for per-player FOV overrides and multipliers
[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::SendPlayerFov(session_t peer_id)
1769 {
1770         NetworkPacket pkt(TOCLIENT_FOV, 4 + 1, peer_id);
1771
1772         PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov();
1773         pkt << fov_spec.fov << fov_spec.is_multiplier;
1774
1775         Send(&pkt);
1776 }
1777
1778 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1779                 f32 animation_speed)
1780 {
1781         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1782                 peer_id);
1783
1784         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1785                         << animation_frames[3] << animation_speed;
1786
1787         Send(&pkt);
1788 }
1789
1790 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1791 {
1792         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1793         pkt << first << third;
1794         Send(&pkt);
1795 }
1796
1797 void Server::SendPlayerPrivileges(session_t peer_id)
1798 {
1799         RemotePlayer *player = m_env->getPlayer(peer_id);
1800         assert(player);
1801         if(player->getPeerId() == PEER_ID_INEXISTENT)
1802                 return;
1803
1804         std::set<std::string> privs;
1805         m_script->getAuth(player->getName(), NULL, &privs);
1806
1807         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1808         pkt << (u16) privs.size();
1809
1810         for (const std::string &priv : privs) {
1811                 pkt << priv;
1812         }
1813
1814         Send(&pkt);
1815 }
1816
1817 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1818 {
1819         RemotePlayer *player = m_env->getPlayer(peer_id);
1820         assert(player);
1821         if (player->getPeerId() == PEER_ID_INEXISTENT)
1822                 return;
1823
1824         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1825         pkt.putLongString(player->inventory_formspec);
1826
1827         Send(&pkt);
1828 }
1829
1830 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1831 {
1832         RemotePlayer *player = m_env->getPlayer(peer_id);
1833         assert(player);
1834         if (player->getPeerId() == PEER_ID_INEXISTENT)
1835                 return;
1836
1837         NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1838         pkt << player->formspec_prepend;
1839         Send(&pkt);
1840 }
1841
1842 void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
1843 {
1844         // Radius inside which objects are active
1845         static thread_local const s16 radius =
1846                 g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
1847
1848         // Radius inside which players are active
1849         static thread_local const bool is_transfer_limited =
1850                 g_settings->exists("unlimited_player_transfer_distance") &&
1851                 !g_settings->getBool("unlimited_player_transfer_distance");
1852
1853         static thread_local const s16 player_transfer_dist =
1854                 g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
1855
1856         s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
1857                 radius : player_transfer_dist;
1858
1859         s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
1860         if (my_radius <= 0)
1861                 my_radius = radius;
1862
1863         std::queue<u16> removed_objects, added_objects;
1864         m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
1865                 client->m_known_objects, removed_objects);
1866         m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
1867                 client->m_known_objects, added_objects);
1868
1869         int removed_count = removed_objects.size();
1870         int added_count   = added_objects.size();
1871
1872         if (removed_objects.empty() && added_objects.empty())
1873                 return;
1874
1875         char buf[4];
1876         std::string data;
1877
1878         // Handle removed objects
1879         writeU16((u8*)buf, removed_objects.size());
1880         data.append(buf, 2);
1881         while (!removed_objects.empty()) {
1882                 // Get object
1883                 u16 id = removed_objects.front();
1884                 ServerActiveObject* obj = m_env->getActiveObject(id);
1885
1886                 // Add to data buffer for sending
1887                 writeU16((u8*)buf, id);
1888                 data.append(buf, 2);
1889
1890                 // Remove from known objects
1891                 client->m_known_objects.erase(id);
1892
1893                 if (obj && obj->m_known_by_count > 0)
1894                         obj->m_known_by_count--;
1895
1896                 removed_objects.pop();
1897         }
1898
1899         // Handle added objects
1900         writeU16((u8*)buf, added_objects.size());
1901         data.append(buf, 2);
1902         while (!added_objects.empty()) {
1903                 // Get object
1904                 u16 id = added_objects.front();
1905                 ServerActiveObject* obj = m_env->getActiveObject(id);
1906
1907                 // Get object type
1908                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
1909                 if (!obj)
1910                         warningstream << FUNCTION_NAME << ": NULL object" << std::endl;
1911                 else
1912                         type = obj->getSendType();
1913
1914                 // Add to data buffer for sending
1915                 writeU16((u8*)buf, id);
1916                 data.append(buf, 2);
1917                 writeU8((u8*)buf, type);
1918                 data.append(buf, 1);
1919
1920                 if (obj)
1921                         data.append(serializeLongString(
1922                                 obj->getClientInitializationData(client->net_proto_version)));
1923                 else
1924                         data.append(serializeLongString(""));
1925
1926                 // Add to known objects
1927                 client->m_known_objects.insert(id);
1928
1929                 if (obj)
1930                         obj->m_known_by_count++;
1931
1932                 added_objects.pop();
1933         }
1934
1935         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, data.size(), client->peer_id);
1936         pkt.putRawString(data.c_str(), data.size());
1937         Send(&pkt);
1938
1939         verbosestream << "Server::SendActiveObjectRemoveAdd: "
1940                 << removed_count << " removed, " << added_count << " added, "
1941                 << "packet size is " << pkt.getSize() << std::endl;
1942 }
1943
1944 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
1945                 bool reliable)
1946 {
1947         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1948                         datas.size(), peer_id);
1949
1950         pkt.putRawString(datas.c_str(), datas.size());
1951
1952         m_clients.send(pkt.getPeerId(),
1953                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1954                         &pkt, reliable);
1955 }
1956
1957 void Server::SendCSMRestrictionFlags(session_t peer_id)
1958 {
1959         NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
1960                 sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
1961         pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
1962         Send(&pkt);
1963 }
1964
1965 void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
1966 {
1967         NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
1968         pkt << added_vel;
1969         Send(&pkt);
1970 }
1971
1972 s32 Server::playSound(const SimpleSoundSpec &spec,
1973                 const ServerSoundParams &params)
1974 {
1975         // Find out initial position of sound
1976         bool pos_exists = false;
1977         v3f pos = params.getPos(m_env, &pos_exists);
1978         // If position is not found while it should be, cancel sound
1979         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1980                 return -1;
1981
1982         // Filter destination clients
1983         std::vector<session_t> dst_clients;
1984         if(!params.to_player.empty()) {
1985                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
1986                 if(!player){
1987                         infostream<<"Server::playSound: Player \""<<params.to_player
1988                                         <<"\" not found"<<std::endl;
1989                         return -1;
1990                 }
1991                 if (player->getPeerId() == PEER_ID_INEXISTENT) {
1992                         infostream<<"Server::playSound: Player \""<<params.to_player
1993                                         <<"\" not connected"<<std::endl;
1994                         return -1;
1995                 }
1996                 dst_clients.push_back(player->getPeerId());
1997         } else {
1998                 std::vector<session_t> clients = m_clients.getClientIDs();
1999
2000                 for (const session_t client_id : clients) {
2001                         RemotePlayer *player = m_env->getPlayer(client_id);
2002                         if (!player)
2003                                 continue;
2004
2005                         PlayerSAO *sao = player->getPlayerSAO();
2006                         if (!sao)
2007                                 continue;
2008
2009                         if (pos_exists) {
2010                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2011                                                 params.max_hear_distance)
2012                                         continue;
2013                         }
2014                         dst_clients.push_back(client_id);
2015                 }
2016         }
2017
2018         if(dst_clients.empty())
2019                 return -1;
2020
2021         // Create the sound
2022         s32 id = m_next_sound_id++;
2023         // The sound will exist as a reference in m_playing_sounds
2024         m_playing_sounds[id] = ServerPlayingSound();
2025         ServerPlayingSound &psound = m_playing_sounds[id];
2026         psound.params = params;
2027         psound.spec = spec;
2028
2029         float gain = params.gain * spec.gain;
2030         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2031         pkt << id << spec.name << gain
2032                         << (u8) params.type << pos << params.object
2033                         << params.loop << params.fade << params.pitch;
2034
2035         // Backwards compability
2036         bool play_sound = gain > 0;
2037
2038         for (const u16 dst_client : dst_clients) {
2039                 if (play_sound || m_clients.getProtocolVersion(dst_client) >= 32) {
2040                         psound.clients.insert(dst_client);
2041                         m_clients.send(dst_client, 0, &pkt, true);
2042                 }
2043         }
2044         return id;
2045 }
2046 void Server::stopSound(s32 handle)
2047 {
2048         // Get sound reference
2049         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2050                 m_playing_sounds.find(handle);
2051         if (i == m_playing_sounds.end())
2052                 return;
2053         ServerPlayingSound &psound = i->second;
2054
2055         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2056         pkt << handle;
2057
2058         for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2059                         si != psound.clients.end(); ++si) {
2060                 // Send as reliable
2061                 m_clients.send(*si, 0, &pkt, true);
2062         }
2063         // Remove sound reference
2064         m_playing_sounds.erase(i);
2065 }
2066
2067 void Server::fadeSound(s32 handle, float step, float gain)
2068 {
2069         // Get sound reference
2070         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2071                 m_playing_sounds.find(handle);
2072         if (i == m_playing_sounds.end())
2073                 return;
2074
2075         ServerPlayingSound &psound = i->second;
2076         psound.params.gain = gain;
2077
2078         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2079         pkt << handle << step << gain;
2080
2081         // Backwards compability
2082         bool play_sound = gain > 0;
2083         ServerPlayingSound compat_psound = psound;
2084         compat_psound.clients.clear();
2085
2086         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2087         compat_pkt << handle;
2088
2089         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2090                         it != psound.clients.end();) {
2091                 if (m_clients.getProtocolVersion(*it) >= 32) {
2092                         // Send as reliable
2093                         m_clients.send(*it, 0, &pkt, true);
2094                         ++it;
2095                 } else {
2096                         compat_psound.clients.insert(*it);
2097                         // Stop old sound
2098                         m_clients.send(*it, 0, &compat_pkt, true);
2099                         psound.clients.erase(it++);
2100                 }
2101         }
2102
2103         // Remove sound reference
2104         if (!play_sound || psound.clients.empty())
2105                 m_playing_sounds.erase(i);
2106
2107         if (play_sound && !compat_psound.clients.empty()) {
2108                 // Play new sound volume on older clients
2109                 playSound(compat_psound.spec, compat_psound.params);
2110         }
2111 }
2112
2113 void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
2114                 float far_d_nodes)
2115 {
2116         float maxd = far_d_nodes * BS;
2117         v3f p_f = intToFloat(p, BS);
2118         v3s16 block_pos = getNodeBlockPos(p);
2119
2120         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2121         pkt << p;
2122
2123         std::vector<session_t> clients = m_clients.getClientIDs();
2124         m_clients.lock();
2125
2126         for (session_t client_id : clients) {
2127                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2128                 if (!client)
2129                         continue;
2130
2131                 RemotePlayer *player = m_env->getPlayer(client_id);
2132                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2133
2134                 // If player is far away, only set modified blocks not sent
2135                 if (!client->isBlockSent(block_pos) || (sao &&
2136                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2137                         if (far_players)
2138                                 far_players->emplace(client_id);
2139                         else
2140                                 client->SetBlockNotSent(block_pos);
2141                         continue;
2142                 }
2143
2144                 // Send as reliable
2145                 m_clients.send(client_id, 0, &pkt, true);
2146         }
2147
2148         m_clients.unlock();
2149 }
2150
2151 void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
2152                 float far_d_nodes, bool remove_metadata)
2153 {
2154         float maxd = far_d_nodes * BS;
2155         v3f p_f = intToFloat(p, BS);
2156         v3s16 block_pos = getNodeBlockPos(p);
2157
2158         NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2159         pkt << p << n.param0 << n.param1 << n.param2
2160                         << (u8) (remove_metadata ? 0 : 1);
2161
2162         std::vector<session_t> clients = m_clients.getClientIDs();
2163         m_clients.lock();
2164
2165         for (session_t client_id : clients) {
2166                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2167                 if (!client)
2168                         continue;
2169
2170                 RemotePlayer *player = m_env->getPlayer(client_id);
2171                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2172
2173                 // If player is far away, only set modified blocks not sent
2174                 if (!client->isBlockSent(block_pos) || (sao &&
2175                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2176                         if (far_players)
2177                                 far_players->emplace(client_id);
2178                         else
2179                                 client->SetBlockNotSent(block_pos);
2180                         continue;
2181                 }
2182
2183                 // Send as reliable
2184                 m_clients.send(client_id, 0, &pkt, true);
2185         }
2186
2187         m_clients.unlock();
2188 }
2189
2190 void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes)
2191 {
2192         float maxd = far_d_nodes * BS;
2193         NodeMetadataList meta_updates_list(false);
2194         std::vector<session_t> clients = m_clients.getClientIDs();
2195
2196         m_clients.lock();
2197
2198         for (session_t i : clients) {
2199                 RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2200                 if (!client)
2201                         continue;
2202
2203                 ServerActiveObject *player = m_env->getActiveObject(i);
2204                 v3f player_pos = player ? player->getBasePosition() : v3f();
2205
2206                 for (const v3s16 &pos : meta_updates) {
2207                         NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
2208
2209                         if (!meta)
2210                                 continue;
2211
2212                         v3s16 block_pos = getNodeBlockPos(pos);
2213                         if (!client->isBlockSent(block_pos) || (player &&
2214                                         player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) {
2215                                 client->SetBlockNotSent(block_pos);
2216                                 continue;
2217                         }
2218
2219                         // Add the change to send list
2220                         meta_updates_list.set(pos, meta);
2221                 }
2222                 if (meta_updates_list.size() == 0)
2223                         continue;
2224
2225                 // Send the meta changes
2226                 std::ostringstream os(std::ios::binary);
2227                 meta_updates_list.serialize(os, client->net_proto_version, false, true);
2228                 std::ostringstream oss(std::ios::binary);
2229                 compressZlib(os.str(), oss);
2230
2231                 NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0);
2232                 pkt.putLongString(oss.str());
2233                 m_clients.send(i, 0, &pkt, true);
2234
2235                 meta_updates_list.clear();
2236         }
2237
2238         m_clients.unlock();
2239 }
2240
2241 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2242                 u16 net_proto_version)
2243 {
2244         /*
2245                 Create a packet with the block in the right format
2246         */
2247
2248         std::ostringstream os(std::ios_base::binary);
2249         block->serialize(os, ver, false);
2250         block->serializeNetworkSpecific(os);
2251         std::string s = os.str();
2252
2253         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2254
2255         pkt << block->getPos();
2256         pkt.putRawString(s.c_str(), s.size());
2257         Send(&pkt);
2258 }
2259
2260 void Server::SendBlocks(float dtime)
2261 {
2262         MutexAutoLock envlock(m_env_mutex);
2263         //TODO check if one big lock could be faster then multiple small ones
2264
2265         std::vector<PrioritySortedBlockTransfer> queue;
2266
2267         u32 total_sending = 0;
2268
2269         {
2270                 ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
2271
2272                 std::vector<session_t> clients = m_clients.getClientIDs();
2273
2274                 m_clients.lock();
2275                 for (const session_t client_id : clients) {
2276                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2277
2278                         if (!client)
2279                                 continue;
2280
2281                         total_sending += client->getSendingCount();
2282                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2283                 }
2284                 m_clients.unlock();
2285         }
2286
2287         // Sort.
2288         // Lowest priority number comes first.
2289         // Lowest is most important.
2290         std::sort(queue.begin(), queue.end());
2291
2292         m_clients.lock();
2293
2294         // Maximal total count calculation
2295         // The per-client block sends is halved with the maximal online users
2296         u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2297                 g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2298
2299         ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
2300         Map &map = m_env->getMap();
2301
2302         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2303                 if (total_sending >= max_blocks_to_send)
2304                         break;
2305
2306                 MapBlock *block = map.getBlockNoCreateNoEx(block_to_send.pos);
2307                 if (!block)
2308                         continue;
2309
2310                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2311                                 CS_Active);
2312                 if (!client)
2313                         continue;
2314
2315                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2316                                 client->net_proto_version);
2317
2318                 client->SentBlock(block_to_send.pos);
2319                 total_sending++;
2320         }
2321         m_clients.unlock();
2322 }
2323
2324 bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos)
2325 {
2326         MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2327         if (!block)
2328                 return false;
2329
2330         m_clients.lock();
2331         RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active);
2332         if (!client || client->isBlockSent(blockpos)) {
2333                 m_clients.unlock();
2334                 return false;
2335         }
2336         SendBlockNoLock(peer_id, block, client->serialization_version,
2337                         client->net_proto_version);
2338         m_clients.unlock();
2339
2340         return true;
2341 }
2342
2343 void Server::fillMediaCache()
2344 {
2345         infostream<<"Server: Calculating media file checksums"<<std::endl;
2346
2347         // Collect all media file paths
2348         std::vector<std::string> paths;
2349         m_modmgr->getModsMediaPaths(paths);
2350         fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2351         fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2352
2353         // Collect media file information from paths into cache
2354         for (const std::string &mediapath : paths) {
2355                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2356                 for (const fs::DirListNode &dln : dirlist) {
2357                         if (dln.dir) // Ignode dirs
2358                                 continue;
2359                         std::string filename = dln.name;
2360                         // If name contains illegal characters, ignore the file
2361                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2362                                 infostream<<"Server: ignoring illegal file name: \""
2363                                                 << filename << "\"" << std::endl;
2364                                 continue;
2365                         }
2366                         // If name is not in a supported format, ignore it
2367                         const char *supported_ext[] = {
2368                                 ".png", ".jpg", ".bmp", ".tga",
2369                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2370                                 ".ogg",
2371                                 ".x", ".b3d", ".md2", ".obj",
2372                                 // Custom translation file format
2373                                 ".tr",
2374                                 NULL
2375                         };
2376                         if (removeStringEnd(filename, supported_ext).empty()){
2377                                 infostream << "Server: ignoring unsupported file extension: \""
2378                                                 << filename << "\"" << std::endl;
2379                                 continue;
2380                         }
2381                         // Ok, attempt to load the file and add to cache
2382                         std::string filepath;
2383                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2384
2385                         // Read data
2386                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2387                         if (!fis.good()) {
2388                                 errorstream << "Server::fillMediaCache(): Could not open \""
2389                                                 << filename << "\" for reading" << std::endl;
2390                                 continue;
2391                         }
2392                         std::ostringstream tmp_os(std::ios_base::binary);
2393                         bool bad = false;
2394                         for(;;) {
2395                                 char buf[1024];
2396                                 fis.read(buf, 1024);
2397                                 std::streamsize len = fis.gcount();
2398                                 tmp_os.write(buf, len);
2399                                 if (fis.eof())
2400                                         break;
2401                                 if (!fis.good()) {
2402                                         bad = true;
2403                                         break;
2404                                 }
2405                         }
2406                         if(bad) {
2407                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2408                                                 << filename << "\"" << std::endl;
2409                                 continue;
2410                         }
2411                         if(tmp_os.str().length() == 0) {
2412                                 errorstream << "Server::fillMediaCache(): Empty file \""
2413                                                 << filepath << "\"" << std::endl;
2414                                 continue;
2415                         }
2416
2417                         SHA1 sha1;
2418                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2419
2420                         unsigned char *digest = sha1.getDigest();
2421                         std::string sha1_base64 = base64_encode(digest, 20);
2422                         std::string sha1_hex = hex_encode((char*)digest, 20);
2423                         free(digest);
2424
2425                         // Put in list
2426                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2427                         verbosestream << "Server: " << sha1_hex << " is " << filename
2428                                         << std::endl;
2429                 }
2430         }
2431 }
2432
2433 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2434 {
2435         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2436                 << std::endl;
2437
2438         // Make packet
2439         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2440
2441         u16 media_sent = 0;
2442         std::string lang_suffix;
2443         lang_suffix.append(".").append(lang_code).append(".tr");
2444         for (const auto &i : m_media) {
2445                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2446                         continue;
2447                 media_sent++;
2448         }
2449
2450         pkt << media_sent;
2451
2452         for (const auto &i : m_media) {
2453                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2454                         continue;
2455                 pkt << i.first << i.second.sha1_digest;
2456         }
2457
2458         pkt << g_settings->get("remote_media");
2459         Send(&pkt);
2460 }
2461
2462 struct SendableMedia
2463 {
2464         std::string name;
2465         std::string path;
2466         std::string data;
2467
2468         SendableMedia(const std::string &name_="", const std::string &path_="",
2469                       const std::string &data_=""):
2470                 name(name_),
2471                 path(path_),
2472                 data(data_)
2473         {}
2474 };
2475
2476 void Server::sendRequestedMedia(session_t peer_id,
2477                 const std::vector<std::string> &tosend)
2478 {
2479         verbosestream<<"Server::sendRequestedMedia(): "
2480                         <<"Sending files to client"<<std::endl;
2481
2482         /* Read files */
2483
2484         // Put 5kB in one bunch (this is not accurate)
2485         u32 bytes_per_bunch = 5000;
2486
2487         std::vector< std::vector<SendableMedia> > file_bunches;
2488         file_bunches.emplace_back();
2489
2490         u32 file_size_bunch_total = 0;
2491
2492         for (const std::string &name : tosend) {
2493                 if (m_media.find(name) == m_media.end()) {
2494                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2495                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2496                         continue;
2497                 }
2498
2499                 //TODO get path + name
2500                 std::string tpath = m_media[name].path;
2501
2502                 // Read data
2503                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2504                 if(!fis.good()){
2505                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2506                                         <<tpath<<"\" for reading"<<std::endl;
2507                         continue;
2508                 }
2509                 std::ostringstream tmp_os(std::ios_base::binary);
2510                 bool bad = false;
2511                 for(;;) {
2512                         char buf[1024];
2513                         fis.read(buf, 1024);
2514                         std::streamsize len = fis.gcount();
2515                         tmp_os.write(buf, len);
2516                         file_size_bunch_total += len;
2517                         if(fis.eof())
2518                                 break;
2519                         if(!fis.good()) {
2520                                 bad = true;
2521                                 break;
2522                         }
2523                 }
2524                 if (bad) {
2525                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2526                                         <<name<<"\""<<std::endl;
2527                         continue;
2528                 }
2529                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2530                                 <<tname<<"\""<<std::endl;*/
2531                 // Put in list
2532                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2533
2534                 // Start next bunch if got enough data
2535                 if(file_size_bunch_total >= bytes_per_bunch) {
2536                         file_bunches.emplace_back();
2537                         file_size_bunch_total = 0;
2538                 }
2539
2540         }
2541
2542         /* Create and send packets */
2543
2544         u16 num_bunches = file_bunches.size();
2545         for (u16 i = 0; i < num_bunches; i++) {
2546                 /*
2547                         u16 command
2548                         u16 total number of texture bunches
2549                         u16 index of this bunch
2550                         u32 number of files in this bunch
2551                         for each file {
2552                                 u16 length of name
2553                                 string name
2554                                 u32 length of data
2555                                 data
2556                         }
2557                 */
2558
2559                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2560                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2561
2562                 for (const SendableMedia &j : file_bunches[i]) {
2563                         pkt << j.name;
2564                         pkt.putLongString(j.data);
2565                 }
2566
2567                 verbosestream << "Server::sendRequestedMedia(): bunch "
2568                                 << i << "/" << num_bunches
2569                                 << " files=" << file_bunches[i].size()
2570                                 << " size="  << pkt.getSize() << std::endl;
2571                 Send(&pkt);
2572         }
2573 }
2574
2575 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
2576 {
2577         const auto &inv_it = m_detached_inventories.find(name);
2578         const auto &player_it = m_detached_inventories_player.find(name);
2579
2580         if (player_it == m_detached_inventories_player.end() ||
2581                         player_it->second.empty()) {
2582                 // OK. Send to everyone
2583         } else {
2584                 if (!m_env)
2585                         return; // Mods are not done loading
2586
2587                 RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
2588                 if (!p)
2589                         return; // Player is offline
2590
2591                 if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
2592                         return; // Caller requested send to a different player, so don't send.
2593
2594                 peer_id = p->getPeerId();
2595         }
2596
2597         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2598         pkt << name;
2599
2600         if (inv_it == m_detached_inventories.end()) {
2601                 pkt << false; // Remove inventory
2602         } else {
2603                 pkt << true; // Update inventory
2604
2605                 // Serialization & NetworkPacket isn't a love story
2606                 std::ostringstream os(std::ios_base::binary);
2607                 inv_it->second->serialize(os);
2608                 inv_it->second->setModified(false);
2609
2610                 const std::string &os_str = os.str();
2611                 pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
2612                 pkt.putRawString(os_str);
2613         }
2614
2615         if (peer_id == PEER_ID_INEXISTENT)
2616                 m_clients.sendToAll(&pkt);
2617         else
2618                 Send(&pkt);
2619 }
2620
2621 void Server::sendDetachedInventories(session_t peer_id, bool incremental)
2622 {
2623         for (const auto &detached_inventory : m_detached_inventories) {
2624                 const std::string &name = detached_inventory.first;
2625                 if (incremental) {
2626                         Inventory *inv = detached_inventory.second;
2627                         if (!inv || !inv->checkModified())
2628                                 continue;
2629                 }
2630
2631                 sendDetachedInventory(name, peer_id);
2632         }
2633 }
2634
2635 /*
2636         Something random
2637 */
2638
2639 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2640 {
2641         PlayerSAO *playersao = getPlayerSAO(peer_id);
2642         // In some rare cases this can be NULL -- if the player is disconnected
2643         // when a Lua function modifies l_punch, for example
2644         if (!playersao)
2645                 return;
2646
2647         infostream << "Server::DiePlayer(): Player "
2648                         << playersao->getPlayer()->getName()
2649                         << " dies" << std::endl;
2650
2651         playersao->setHP(0, reason);
2652         playersao->clearParentAttachment();
2653
2654         // Trigger scripted stuff
2655         m_script->on_dieplayer(playersao, reason);
2656
2657         SendPlayerHP(peer_id);
2658         SendDeathscreen(peer_id, false, v3f(0,0,0));
2659 }
2660
2661 void Server::RespawnPlayer(session_t peer_id)
2662 {
2663         PlayerSAO *playersao = getPlayerSAO(peer_id);
2664         assert(playersao);
2665
2666         infostream << "Server::RespawnPlayer(): Player "
2667                         << playersao->getPlayer()->getName()
2668                         << " respawns" << std::endl;
2669
2670         playersao->setHP(playersao->accessObjectProperties()->hp_max,
2671                         PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2672         playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2673
2674         bool repositioned = m_script->on_respawnplayer(playersao);
2675         if (!repositioned) {
2676                 // setPos will send the new position to client
2677                 playersao->setPos(findSpawnPos());
2678         }
2679
2680         SendPlayerHP(peer_id);
2681 }
2682
2683
2684 void Server::DenySudoAccess(session_t peer_id)
2685 {
2686         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2687         Send(&pkt);
2688 }
2689
2690
2691 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2692                 const std::string &str_reason, bool reconnect)
2693 {
2694         SendAccessDenied(peer_id, reason, str_reason, reconnect);
2695
2696         m_clients.event(peer_id, CSE_SetDenied);
2697         DisconnectPeer(peer_id);
2698 }
2699
2700
2701 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2702                 const std::string &custom_reason)
2703 {
2704         SendAccessDenied(peer_id, reason, custom_reason);
2705         m_clients.event(peer_id, CSE_SetDenied);
2706         DisconnectPeer(peer_id);
2707 }
2708
2709 // 13/03/15: remove this function when protocol version 25 will become
2710 // the minimum version for MT users, maybe in 1 year
2711 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2712 {
2713         SendAccessDenied_Legacy(peer_id, reason);
2714         m_clients.event(peer_id, CSE_SetDenied);
2715         DisconnectPeer(peer_id);
2716 }
2717
2718 void Server::DisconnectPeer(session_t peer_id)
2719 {
2720         m_modchannel_mgr->leaveAllChannels(peer_id);
2721         m_con->DisconnectPeer(peer_id);
2722 }
2723
2724 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2725 {
2726         if (!forSudoMode) {
2727                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2728
2729                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2730
2731                 // Right now, the auth mechs don't change between login and sudo mode.
2732                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2733                 client->allowed_sudo_mechs = sudo_auth_mechs;
2734
2735                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2736                                 << g_settings->getFloat("dedicated_server_step")
2737                                 << sudo_auth_mechs;
2738
2739                 Send(&resp_pkt);
2740                 m_clients.event(peer_id, CSE_AuthAccept);
2741         } else {
2742                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2743
2744                 // We only support SRP right now
2745                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2746
2747                 resp_pkt << sudo_auth_mechs;
2748                 Send(&resp_pkt);
2749                 m_clients.event(peer_id, CSE_SudoSuccess);
2750         }
2751 }
2752
2753 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2754 {
2755         std::wstring message;
2756         {
2757                 /*
2758                         Clear references to playing sounds
2759                 */
2760                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2761                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2762                         ServerPlayingSound &psound = i->second;
2763                         psound.clients.erase(peer_id);
2764                         if (psound.clients.empty())
2765                                 m_playing_sounds.erase(i++);
2766                         else
2767                                 ++i;
2768                 }
2769
2770                 // clear formspec info so the next client can't abuse the current state
2771                 m_formspec_state_data.erase(peer_id);
2772
2773                 RemotePlayer *player = m_env->getPlayer(peer_id);
2774
2775                 /* Run scripts and remove from environment */
2776                 if (player) {
2777                         PlayerSAO *playersao = player->getPlayerSAO();
2778                         assert(playersao);
2779
2780                         playersao->clearChildAttachments();
2781                         playersao->clearParentAttachment();
2782
2783                         // inform connected clients
2784                         const std::string &player_name = player->getName();
2785                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2786                         // (u16) 1 + std::string represents a vector serialization representation
2787                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
2788                         m_clients.sendToAll(&notice);
2789                         // run scripts
2790                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2791
2792                         playersao->disconnected();
2793                 }
2794
2795                 /*
2796                         Print out action
2797                 */
2798                 {
2799                         if (player && reason != CDR_DENY) {
2800                                 std::ostringstream os(std::ios_base::binary);
2801                                 std::vector<session_t> clients = m_clients.getClientIDs();
2802
2803                                 for (const session_t client_id : clients) {
2804                                         // Get player
2805                                         RemotePlayer *player = m_env->getPlayer(client_id);
2806                                         if (!player)
2807                                                 continue;
2808
2809                                         // Get name of player
2810                                         os << player->getName() << " ";
2811                                 }
2812
2813                                 std::string name = player->getName();
2814                                 actionstream << name << " "
2815                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2816                                                 << " List of players: " << os.str() << std::endl;
2817                                 if (m_admin_chat)
2818                                         m_admin_chat->outgoing_queue.push_back(
2819                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2820                         }
2821                 }
2822                 {
2823                         MutexAutoLock env_lock(m_env_mutex);
2824                         m_clients.DeleteClient(peer_id);
2825                 }
2826         }
2827
2828         // Send leave chat message to all remaining clients
2829         if (!message.empty()) {
2830                 SendChatMessage(PEER_ID_INEXISTENT,
2831                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2832         }
2833 }
2834
2835 void Server::UpdateCrafting(RemotePlayer *player)
2836 {
2837         InventoryList *clist = player->inventory.getList("craft");
2838         if (!clist || clist->getSize() == 0)
2839                 return;
2840
2841         if (!clist->checkModified()) {
2842                 verbosestream << "Skip Server::UpdateCrafting(): list unmodified" << std::endl;
2843                 return;
2844         }
2845
2846         // Get a preview for crafting
2847         ItemStack preview;
2848         InventoryLocation loc;
2849         loc.setPlayer(player->getName());
2850         std::vector<ItemStack> output_replacements;
2851         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2852         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2853                         clist, loc);
2854
2855         InventoryList *plist = player->inventory.getList("craftpreview");
2856         if (plist && plist->getSize() >= 1) {
2857                 // Put the new preview in
2858                 plist->changeItem(0, preview);
2859         }
2860 }
2861
2862 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2863 {
2864         if (evt->type == CET_NICK_ADD) {
2865                 // The terminal informed us of its nick choice
2866                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2867                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2868                         errorstream << "You haven't set up an account." << std::endl
2869                                 << "Please log in using the client as '"
2870                                 << m_admin_nick << "' with a secure password." << std::endl
2871                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2872                                 << "and everybody can claim the user account instead of you," << std::endl
2873                                 << "giving them full control over this server." << std::endl;
2874                 }
2875         } else {
2876                 assert(evt->type == CET_CHAT);
2877                 handleAdminChat((ChatEventChat *)evt);
2878         }
2879 }
2880
2881 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2882         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2883 {
2884         // If something goes wrong, this player is to blame
2885         RollbackScopeActor rollback_scope(m_rollback,
2886                         std::string("player:") + name);
2887
2888         if (g_settings->getBool("strip_color_codes"))
2889                 wmessage = unescape_enriched(wmessage);
2890
2891         if (player) {
2892                 switch (player->canSendChatMessage()) {
2893                 case RPLAYER_CHATRESULT_FLOODING: {
2894                         std::wstringstream ws;
2895                         ws << L"You cannot send more messages. You are limited to "
2896                                         << g_settings->getFloat("chat_message_limit_per_10sec")
2897                                         << L" messages per 10 seconds.";
2898                         return ws.str();
2899                 }
2900                 case RPLAYER_CHATRESULT_KICK:
2901                         DenyAccess_Legacy(player->getPeerId(),
2902                                         L"You have been kicked due to message flooding.");
2903                         return L"";
2904                 case RPLAYER_CHATRESULT_OK:
2905                         break;
2906                 default:
2907                         FATAL_ERROR("Unhandled chat filtering result found.");
2908                 }
2909         }
2910
2911         if (m_max_chatmessage_length > 0
2912                         && wmessage.length() > m_max_chatmessage_length) {
2913                 return L"Your message exceed the maximum chat message limit set on the server. "
2914                                 L"It was refused. Send a shorter message";
2915         }
2916
2917         auto message = trim(wide_to_utf8(wmessage));
2918         if (message.find_first_of("\n\r") != std::wstring::npos) {
2919                 return L"New lines are not permitted in chat messages";
2920         }
2921
2922         // Run script hook, exit if script ate the chat message
2923         if (m_script->on_chat_message(name, message))
2924                 return L"";
2925
2926         // Line to send
2927         std::wstring line;
2928         // Whether to send line to the player that sent the message, or to all players
2929         bool broadcast_line = true;
2930
2931         if (check_shout_priv && !checkPriv(name, "shout")) {
2932                 line += L"-!- You don't have permission to shout.";
2933                 broadcast_line = false;
2934         } else {
2935                 line += narrow_to_wide(m_script->formatChatMessage(name,
2936                                 wide_to_narrow(wmessage)));
2937         }
2938
2939         /*
2940                 Tell calling method to send the message to sender
2941         */
2942         if (!broadcast_line)
2943                 return line;
2944
2945         /*
2946                 Send the message to others
2947         */
2948         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2949
2950         std::vector<session_t> clients = m_clients.getClientIDs();
2951
2952         /*
2953                 Send the message back to the inital sender
2954                 if they are using protocol version >= 29
2955         */
2956
2957         session_t peer_id_to_avoid_sending =
2958                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
2959
2960         if (player && player->protocol_version >= 29)
2961                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2962
2963         for (u16 cid : clients) {
2964                 if (cid != peer_id_to_avoid_sending)
2965                         SendChatMessage(cid, ChatMessage(line));
2966         }
2967         return L"";
2968 }
2969
2970 void Server::handleAdminChat(const ChatEventChat *evt)
2971 {
2972         std::string name = evt->nick;
2973         std::wstring wname = utf8_to_wide(name);
2974         std::wstring wmessage = evt->evt_msg;
2975
2976         std::wstring answer = handleChat(name, wname, wmessage);
2977
2978         // If asked to send answer to sender
2979         if (!answer.empty()) {
2980                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2981         }
2982 }
2983
2984 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
2985 {
2986         RemoteClient *client = getClientNoEx(peer_id,state_min);
2987         if(!client)
2988                 throw ClientNotFoundException("Client not found");
2989
2990         return client;
2991 }
2992 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
2993 {
2994         return m_clients.getClientNoEx(peer_id, state_min);
2995 }
2996
2997 std::string Server::getPlayerName(session_t peer_id)
2998 {
2999         RemotePlayer *player = m_env->getPlayer(peer_id);
3000         if (!player)
3001                 return "[id="+itos(peer_id)+"]";
3002         return player->getName();
3003 }
3004
3005 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
3006 {
3007         RemotePlayer *player = m_env->getPlayer(peer_id);
3008         if (!player)
3009                 return NULL;
3010         return player->getPlayerSAO();
3011 }
3012
3013 std::wstring Server::getStatusString()
3014 {
3015         std::wostringstream os(std::ios_base::binary);
3016         os << L"# Server: ";
3017         // Version
3018         os << L"version=" << narrow_to_wide(g_version_string);
3019         // Uptime
3020         os << L", uptime=" << m_uptime.get();
3021         // Max lag estimate
3022         os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
3023
3024         // Information about clients
3025         bool first = true;
3026         os << L", clients={";
3027         if (m_env) {
3028                 std::vector<session_t> clients = m_clients.getClientIDs();
3029                 for (session_t client_id : clients) {
3030                         RemotePlayer *player = m_env->getPlayer(client_id);
3031
3032                         // Get name of player
3033                         std::wstring name = L"unknown";
3034                         if (player)
3035                                 name = narrow_to_wide(player->getName());
3036
3037                         // Add name to information string
3038                         if (!first)
3039                                 os << L", ";
3040                         else
3041                                 first = false;
3042
3043                         os << name;
3044                 }
3045         }
3046         os << L"}";
3047
3048         if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3049                 os << std::endl << L"# Server: " << " WARNING: Map saving is disabled.";
3050
3051         if (!g_settings->get("motd").empty())
3052                 os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd"));
3053
3054         return os.str();
3055 }
3056
3057 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3058 {
3059         std::set<std::string> privs;
3060         m_script->getAuth(name, NULL, &privs);
3061         return privs;
3062 }
3063
3064 bool Server::checkPriv(const std::string &name, const std::string &priv)
3065 {
3066         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3067         return (privs.count(priv) != 0);
3068 }
3069
3070 void Server::reportPrivsModified(const std::string &name)
3071 {
3072         if (name.empty()) {
3073                 std::vector<session_t> clients = m_clients.getClientIDs();
3074                 for (const session_t client_id : clients) {
3075                         RemotePlayer *player = m_env->getPlayer(client_id);
3076                         reportPrivsModified(player->getName());
3077                 }
3078         } else {
3079                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3080                 if (!player)
3081                         return;
3082                 SendPlayerPrivileges(player->getPeerId());
3083                 PlayerSAO *sao = player->getPlayerSAO();
3084                 if(!sao)
3085                         return;
3086                 sao->updatePrivileges(
3087                                 getPlayerEffectivePrivs(name),
3088                                 isSingleplayer());
3089         }
3090 }
3091
3092 void Server::reportInventoryFormspecModified(const std::string &name)
3093 {
3094         RemotePlayer *player = m_env->getPlayer(name.c_str());
3095         if (!player)
3096                 return;
3097         SendPlayerInventoryFormspec(player->getPeerId());
3098 }
3099
3100 void Server::reportFormspecPrependModified(const std::string &name)
3101 {
3102         RemotePlayer *player = m_env->getPlayer(name.c_str());
3103         if (!player)
3104                 return;
3105         SendPlayerFormspecPrepend(player->getPeerId());
3106 }
3107
3108 void Server::setIpBanned(const std::string &ip, const std::string &name)
3109 {
3110         m_banmanager->add(ip, name);
3111 }
3112
3113 void Server::unsetIpBanned(const std::string &ip_or_name)
3114 {
3115         m_banmanager->remove(ip_or_name);
3116 }
3117
3118 std::string Server::getBanDescription(const std::string &ip_or_name)
3119 {
3120         return m_banmanager->getBanDescription(ip_or_name);
3121 }
3122
3123 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3124 {
3125         // m_env will be NULL if the server is initializing
3126         if (!m_env)
3127                 return;
3128
3129         if (m_admin_nick == name && !m_admin_nick.empty()) {
3130                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3131         }
3132
3133         RemotePlayer *player = m_env->getPlayer(name);
3134         if (!player) {
3135                 return;
3136         }
3137
3138         if (player->getPeerId() == PEER_ID_INEXISTENT)
3139                 return;
3140
3141         SendChatMessage(player->getPeerId(), ChatMessage(msg));
3142 }
3143
3144 bool Server::showFormspec(const char *playername, const std::string &formspec,
3145         const std::string &formname)
3146 {
3147         // m_env will be NULL if the server is initializing
3148         if (!m_env)
3149                 return false;
3150
3151         RemotePlayer *player = m_env->getPlayer(playername);
3152         if (!player)
3153                 return false;
3154
3155         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3156         return true;
3157 }
3158
3159 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3160 {
3161         if (!player)
3162                 return -1;
3163
3164         u32 id = player->addHud(form);
3165
3166         SendHUDAdd(player->getPeerId(), id, form);
3167
3168         return id;
3169 }
3170
3171 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3172         if (!player)
3173                 return false;
3174
3175         HudElement* todel = player->removeHud(id);
3176
3177         if (!todel)
3178                 return false;
3179
3180         delete todel;
3181
3182         SendHUDRemove(player->getPeerId(), id);
3183         return true;
3184 }
3185
3186 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3187 {
3188         if (!player)
3189                 return false;
3190
3191         SendHUDChange(player->getPeerId(), id, stat, data);
3192         return true;
3193 }
3194
3195 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3196 {
3197         if (!player)
3198                 return false;
3199
3200         SendHUDSetFlags(player->getPeerId(), flags, mask);
3201         player->hud_flags &= ~mask;
3202         player->hud_flags |= flags;
3203
3204         PlayerSAO* playersao = player->getPlayerSAO();
3205
3206         if (!playersao)
3207                 return false;
3208
3209         m_script->player_event(playersao, "hud_changed");
3210         return true;
3211 }
3212
3213 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3214 {
3215         if (!player)
3216                 return false;
3217
3218         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3219                 return false;
3220
3221         player->setHotbarItemcount(hotbar_itemcount);
3222         std::ostringstream os(std::ios::binary);
3223         writeS32(os, hotbar_itemcount);
3224         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3225         return true;
3226 }
3227
3228 void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
3229 {
3230         if (!player)
3231                 return;
3232
3233         player->setHotbarImage(name);
3234         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3235 }
3236
3237 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
3238 {
3239         if (!player)
3240                 return;
3241
3242         player->setHotbarSelectedImage(name);
3243         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3244 }
3245
3246 Address Server::getPeerAddress(session_t peer_id)
3247 {
3248         return m_con->GetPeerAddress(peer_id);
3249 }
3250
3251 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3252                 v2s32 animation_frames[4], f32 frame_speed)
3253 {
3254         sanity_check(player);
3255         player->setLocalAnimations(animation_frames, frame_speed);
3256         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3257 }
3258
3259 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3260 {
3261         sanity_check(player);
3262         player->eye_offset_first = first;
3263         player->eye_offset_third = third;
3264         SendEyeOffset(player->getPeerId(), first, third);
3265 }
3266
3267 void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3268         const std::string &type, const std::vector<std::string> &params,
3269         bool &clouds)
3270 {
3271         sanity_check(player);
3272         player->setSky(bgcolor, type, params, clouds);
3273         SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
3274 }
3275
3276 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3277 {
3278         sanity_check(player);
3279         player->setCloudParams(params);
3280         SendCloudParams(player->getPeerId(), params);
3281 }
3282
3283 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3284         float ratio)
3285 {
3286         if (!player)
3287                 return false;
3288
3289         player->overrideDayNightRatio(do_override, ratio);
3290         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3291         return true;
3292 }
3293
3294 void Server::notifyPlayers(const std::wstring &msg)
3295 {
3296         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3297 }
3298
3299 void Server::spawnParticle(const std::string &playername, v3f pos,
3300         v3f velocity, v3f acceleration,
3301         float expirationtime, float size, bool
3302         collisiondetection, bool collision_removal, bool object_collision,
3303         bool vertical, const std::string &texture,
3304         const struct TileAnimationParams &animation, u8 glow)
3305 {
3306         // m_env will be NULL if the server is initializing
3307         if (!m_env)
3308                 return;
3309
3310         session_t peer_id = PEER_ID_INEXISTENT;
3311         u16 proto_ver = 0;
3312         if (!playername.empty()) {
3313                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3314                 if (!player)
3315                         return;
3316                 peer_id = player->getPeerId();
3317                 proto_ver = player->protocol_version;
3318         }
3319
3320         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3321                         expirationtime, size, collisiondetection, collision_removal,
3322                         object_collision, vertical, texture, animation, glow);
3323 }
3324
3325 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3326         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3327         float minexptime, float maxexptime, float minsize, float maxsize,
3328         bool collisiondetection, bool collision_removal, bool object_collision,
3329         ServerActiveObject *attached, bool vertical, const std::string &texture,
3330         const std::string &playername, const struct TileAnimationParams &animation,
3331         u8 glow)
3332 {
3333         // m_env will be NULL if the server is initializing
3334         if (!m_env)
3335                 return -1;
3336
3337         session_t peer_id = PEER_ID_INEXISTENT;
3338         u16 proto_ver = 0;
3339         if (!playername.empty()) {
3340                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3341                 if (!player)
3342                         return -1;
3343                 peer_id = player->getPeerId();
3344                 proto_ver = player->protocol_version;
3345         }
3346
3347         u16 attached_id = attached ? attached->getId() : 0;
3348
3349         u32 id;
3350         if (attached_id == 0)
3351                 id = m_env->addParticleSpawner(spawntime);
3352         else
3353                 id = m_env->addParticleSpawner(spawntime, attached_id);
3354
3355         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3356                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3357                 minexptime, maxexptime, minsize, maxsize, collisiondetection,
3358                 collision_removal, object_collision, attached_id, vertical,
3359                 texture, id, animation, glow);
3360
3361         return id;
3362 }
3363
3364 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3365 {
3366         // m_env will be NULL if the server is initializing
3367         if (!m_env)
3368                 throw ServerError("Can't delete particle spawners during initialisation!");
3369
3370         session_t peer_id = PEER_ID_INEXISTENT;
3371         if (!playername.empty()) {
3372                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3373                 if (!player)
3374                         return;
3375                 peer_id = player->getPeerId();
3376         }
3377
3378         m_env->deleteParticleSpawner(id);
3379         SendDeleteParticleSpawner(peer_id, id);
3380 }
3381
3382 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3383 {
3384         if(m_detached_inventories.count(name) > 0){
3385                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3386                 delete m_detached_inventories[name];
3387         } else {
3388                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3389         }
3390         Inventory *inv = new Inventory(m_itemdef);
3391         sanity_check(inv);
3392         m_detached_inventories[name] = inv;
3393         if (!player.empty())
3394                 m_detached_inventories_player[name] = player;
3395
3396         //TODO find a better way to do this
3397         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3398         return inv;
3399 }
3400
3401 bool Server::removeDetachedInventory(const std::string &name)
3402 {
3403         const auto &inv_it = m_detached_inventories.find(name);
3404         if (inv_it == m_detached_inventories.end())
3405                 return false;
3406
3407         delete inv_it->second;
3408         m_detached_inventories.erase(inv_it);
3409
3410         if (!m_env) // Mods are not done loading
3411                 return true;
3412
3413         const auto &player_it = m_detached_inventories_player.find(name);
3414         if (player_it != m_detached_inventories_player.end()) {
3415                 RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());
3416
3417                 if (player && player->getPeerId() != PEER_ID_INEXISTENT)
3418                         sendDetachedInventory(name, player->getPeerId());
3419
3420                 m_detached_inventories_player.erase(player_it);
3421         } else {
3422                 // Notify all players about the change
3423                 sendDetachedInventory(name, PEER_ID_INEXISTENT);
3424         }
3425         return true;
3426 }
3427
3428 // actions: time-reversed list
3429 // Return value: success/failure
3430 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3431                 std::list<std::string> *log)
3432 {
3433         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3434         ServerMap *map = (ServerMap*)(&m_env->getMap());
3435
3436         // Fail if no actions to handle
3437         if (actions.empty()) {
3438                 assert(log);
3439                 log->push_back("Nothing to do.");
3440                 return false;
3441         }
3442
3443         int num_tried = 0;
3444         int num_failed = 0;
3445
3446         for (const RollbackAction &action : actions) {
3447                 num_tried++;
3448                 bool success = action.applyRevert(map, this, this);
3449                 if(!success){
3450                         num_failed++;
3451                         std::ostringstream os;
3452                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3453                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3454                         if (log)
3455                                 log->push_back(os.str());
3456                 }else{
3457                         std::ostringstream os;
3458                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3459                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3460                         if (log)
3461                                 log->push_back(os.str());
3462                 }
3463         }
3464
3465         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3466                         <<" failed"<<std::endl;
3467
3468         // Call it done if less than half failed
3469         return num_failed <= num_tried/2;
3470 }
3471
3472 // IGameDef interface
3473 // Under envlock
3474 IItemDefManager *Server::getItemDefManager()
3475 {
3476         return m_itemdef;
3477 }
3478
3479 const NodeDefManager *Server::getNodeDefManager()
3480 {
3481         return m_nodedef;
3482 }
3483
3484 ICraftDefManager *Server::getCraftDefManager()
3485 {
3486         return m_craftdef;
3487 }
3488
3489 u16 Server::allocateUnknownNodeId(const std::string &name)
3490 {
3491         return m_nodedef->allocateDummy(name);
3492 }
3493
3494 IWritableItemDefManager *Server::getWritableItemDefManager()
3495 {
3496         return m_itemdef;
3497 }
3498
3499 NodeDefManager *Server::getWritableNodeDefManager()
3500 {
3501         return m_nodedef;
3502 }
3503
3504 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3505 {
3506         return m_craftdef;
3507 }
3508
3509 const std::vector<ModSpec> & Server::getMods() const
3510 {
3511         return m_modmgr->getMods();
3512 }
3513
3514 const ModSpec *Server::getModSpec(const std::string &modname) const
3515 {
3516         return m_modmgr->getModSpec(modname);
3517 }
3518
3519 void Server::getModNames(std::vector<std::string> &modlist)
3520 {
3521         m_modmgr->getModNames(modlist);
3522 }
3523
3524 std::string Server::getBuiltinLuaPath()
3525 {
3526         return porting::path_share + DIR_DELIM + "builtin";
3527 }
3528
3529 std::string Server::getModStoragePath() const
3530 {
3531         return m_path_world + DIR_DELIM + "mod_storage";
3532 }
3533
3534 v3f Server::findSpawnPos()
3535 {
3536         ServerMap &map = m_env->getServerMap();
3537         v3f nodeposf;
3538         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
3539                 return nodeposf * BS;
3540
3541         bool is_good = false;
3542         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3543         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3544
3545         // Try to find a good place a few times
3546         for (s32 i = 0; i < 4000 && !is_good; i++) {
3547                 s32 range = MYMIN(1 + i, range_max);
3548                 // We're going to try to throw the player to this position
3549                 v2s16 nodepos2d = v2s16(
3550                         -range + (myrand() % (range * 2)),
3551                         -range + (myrand() % (range * 2)));
3552                 // Get spawn level at point
3553                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3554                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
3555                 // signify an unsuitable spawn position, or if outside limits.
3556                 if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
3557                                 spawn_level <= -MAX_MAP_GENERATION_LIMIT)
3558                         continue;
3559
3560                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3561                 // Consecutive empty nodes
3562                 s32 air_count = 0;
3563
3564                 // Search upwards from 'spawn level' for 2 consecutive empty nodes, to
3565                 // avoid obstructions in already-generated mapblocks.
3566                 // In ungenerated mapblocks consisting of 'ignore' nodes, there will be
3567                 // no obstructions, but mapgen decorations are generated after spawn so
3568                 // the player may end up inside one.
3569                 for (s32 i = 0; i < 8; i++) {
3570                         v3s16 blockpos = getNodeBlockPos(nodepos);
3571                         map.emergeBlock(blockpos, true);
3572                         content_t c = map.getNode(nodepos).getContent();
3573
3574                         // In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
3575                         // In ungenerated mapblocks allow spawn in 'ignore' nodes.
3576                         if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
3577                                 air_count++;
3578                                 if (air_count >= 2) {
3579                                         // Spawn in lower empty node
3580                                         nodepos.Y--;
3581                                         nodeposf = intToFloat(nodepos, BS);
3582                                         // Don't spawn the player outside map boundaries
3583                                         if (objectpos_over_limit(nodeposf))
3584                                                 // Exit this loop, positions above are probably over limit
3585                                                 break;
3586
3587                                         // Good position found, cause an exit from main loop
3588                                         is_good = true;
3589                                         break;
3590                                 }
3591                         } else {
3592                                 air_count = 0;
3593                         }
3594                         nodepos.Y++;
3595                 }
3596         }
3597
3598         if (is_good)
3599                 return nodeposf;
3600
3601         // No suitable spawn point found, return fallback 0,0,0
3602         return v3f(0.0f, 0.0f, 0.0f);
3603 }
3604
3605 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3606 {
3607         if (delay == 0.0f) {
3608         // No delay, shutdown immediately
3609                 m_shutdown_state.is_requested = true;
3610                 // only print to the infostream, a chat message saying
3611                 // "Server Shutting Down" is sent when the server destructs.
3612                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3613         } else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3614                 // Negative delay, cancel shutdown if requested
3615                 m_shutdown_state.reset();
3616                 std::wstringstream ws;
3617
3618                 ws << L"*** Server shutdown canceled.";
3619
3620                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3621                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3622                 // m_shutdown_* are already handled, skip.
3623                 return;
3624         } else if (delay > 0.0f) {
3625         // Positive delay, tell the clients when the server will shut down
3626                 std::wstringstream ws;
3627
3628                 ws << L"*** Server shutting down in "
3629                                 << duration_to_string(myround(delay)).c_str()
3630                                 << ".";
3631
3632                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3633                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3634         }
3635
3636         m_shutdown_state.trigger(delay, msg, reconnect);
3637 }
3638
3639 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3640 {
3641         /*
3642                 Try to get an existing player
3643         */
3644         RemotePlayer *player = m_env->getPlayer(name);
3645
3646         // If player is already connected, cancel
3647         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3648                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3649                 return NULL;
3650         }
3651
3652         /*
3653                 If player with the wanted peer_id already exists, cancel.
3654         */
3655         if (m_env->getPlayer(peer_id)) {
3656                 infostream<<"emergePlayer(): Player with wrong name but same"
3657                                 " peer_id already exists"<<std::endl;
3658                 return NULL;
3659         }
3660
3661         if (!player) {
3662                 player = new RemotePlayer(name, idef());
3663         }
3664
3665         bool newplayer = false;
3666
3667         // Load player
3668         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3669
3670         // Complete init with server parts
3671         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3672         player->protocol_version = proto_version;
3673
3674         /* Run scripts */
3675         if (newplayer) {
3676                 m_script->on_newplayer(playersao);
3677         }
3678
3679         return playersao;
3680 }
3681
3682 bool Server::registerModStorage(ModMetadata *storage)
3683 {
3684         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3685                 errorstream << "Unable to register same mod storage twice. Storage name: "
3686                                 << storage->getModName() << std::endl;
3687                 return false;
3688         }
3689
3690         m_mod_storages[storage->getModName()] = storage;
3691         return true;
3692 }
3693
3694 void Server::unregisterModStorage(const std::string &name)
3695 {
3696         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3697         if (it != m_mod_storages.end()) {
3698                 // Save unconditionaly on unregistration
3699                 it->second->save(getModStoragePath());
3700                 m_mod_storages.erase(name);
3701         }
3702 }
3703
3704 void dedicated_server_loop(Server &server, bool &kill)
3705 {
3706         verbosestream<<"dedicated_server_loop()"<<std::endl;
3707
3708         IntervalLimiter m_profiler_interval;
3709
3710         static thread_local const float steplen =
3711                         g_settings->getFloat("dedicated_server_step");
3712         static thread_local const float profiler_print_interval =
3713                         g_settings->getFloat("profiler_print_interval");
3714
3715         for(;;) {
3716                 // This is kind of a hack but can be done like this
3717                 // because server.step() is very light
3718                 sleep_ms((int)(steplen*1000.0));
3719                 server.step(steplen);
3720
3721                 if (server.isShutdownRequested() || kill)
3722                         break;
3723
3724                 /*
3725                         Profiler
3726                 */
3727                 if (profiler_print_interval != 0) {
3728                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3729                         {
3730                                 infostream<<"Profiler:"<<std::endl;
3731                                 g_profiler->print(infostream);
3732                                 g_profiler->clear();
3733                         }
3734                 }
3735         }
3736
3737         infostream << "Dedicated server quitting" << std::endl;
3738 #if USE_CURL
3739         if (g_settings->getBool("server_announce"))
3740                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3741                         server.m_bind_addr.getPort());
3742 #endif
3743 }
3744
3745 /*
3746  * Mod channels
3747  */
3748
3749
3750 bool Server::joinModChannel(const std::string &channel)
3751 {
3752         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3753                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3754 }
3755
3756 bool Server::leaveModChannel(const std::string &channel)
3757 {
3758         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3759 }
3760
3761 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3762 {
3763         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3764                 return false;
3765
3766         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3767         return true;
3768 }
3769
3770 ModChannel* Server::getModChannel(const std::string &channel)
3771 {
3772         return m_modchannel_mgr->getModChannel(channel);
3773 }
3774
3775 void Server::broadcastModChannelMessage(const std::string &channel,
3776                 const std::string &message, session_t from_peer)
3777 {
3778         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3779         if (peers.empty())
3780                 return;
3781
3782         if (message.size() > STRING_MAX_LEN) {
3783                 warningstream << "ModChannel message too long, dropping before sending "
3784                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3785                                 << channel << ")" << std::endl;
3786                 return;
3787         }
3788
3789         std::string sender;
3790         if (from_peer != PEER_ID_SERVER) {
3791                 sender = getPlayerName(from_peer);
3792         }
3793
3794         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3795                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3796         resp_pkt << channel << sender << message;
3797         for (session_t peer_id : peers) {
3798                 // Ignore sender
3799                 if (peer_id == from_peer)
3800                         continue;
3801
3802                 Send(peer_id, &resp_pkt);
3803         }
3804
3805         if (from_peer != PEER_ID_SERVER) {
3806                 m_script->on_modchannel_message(channel, sender, message);
3807         }
3808 }