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