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