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