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