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