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