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