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