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