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