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