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