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