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