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