Add reasons to on_dieplayer and on_hpchange
[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         rawstream
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                                 PlayerHPChangeReason(PlayerHPChangeReason::SET_HP));
1034
1035         // Send Breath
1036         SendPlayerBreath(playersao);
1037
1038         // Note things in chat if not in simple singleplayer mode
1039         if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) {
1040                 // Send information about server to player in chat
1041                 SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, getStatusString()));
1042         }
1043         Address addr = getPeerAddress(player->getPeerId());
1044         std::string ip_str = addr.serializeString();
1045         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1046         /*
1047                 Print out action
1048         */
1049         {
1050                 const std::vector<std::string> &names = m_clients.getPlayerNames();
1051
1052                 actionstream << player->getName() << " joins game. List of players: ";
1053
1054                 for (const std::string &name : names) {
1055                         actionstream << name << " ";
1056                 }
1057
1058                 actionstream << player->getName() <<std::endl;
1059         }
1060         return playersao;
1061 }
1062
1063 inline void Server::handleCommand(NetworkPacket* pkt)
1064 {
1065         const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
1066         (this->*opHandle.handler)(pkt);
1067 }
1068
1069 void Server::ProcessData(NetworkPacket *pkt)
1070 {
1071         // Environment is locked first.
1072         MutexAutoLock envlock(m_env_mutex);
1073
1074         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1075         u32 peer_id = pkt->getPeerId();
1076
1077         try {
1078                 Address address = getPeerAddress(peer_id);
1079                 std::string addr_s = address.serializeString();
1080
1081                 if(m_banmanager->isIpBanned(addr_s)) {
1082                         std::string ban_name = m_banmanager->getBanName(addr_s);
1083                         infostream << "Server: A banned client tried to connect from "
1084                                         << addr_s << "; banned name was "
1085                                         << ban_name << std::endl;
1086                         // This actually doesn't seem to transfer to the client
1087                         DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
1088                                         + utf8_to_wide(ban_name));
1089                         return;
1090                 }
1091         }
1092         catch(con::PeerNotFoundException &e) {
1093                 /*
1094                  * no peer for this packet found
1095                  * most common reason is peer timeout, e.g. peer didn't
1096                  * respond for some time, your server was overloaded or
1097                  * things like that.
1098                  */
1099                 infostream << "Server::ProcessData(): Canceling: peer "
1100                                 << peer_id << " not found" << std::endl;
1101                 return;
1102         }
1103
1104         try {
1105                 ToServerCommand command = (ToServerCommand) pkt->getCommand();
1106
1107                 // Command must be handled into ToServerCommandHandler
1108                 if (command >= TOSERVER_NUM_MSG_TYPES) {
1109                         infostream << "Server: Ignoring unknown command "
1110                                          << command << std::endl;
1111                         return;
1112                 }
1113
1114                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1115                         handleCommand(pkt);
1116                         return;
1117                 }
1118
1119                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1120
1121                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1122                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1123                                         " serialization format invalid or not initialized."
1124                                         " Skipping incoming command=" << command << std::endl;
1125                         return;
1126                 }
1127
1128                 /* Handle commands related to client startup */
1129                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1130                         handleCommand(pkt);
1131                         return;
1132                 }
1133
1134                 if (m_clients.getClientState(peer_id) < CS_Active) {
1135                         if (command == TOSERVER_PLAYERPOS) return;
1136
1137                         errorstream << "Got packet command: " << command << " for peer id "
1138                                         << peer_id << " but client isn't active yet. Dropping packet "
1139                                         << std::endl;
1140                         return;
1141                 }
1142
1143                 handleCommand(pkt);
1144         } catch (SendFailedException &e) {
1145                 errorstream << "Server::ProcessData(): SendFailedException: "
1146                                 << "what=" << e.what()
1147                                 << std::endl;
1148         } catch (PacketError &e) {
1149                 actionstream << "Server::ProcessData(): PacketError: "
1150                                 << "what=" << e.what()
1151                                 << std::endl;
1152         }
1153 }
1154
1155 void Server::setTimeOfDay(u32 time)
1156 {
1157         m_env->setTimeOfDay(time);
1158         m_time_of_day_send_timer = 0;
1159 }
1160
1161 void Server::onMapEditEvent(MapEditEvent *event)
1162 {
1163         if(m_ignore_map_edit_events)
1164                 return;
1165         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1166                 return;
1167         MapEditEvent *e = event->clone();
1168         m_unsent_map_edit_queue.push(e);
1169 }
1170
1171 Inventory* Server::getInventory(const InventoryLocation &loc)
1172 {
1173         switch (loc.type) {
1174         case InventoryLocation::UNDEFINED:
1175         case InventoryLocation::CURRENT_PLAYER:
1176                 break;
1177         case InventoryLocation::PLAYER:
1178         {
1179                 RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
1180                 if(!player)
1181                         return NULL;
1182                 PlayerSAO *playersao = player->getPlayerSAO();
1183                 if(!playersao)
1184                         return NULL;
1185                 return playersao->getInventory();
1186         }
1187                 break;
1188         case InventoryLocation::NODEMETA:
1189         {
1190                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1191                 if(!meta)
1192                         return NULL;
1193                 return meta->getInventory();
1194         }
1195                 break;
1196         case InventoryLocation::DETACHED:
1197         {
1198                 if(m_detached_inventories.count(loc.name) == 0)
1199                         return NULL;
1200                 return m_detached_inventories[loc.name];
1201         }
1202                 break;
1203         default:
1204                 sanity_check(false); // abort
1205                 break;
1206         }
1207         return NULL;
1208 }
1209 void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
1210 {
1211         switch(loc.type){
1212         case InventoryLocation::UNDEFINED:
1213                 break;
1214         case InventoryLocation::PLAYER:
1215         {
1216                 if (!playerSend)
1217                         return;
1218
1219                 RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
1220
1221                 if (!player)
1222                         return;
1223
1224                 PlayerSAO *playersao = player->getPlayerSAO();
1225                 if(!playersao)
1226                         return;
1227
1228                 SendInventory(playersao);
1229         }
1230                 break;
1231         case InventoryLocation::NODEMETA:
1232         {
1233                 v3s16 blockpos = getNodeBlockPos(loc.p);
1234
1235                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1236                 if (block)
1237                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1238
1239                 m_clients.markBlockposAsNotSent(blockpos);
1240         }
1241                 break;
1242         case InventoryLocation::DETACHED:
1243         {
1244                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1245         }
1246                 break;
1247         default:
1248                 sanity_check(false); // abort
1249                 break;
1250         }
1251 }
1252
1253 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1254 {
1255         std::vector<session_t> clients = m_clients.getClientIDs();
1256         m_clients.lock();
1257         // Set the modified blocks unsent for all the clients
1258         for (const session_t client_id : clients) {
1259                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(client_id))
1260                                 client->SetBlocksNotSent(block);
1261         }
1262         m_clients.unlock();
1263 }
1264
1265 void Server::peerAdded(con::Peer *peer)
1266 {
1267         verbosestream<<"Server::peerAdded(): peer->id="
1268                         <<peer->id<<std::endl;
1269
1270         m_peer_change_queue.push(con::PeerChange(con::PEER_ADDED, peer->id, false));
1271 }
1272
1273 void Server::deletingPeer(con::Peer *peer, bool timeout)
1274 {
1275         verbosestream<<"Server::deletingPeer(): peer->id="
1276                         <<peer->id<<", timeout="<<timeout<<std::endl;
1277
1278         m_clients.event(peer->id, CSE_Disconnect);
1279         m_peer_change_queue.push(con::PeerChange(con::PEER_REMOVED, peer->id, timeout));
1280 }
1281
1282 bool Server::getClientConInfo(session_t peer_id, con::rtt_stat_type type, float* retval)
1283 {
1284         *retval = m_con->getPeerStat(peer_id,type);
1285         return *retval != -1;
1286 }
1287
1288 bool Server::getClientInfo(
1289                 session_t    peer_id,
1290                 ClientState* state,
1291                 u32*         uptime,
1292                 u8*          ser_vers,
1293                 u16*         prot_vers,
1294                 u8*          major,
1295                 u8*          minor,
1296                 u8*          patch,
1297                 std::string* vers_string
1298         )
1299 {
1300         *state = m_clients.getClientState(peer_id);
1301         m_clients.lock();
1302         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1303
1304         if (!client) {
1305                 m_clients.unlock();
1306                 return false;
1307         }
1308
1309         *uptime = client->uptime();
1310         *ser_vers = client->serialization_version;
1311         *prot_vers = client->net_proto_version;
1312
1313         *major = client->getMajor();
1314         *minor = client->getMinor();
1315         *patch = client->getPatch();
1316         *vers_string = client->getPatch();
1317
1318         m_clients.unlock();
1319
1320         return true;
1321 }
1322
1323 void Server::handlePeerChanges()
1324 {
1325         while(!m_peer_change_queue.empty())
1326         {
1327                 con::PeerChange c = m_peer_change_queue.front();
1328                 m_peer_change_queue.pop();
1329
1330                 verbosestream<<"Server: Handling peer change: "
1331                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1332                                 <<std::endl;
1333
1334                 switch(c.type)
1335                 {
1336                 case con::PEER_ADDED:
1337                         m_clients.CreateClient(c.peer_id);
1338                         break;
1339
1340                 case con::PEER_REMOVED:
1341                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1342                         break;
1343
1344                 default:
1345                         FATAL_ERROR("Invalid peer change event received!");
1346                         break;
1347                 }
1348         }
1349 }
1350
1351 void Server::printToConsoleOnly(const std::string &text)
1352 {
1353         if (m_admin_chat) {
1354                 m_admin_chat->outgoing_queue.push_back(
1355                         new ChatEventChat("", utf8_to_wide(text)));
1356         } else {
1357                 std::cout << text << std::endl;
1358         }
1359 }
1360
1361 void Server::Send(NetworkPacket *pkt)
1362 {
1363         Send(pkt->getPeerId(), pkt);
1364 }
1365
1366 void Server::Send(session_t peer_id, NetworkPacket *pkt)
1367 {
1368         m_clients.send(peer_id,
1369                 clientCommandFactoryTable[pkt->getCommand()].channel,
1370                 pkt,
1371                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1372 }
1373
1374 void Server::SendMovement(session_t peer_id)
1375 {
1376         std::ostringstream os(std::ios_base::binary);
1377
1378         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1379
1380         pkt << g_settings->getFloat("movement_acceleration_default");
1381         pkt << g_settings->getFloat("movement_acceleration_air");
1382         pkt << g_settings->getFloat("movement_acceleration_fast");
1383         pkt << g_settings->getFloat("movement_speed_walk");
1384         pkt << g_settings->getFloat("movement_speed_crouch");
1385         pkt << g_settings->getFloat("movement_speed_fast");
1386         pkt << g_settings->getFloat("movement_speed_climb");
1387         pkt << g_settings->getFloat("movement_speed_jump");
1388         pkt << g_settings->getFloat("movement_liquid_fluidity");
1389         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1390         pkt << g_settings->getFloat("movement_liquid_sink");
1391         pkt << g_settings->getFloat("movement_gravity");
1392
1393         Send(&pkt);
1394 }
1395
1396 void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
1397 {
1398         if (!g_settings->getBool("enable_damage"))
1399                 return;
1400
1401         session_t peer_id   = playersao->getPeerID();
1402         bool is_alive = playersao->getHP() > 0;
1403
1404         if (is_alive)
1405                 SendPlayerHP(peer_id);
1406         else
1407                 DiePlayer(peer_id, reason);
1408 }
1409
1410 void Server::SendHP(session_t peer_id, u16 hp)
1411 {
1412         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1413         pkt << hp;
1414         Send(&pkt);
1415 }
1416
1417 void Server::SendBreath(session_t peer_id, u16 breath)
1418 {
1419         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1420         pkt << (u16) breath;
1421         Send(&pkt);
1422 }
1423
1424 void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
1425                 const std::string &custom_reason, bool reconnect)
1426 {
1427         assert(reason < SERVER_ACCESSDENIED_MAX);
1428
1429         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1430         pkt << (u8)reason;
1431         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1432                 pkt << custom_reason;
1433         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1434                         reason == SERVER_ACCESSDENIED_CRASH)
1435                 pkt << custom_reason << (u8)reconnect;
1436         Send(&pkt);
1437 }
1438
1439 void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reason)
1440 {
1441         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1442         pkt << reason;
1443         Send(&pkt);
1444 }
1445
1446 void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
1447                 v3f camera_point_target)
1448 {
1449         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1450         pkt << set_camera_point_target << camera_point_target;
1451         Send(&pkt);
1452 }
1453
1454 void Server::SendItemDef(session_t peer_id,
1455                 IItemDefManager *itemdef, u16 protocol_version)
1456 {
1457         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1458
1459         /*
1460                 u16 command
1461                 u32 length of the next item
1462                 zlib-compressed serialized ItemDefManager
1463         */
1464         std::ostringstream tmp_os(std::ios::binary);
1465         itemdef->serialize(tmp_os, protocol_version);
1466         std::ostringstream tmp_os2(std::ios::binary);
1467         compressZlib(tmp_os.str(), tmp_os2);
1468         pkt.putLongString(tmp_os2.str());
1469
1470         // Make data buffer
1471         verbosestream << "Server: Sending item definitions to id(" << peer_id
1472                         << "): size=" << pkt.getSize() << std::endl;
1473
1474         Send(&pkt);
1475 }
1476
1477 void Server::SendNodeDef(session_t peer_id,
1478         const NodeDefManager *nodedef, u16 protocol_version)
1479 {
1480         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1481
1482         /*
1483                 u16 command
1484                 u32 length of the next item
1485                 zlib-compressed serialized NodeDefManager
1486         */
1487         std::ostringstream tmp_os(std::ios::binary);
1488         nodedef->serialize(tmp_os, protocol_version);
1489         std::ostringstream tmp_os2(std::ios::binary);
1490         compressZlib(tmp_os.str(), tmp_os2);
1491
1492         pkt.putLongString(tmp_os2.str());
1493
1494         // Make data buffer
1495         verbosestream << "Server: Sending node definitions to id(" << peer_id
1496                         << "): size=" << pkt.getSize() << std::endl;
1497
1498         Send(&pkt);
1499 }
1500
1501 /*
1502         Non-static send methods
1503 */
1504
1505 void Server::SendInventory(PlayerSAO* playerSAO)
1506 {
1507         UpdateCrafting(playerSAO->getPlayer());
1508
1509         /*
1510                 Serialize it
1511         */
1512
1513         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1514
1515         std::ostringstream os;
1516         playerSAO->getInventory()->serialize(os);
1517
1518         std::string s = os.str();
1519
1520         pkt.putRawString(s.c_str(), s.size());
1521         Send(&pkt);
1522 }
1523
1524 void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
1525 {
1526         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1527         u8 version = 1;
1528         u8 type = message.type;
1529         pkt << version << type << std::wstring(L"") << message.message << message.timestamp;
1530
1531         if (peer_id != PEER_ID_INEXISTENT) {
1532                 RemotePlayer *player = m_env->getPlayer(peer_id);
1533                 if (!player)
1534                         return;
1535
1536                 Send(&pkt);
1537         } else {
1538                 m_clients.sendToAll(&pkt);
1539         }
1540 }
1541
1542 void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
1543                                      const std::string &formname)
1544 {
1545         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1546         if (formspec.empty()){
1547                 //the client should close the formspec
1548                 m_formspec_state_data.erase(peer_id);
1549                 pkt.putLongString("");
1550         } else {
1551                 m_formspec_state_data[peer_id] = formname;
1552                 pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1553         }
1554         pkt << formname;
1555
1556         Send(&pkt);
1557 }
1558
1559 // Spawns a particle on peer with peer_id
1560 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
1561                                 v3f pos, v3f velocity, v3f acceleration,
1562                                 float expirationtime, float size, bool collisiondetection,
1563                                 bool collision_removal,
1564                                 bool vertical, const std::string &texture,
1565                                 const struct TileAnimationParams &animation, u8 glow)
1566 {
1567         static thread_local const float radius =
1568                         g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1569
1570         if (peer_id == PEER_ID_INEXISTENT) {
1571                 std::vector<session_t> clients = m_clients.getClientIDs();
1572
1573                 for (const session_t client_id : clients) {
1574                         RemotePlayer *player = m_env->getPlayer(client_id);
1575                         if (!player)
1576                                 continue;
1577
1578                         PlayerSAO *sao = player->getPlayerSAO();
1579                         if (!sao)
1580                                 continue;
1581
1582                         // Do not send to distant clients
1583                         if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
1584                                 continue;
1585
1586                         SendSpawnParticle(client_id, player->protocol_version,
1587                                         pos, velocity, acceleration,
1588                                         expirationtime, size, collisiondetection,
1589                                         collision_removal, vertical, texture, animation, glow);
1590                 }
1591                 return;
1592         }
1593
1594         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1595
1596         pkt << pos << velocity << acceleration << expirationtime
1597                         << size << collisiondetection;
1598         pkt.putLongString(texture);
1599         pkt << vertical;
1600         pkt << collision_removal;
1601         // This is horrible but required (why are there two ways to serialize pkts?)
1602         std::ostringstream os(std::ios_base::binary);
1603         animation.serialize(os, protocol_version);
1604         pkt.putRawString(os.str());
1605         pkt << glow;
1606
1607         Send(&pkt);
1608 }
1609
1610 // Adds a ParticleSpawner on peer with peer_id
1611 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
1612         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1613         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1614         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1615         u16 attached_id, bool vertical, const std::string &texture, u32 id,
1616         const struct TileAnimationParams &animation, u8 glow)
1617 {
1618         if (peer_id == PEER_ID_INEXISTENT) {
1619                 // This sucks and should be replaced:
1620                 std::vector<session_t> clients = m_clients.getClientIDs();
1621                 for (const session_t client_id : clients) {
1622                         RemotePlayer *player = m_env->getPlayer(client_id);
1623                         if (!player)
1624                                 continue;
1625                         SendAddParticleSpawner(client_id, player->protocol_version,
1626                                         amount, spawntime, minpos, maxpos,
1627                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1628                                         minsize, maxsize, collisiondetection, collision_removal,
1629                                         attached_id, vertical, texture, id, animation, glow);
1630                 }
1631                 return;
1632         }
1633
1634         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1635
1636         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1637                         << minacc << maxacc << minexptime << maxexptime << minsize
1638                         << maxsize << collisiondetection;
1639
1640         pkt.putLongString(texture);
1641
1642         pkt << id << vertical;
1643         pkt << collision_removal;
1644         pkt << attached_id;
1645         // This is horrible but required
1646         std::ostringstream os(std::ios_base::binary);
1647         animation.serialize(os, protocol_version);
1648         pkt.putRawString(os.str());
1649         pkt << glow;
1650
1651         Send(&pkt);
1652 }
1653
1654 void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
1655 {
1656         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
1657
1658         // Ugly error in this packet
1659         pkt << id;
1660
1661         if (peer_id != PEER_ID_INEXISTENT)
1662                 Send(&pkt);
1663         else
1664                 m_clients.sendToAll(&pkt);
1665
1666 }
1667
1668 void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
1669 {
1670         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1671
1672         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1673                         << form->text << form->number << form->item << form->dir
1674                         << form->align << form->offset << form->world_pos << form->size;
1675
1676         Send(&pkt);
1677 }
1678
1679 void Server::SendHUDRemove(session_t peer_id, u32 id)
1680 {
1681         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1682         pkt << id;
1683         Send(&pkt);
1684 }
1685
1686 void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
1687 {
1688         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1689         pkt << id << (u8) stat;
1690
1691         switch (stat) {
1692                 case HUD_STAT_POS:
1693                 case HUD_STAT_SCALE:
1694                 case HUD_STAT_ALIGN:
1695                 case HUD_STAT_OFFSET:
1696                         pkt << *(v2f *) value;
1697                         break;
1698                 case HUD_STAT_NAME:
1699                 case HUD_STAT_TEXT:
1700                         pkt << *(std::string *) value;
1701                         break;
1702                 case HUD_STAT_WORLD_POS:
1703                         pkt << *(v3f *) value;
1704                         break;
1705                 case HUD_STAT_SIZE:
1706                         pkt << *(v2s32 *) value;
1707                         break;
1708                 case HUD_STAT_NUMBER:
1709                 case HUD_STAT_ITEM:
1710                 case HUD_STAT_DIR:
1711                 default:
1712                         pkt << *(u32 *) value;
1713                         break;
1714         }
1715
1716         Send(&pkt);
1717 }
1718
1719 void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
1720 {
1721         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1722
1723         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1724
1725         pkt << flags << mask;
1726
1727         Send(&pkt);
1728 }
1729
1730 void Server::SendHUDSetParam(session_t peer_id, u16 param, const std::string &value)
1731 {
1732         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1733         pkt << param << value;
1734         Send(&pkt);
1735 }
1736
1737 void Server::SendSetSky(session_t peer_id, const video::SColor &bgcolor,
1738                 const std::string &type, const std::vector<std::string> &params,
1739                 bool &clouds)
1740 {
1741         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1742         pkt << bgcolor << type << (u16) params.size();
1743
1744         for (const std::string &param : params)
1745                 pkt << param;
1746
1747         pkt << clouds;
1748
1749         Send(&pkt);
1750 }
1751
1752 void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
1753 {
1754         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1755         pkt << params.density << params.color_bright << params.color_ambient
1756                         << params.height << params.thickness << params.speed;
1757         Send(&pkt);
1758 }
1759
1760 void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
1761                 float ratio)
1762 {
1763         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1764                         1 + 2, peer_id);
1765
1766         pkt << do_override << (u16) (ratio * 65535);
1767
1768         Send(&pkt);
1769 }
1770
1771 void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
1772 {
1773         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1774         pkt << time << time_speed;
1775
1776         if (peer_id == PEER_ID_INEXISTENT) {
1777                 m_clients.sendToAll(&pkt);
1778         }
1779         else {
1780                 Send(&pkt);
1781         }
1782 }
1783
1784 void Server::SendPlayerHP(session_t peer_id)
1785 {
1786         PlayerSAO *playersao = getPlayerSAO(peer_id);
1787         // In some rare case if the player is disconnected
1788         // while Lua call l_punch, for example, this can be NULL
1789         if (!playersao)
1790                 return;
1791
1792         SendHP(peer_id, playersao->getHP());
1793         m_script->player_event(playersao,"health_changed");
1794
1795         // Send to other clients
1796         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1797         ActiveObjectMessage aom(playersao->getId(), true, str);
1798         playersao->m_messages_out.push(aom);
1799 }
1800
1801 void Server::SendPlayerBreath(PlayerSAO *sao)
1802 {
1803         assert(sao);
1804
1805         m_script->player_event(sao, "breath_changed");
1806         SendBreath(sao->getPeerID(), sao->getBreath());
1807 }
1808
1809 void Server::SendMovePlayer(session_t peer_id)
1810 {
1811         RemotePlayer *player = m_env->getPlayer(peer_id);
1812         assert(player);
1813         PlayerSAO *sao = player->getPlayerSAO();
1814         assert(sao);
1815
1816         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1817         pkt << sao->getBasePosition() << sao->getPitch() << sao->getYaw();
1818
1819         {
1820                 v3f pos = sao->getBasePosition();
1821                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1822                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1823                                 << " pitch=" << sao->getPitch()
1824                                 << " yaw=" << sao->getYaw()
1825                                 << std::endl;
1826         }
1827
1828         Send(&pkt);
1829 }
1830
1831 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1832                 f32 animation_speed)
1833 {
1834         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1835                 peer_id);
1836
1837         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1838                         << animation_frames[3] << animation_speed;
1839
1840         Send(&pkt);
1841 }
1842
1843 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1844 {
1845         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1846         pkt << first << third;
1847         Send(&pkt);
1848 }
1849
1850 void Server::SendPlayerPrivileges(session_t peer_id)
1851 {
1852         RemotePlayer *player = m_env->getPlayer(peer_id);
1853         assert(player);
1854         if(player->getPeerId() == PEER_ID_INEXISTENT)
1855                 return;
1856
1857         std::set<std::string> privs;
1858         m_script->getAuth(player->getName(), NULL, &privs);
1859
1860         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1861         pkt << (u16) privs.size();
1862
1863         for (const std::string &priv : privs) {
1864                 pkt << priv;
1865         }
1866
1867         Send(&pkt);
1868 }
1869
1870 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1871 {
1872         RemotePlayer *player = m_env->getPlayer(peer_id);
1873         assert(player);
1874         if (player->getPeerId() == PEER_ID_INEXISTENT)
1875                 return;
1876
1877         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1878         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1879         Send(&pkt);
1880 }
1881
1882 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1883 {
1884         RemotePlayer *player = m_env->getPlayer(peer_id);
1885         assert(player);
1886         if (player->getPeerId() == PEER_ID_INEXISTENT)
1887                 return;
1888
1889         NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1890         pkt << FORMSPEC_VERSION_STRING + player->formspec_prepend;
1891         Send(&pkt);
1892 }
1893
1894 u32 Server::SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas)
1895 {
1896         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1897         pkt.putRawString(datas.c_str(), datas.size());
1898         Send(&pkt);
1899         return pkt.getSize();
1900 }
1901
1902 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
1903                 bool reliable)
1904 {
1905         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1906                         datas.size(), peer_id);
1907
1908         pkt.putRawString(datas.c_str(), datas.size());
1909
1910         m_clients.send(pkt.getPeerId(),
1911                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1912                         &pkt, reliable);
1913 }
1914
1915 void Server::SendCSMFlavourLimits(session_t peer_id)
1916 {
1917         NetworkPacket pkt(TOCLIENT_CSM_FLAVOUR_LIMITS,
1918                 sizeof(m_csm_flavour_limits) + sizeof(m_csm_noderange_limit), peer_id);
1919         pkt << m_csm_flavour_limits << m_csm_noderange_limit;
1920         Send(&pkt);
1921 }
1922
1923 s32 Server::playSound(const SimpleSoundSpec &spec,
1924                 const ServerSoundParams &params)
1925 {
1926         // Find out initial position of sound
1927         bool pos_exists = false;
1928         v3f pos = params.getPos(m_env, &pos_exists);
1929         // If position is not found while it should be, cancel sound
1930         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1931                 return -1;
1932
1933         // Filter destination clients
1934         std::vector<session_t> dst_clients;
1935         if(!params.to_player.empty()) {
1936                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
1937                 if(!player){
1938                         infostream<<"Server::playSound: Player \""<<params.to_player
1939                                         <<"\" not found"<<std::endl;
1940                         return -1;
1941                 }
1942                 if (player->getPeerId() == PEER_ID_INEXISTENT) {
1943                         infostream<<"Server::playSound: Player \""<<params.to_player
1944                                         <<"\" not connected"<<std::endl;
1945                         return -1;
1946                 }
1947                 dst_clients.push_back(player->getPeerId());
1948         } else {
1949                 std::vector<session_t> clients = m_clients.getClientIDs();
1950
1951                 for (const session_t client_id : clients) {
1952                         RemotePlayer *player = m_env->getPlayer(client_id);
1953                         if (!player)
1954                                 continue;
1955
1956                         PlayerSAO *sao = player->getPlayerSAO();
1957                         if (!sao)
1958                                 continue;
1959
1960                         if (pos_exists) {
1961                                 if(sao->getBasePosition().getDistanceFrom(pos) >
1962                                                 params.max_hear_distance)
1963                                         continue;
1964                         }
1965                         dst_clients.push_back(client_id);
1966                 }
1967         }
1968
1969         if(dst_clients.empty())
1970                 return -1;
1971
1972         // Create the sound
1973         s32 id = m_next_sound_id++;
1974         // The sound will exist as a reference in m_playing_sounds
1975         m_playing_sounds[id] = ServerPlayingSound();
1976         ServerPlayingSound &psound = m_playing_sounds[id];
1977         psound.params = params;
1978         psound.spec = spec;
1979
1980         float gain = params.gain * spec.gain;
1981         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
1982         pkt << id << spec.name << gain
1983                         << (u8) params.type << pos << params.object
1984                         << params.loop << params.fade << params.pitch;
1985
1986         // Backwards compability
1987         bool play_sound = gain > 0;
1988
1989         for (const u16 dst_client : dst_clients) {
1990                 if (play_sound || m_clients.getProtocolVersion(dst_client) >= 32) {
1991                         psound.clients.insert(dst_client);
1992                         m_clients.send(dst_client, 0, &pkt, true);
1993                 }
1994         }
1995         return id;
1996 }
1997 void Server::stopSound(s32 handle)
1998 {
1999         // Get sound reference
2000         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2001                 m_playing_sounds.find(handle);
2002         if (i == m_playing_sounds.end())
2003                 return;
2004         ServerPlayingSound &psound = i->second;
2005
2006         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2007         pkt << handle;
2008
2009         for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2010                         si != psound.clients.end(); ++si) {
2011                 // Send as reliable
2012                 m_clients.send(*si, 0, &pkt, true);
2013         }
2014         // Remove sound reference
2015         m_playing_sounds.erase(i);
2016 }
2017
2018 void Server::fadeSound(s32 handle, float step, float gain)
2019 {
2020         // Get sound reference
2021         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2022                 m_playing_sounds.find(handle);
2023         if (i == m_playing_sounds.end())
2024                 return;
2025
2026         ServerPlayingSound &psound = i->second;
2027         psound.params.gain = gain;
2028
2029         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2030         pkt << handle << step << gain;
2031
2032         // Backwards compability
2033         bool play_sound = gain > 0;
2034         ServerPlayingSound compat_psound = psound;
2035         compat_psound.clients.clear();
2036
2037         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2038         compat_pkt << handle;
2039
2040         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2041                         it != psound.clients.end();) {
2042                 if (m_clients.getProtocolVersion(*it) >= 32) {
2043                         // Send as reliable
2044                         m_clients.send(*it, 0, &pkt, true);
2045                         ++it;
2046                 } else {
2047                         compat_psound.clients.insert(*it);
2048                         // Stop old sound
2049                         m_clients.send(*it, 0, &compat_pkt, true);
2050                         psound.clients.erase(it++);
2051                 }
2052         }
2053
2054         // Remove sound reference
2055         if (!play_sound || psound.clients.empty())
2056                 m_playing_sounds.erase(i);
2057
2058         if (play_sound && !compat_psound.clients.empty()) {
2059                 // Play new sound volume on older clients
2060                 playSound(compat_psound.spec, compat_psound.params);
2061         }
2062 }
2063
2064 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2065         std::vector<u16> *far_players, float far_d_nodes)
2066 {
2067         float maxd = far_d_nodes*BS;
2068         v3f p_f = intToFloat(p, BS);
2069
2070         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2071         pkt << p;
2072
2073         std::vector<session_t> clients = m_clients.getClientIDs();
2074         for (session_t client_id : clients) {
2075                 if (far_players) {
2076                         // Get player
2077                         if (RemotePlayer *player = m_env->getPlayer(client_id)) {
2078                                 PlayerSAO *sao = player->getPlayerSAO();
2079                                 if (!sao)
2080                                         continue;
2081
2082                                 // If player is far away, only set modified blocks not sent
2083                                 v3f player_pos = sao->getBasePosition();
2084                                 if (player_pos.getDistanceFrom(p_f) > maxd) {
2085                                         far_players->push_back(client_id);
2086                                         continue;
2087                                 }
2088                         }
2089                 }
2090
2091                 // Send as reliable
2092                 m_clients.send(client_id, 0, &pkt, true);
2093         }
2094 }
2095
2096 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2097                 std::vector<u16> *far_players, float far_d_nodes,
2098                 bool remove_metadata)
2099 {
2100         float maxd = far_d_nodes*BS;
2101         v3f p_f = intToFloat(p, BS);
2102
2103         std::vector<session_t> clients = m_clients.getClientIDs();
2104         for (const session_t client_id : clients) {
2105                 if (far_players) {
2106                         // Get player
2107                         if (RemotePlayer *player = m_env->getPlayer(client_id)) {
2108                                 PlayerSAO *sao = player->getPlayerSAO();
2109                                 if (!sao)
2110                                         continue;
2111
2112                                 // If player is far away, only set modified blocks not sent
2113                                 v3f player_pos = sao->getBasePosition();
2114                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2115                                         far_players->push_back(client_id);
2116                                         continue;
2117                                 }
2118                         }
2119                 }
2120
2121                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2122                 m_clients.lock();
2123                 RemoteClient* client = m_clients.lockedGetClientNoEx(client_id);
2124                 if (client) {
2125                         pkt << p << n.param0 << n.param1 << n.param2
2126                                         << (u8) (remove_metadata ? 0 : 1);
2127                 }
2128                 m_clients.unlock();
2129
2130                 // Send as reliable
2131                 if (pkt.getSize() > 0)
2132                         m_clients.send(client_id, 0, &pkt, true);
2133         }
2134 }
2135
2136 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2137                 u16 net_proto_version)
2138 {
2139         /*
2140                 Create a packet with the block in the right format
2141         */
2142
2143         std::ostringstream os(std::ios_base::binary);
2144         block->serialize(os, ver, false);
2145         block->serializeNetworkSpecific(os);
2146         std::string s = os.str();
2147
2148         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2149
2150         pkt << block->getPos();
2151         pkt.putRawString(s.c_str(), s.size());
2152         Send(&pkt);
2153 }
2154
2155 void Server::SendBlocks(float dtime)
2156 {
2157         MutexAutoLock envlock(m_env_mutex);
2158         //TODO check if one big lock could be faster then multiple small ones
2159
2160         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2161
2162         std::vector<PrioritySortedBlockTransfer> queue;
2163
2164         u32 total_sending = 0;
2165
2166         {
2167                 ScopeProfiler sp2(g_profiler, "Server: selecting blocks for sending");
2168
2169                 std::vector<session_t> clients = m_clients.getClientIDs();
2170
2171                 m_clients.lock();
2172                 for (const session_t client_id : clients) {
2173                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2174
2175                         if (!client)
2176                                 continue;
2177
2178                         total_sending += client->getSendingCount();
2179                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2180                 }
2181                 m_clients.unlock();
2182         }
2183
2184         // Sort.
2185         // Lowest priority number comes first.
2186         // Lowest is most important.
2187         std::sort(queue.begin(), queue.end());
2188
2189         m_clients.lock();
2190
2191         // Maximal total count calculation
2192         // The per-client block sends is halved with the maximal online users
2193         u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2194                 g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2195
2196         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2197                 if (total_sending >= max_blocks_to_send)
2198                         break;
2199
2200                 MapBlock *block = nullptr;
2201                 try {
2202                         block = m_env->getMap().getBlockNoCreate(block_to_send.pos);
2203                 } catch (const InvalidPositionException &e) {
2204                         continue;
2205                 }
2206
2207                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2208                                 CS_Active);
2209                 if (!client)
2210                         continue;
2211
2212                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2213                                 client->net_proto_version);
2214
2215                 client->SentBlock(block_to_send.pos);
2216                 total_sending++;
2217         }
2218         m_clients.unlock();
2219 }
2220
2221 void Server::fillMediaCache()
2222 {
2223         infostream<<"Server: Calculating media file checksums"<<std::endl;
2224
2225         // Collect all media file paths
2226         std::vector<std::string> paths;
2227         m_modmgr->getModsMediaPaths(paths);
2228         fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2229         fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2230
2231         // Collect media file information from paths into cache
2232         for (const std::string &mediapath : paths) {
2233                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2234                 for (const fs::DirListNode &dln : dirlist) {
2235                         if (dln.dir) // Ignode dirs
2236                                 continue;
2237                         std::string filename = dln.name;
2238                         // If name contains illegal characters, ignore the file
2239                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2240                                 infostream<<"Server: ignoring illegal file name: \""
2241                                                 << filename << "\"" << std::endl;
2242                                 continue;
2243                         }
2244                         // If name is not in a supported format, ignore it
2245                         const char *supported_ext[] = {
2246                                 ".png", ".jpg", ".bmp", ".tga",
2247                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2248                                 ".ogg",
2249                                 ".x", ".b3d", ".md2", ".obj",
2250                                 // Custom translation file format
2251                                 ".tr",
2252                                 NULL
2253                         };
2254                         if (removeStringEnd(filename, supported_ext).empty()){
2255                                 infostream << "Server: ignoring unsupported file extension: \""
2256                                                 << filename << "\"" << std::endl;
2257                                 continue;
2258                         }
2259                         // Ok, attempt to load the file and add to cache
2260                         std::string filepath;
2261                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2262
2263                         // Read data
2264                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2265                         if (!fis.good()) {
2266                                 errorstream << "Server::fillMediaCache(): Could not open \""
2267                                                 << filename << "\" for reading" << std::endl;
2268                                 continue;
2269                         }
2270                         std::ostringstream tmp_os(std::ios_base::binary);
2271                         bool bad = false;
2272                         for(;;) {
2273                                 char buf[1024];
2274                                 fis.read(buf, 1024);
2275                                 std::streamsize len = fis.gcount();
2276                                 tmp_os.write(buf, len);
2277                                 if (fis.eof())
2278                                         break;
2279                                 if (!fis.good()) {
2280                                         bad = true;
2281                                         break;
2282                                 }
2283                         }
2284                         if(bad) {
2285                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2286                                                 << filename << "\"" << std::endl;
2287                                 continue;
2288                         }
2289                         if(tmp_os.str().length() == 0) {
2290                                 errorstream << "Server::fillMediaCache(): Empty file \""
2291                                                 << filepath << "\"" << std::endl;
2292                                 continue;
2293                         }
2294
2295                         SHA1 sha1;
2296                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2297
2298                         unsigned char *digest = sha1.getDigest();
2299                         std::string sha1_base64 = base64_encode(digest, 20);
2300                         std::string sha1_hex = hex_encode((char*)digest, 20);
2301                         free(digest);
2302
2303                         // Put in list
2304                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2305                         verbosestream << "Server: " << sha1_hex << " is " << filename
2306                                         << std::endl;
2307                 }
2308         }
2309 }
2310
2311 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2312 {
2313         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2314                 << std::endl;
2315
2316         // Make packet
2317         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2318
2319         u16 media_sent = 0;
2320         std::string lang_suffix;
2321         lang_suffix.append(".").append(lang_code).append(".tr");
2322         for (const auto &i : m_media) {
2323                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2324                         continue;
2325                 media_sent++;
2326         }
2327
2328         pkt << media_sent;
2329
2330         for (const auto &i : m_media) {
2331                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2332                         continue;
2333                 pkt << i.first << i.second.sha1_digest;
2334         }
2335
2336         pkt << g_settings->get("remote_media");
2337         Send(&pkt);
2338 }
2339
2340 struct SendableMedia
2341 {
2342         std::string name;
2343         std::string path;
2344         std::string data;
2345
2346         SendableMedia(const std::string &name_="", const std::string &path_="",
2347                       const std::string &data_=""):
2348                 name(name_),
2349                 path(path_),
2350                 data(data_)
2351         {}
2352 };
2353
2354 void Server::sendRequestedMedia(session_t peer_id,
2355                 const std::vector<std::string> &tosend)
2356 {
2357         verbosestream<<"Server::sendRequestedMedia(): "
2358                         <<"Sending files to client"<<std::endl;
2359
2360         /* Read files */
2361
2362         // Put 5kB in one bunch (this is not accurate)
2363         u32 bytes_per_bunch = 5000;
2364
2365         std::vector< std::vector<SendableMedia> > file_bunches;
2366         file_bunches.emplace_back();
2367
2368         u32 file_size_bunch_total = 0;
2369
2370         for (const std::string &name : tosend) {
2371                 if (m_media.find(name) == m_media.end()) {
2372                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2373                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2374                         continue;
2375                 }
2376
2377                 //TODO get path + name
2378                 std::string tpath = m_media[name].path;
2379
2380                 // Read data
2381                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2382                 if(!fis.good()){
2383                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2384                                         <<tpath<<"\" for reading"<<std::endl;
2385                         continue;
2386                 }
2387                 std::ostringstream tmp_os(std::ios_base::binary);
2388                 bool bad = false;
2389                 for(;;) {
2390                         char buf[1024];
2391                         fis.read(buf, 1024);
2392                         std::streamsize len = fis.gcount();
2393                         tmp_os.write(buf, len);
2394                         file_size_bunch_total += len;
2395                         if(fis.eof())
2396                                 break;
2397                         if(!fis.good()) {
2398                                 bad = true;
2399                                 break;
2400                         }
2401                 }
2402                 if (bad) {
2403                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2404                                         <<name<<"\""<<std::endl;
2405                         continue;
2406                 }
2407                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2408                                 <<tname<<"\""<<std::endl;*/
2409                 // Put in list
2410                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2411
2412                 // Start next bunch if got enough data
2413                 if(file_size_bunch_total >= bytes_per_bunch) {
2414                         file_bunches.emplace_back();
2415                         file_size_bunch_total = 0;
2416                 }
2417
2418         }
2419
2420         /* Create and send packets */
2421
2422         u16 num_bunches = file_bunches.size();
2423         for (u16 i = 0; i < num_bunches; i++) {
2424                 /*
2425                         u16 command
2426                         u16 total number of texture bunches
2427                         u16 index of this bunch
2428                         u32 number of files in this bunch
2429                         for each file {
2430                                 u16 length of name
2431                                 string name
2432                                 u32 length of data
2433                                 data
2434                         }
2435                 */
2436
2437                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2438                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2439
2440                 for (const SendableMedia &j : file_bunches[i]) {
2441                         pkt << j.name;
2442                         pkt.putLongString(j.data);
2443                 }
2444
2445                 verbosestream << "Server::sendRequestedMedia(): bunch "
2446                                 << i << "/" << num_bunches
2447                                 << " files=" << file_bunches[i].size()
2448                                 << " size="  << pkt.getSize() << std::endl;
2449                 Send(&pkt);
2450         }
2451 }
2452
2453 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
2454 {
2455         if(m_detached_inventories.count(name) == 0) {
2456                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2457                 return;
2458         }
2459         Inventory *inv = m_detached_inventories[name];
2460         std::ostringstream os(std::ios_base::binary);
2461
2462         os << serializeString(name);
2463         inv->serialize(os);
2464
2465         // Make data buffer
2466         std::string s = os.str();
2467
2468         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2469         pkt.putRawString(s.c_str(), s.size());
2470
2471         const std::string &check = m_detached_inventories_player[name];
2472         if (peer_id == PEER_ID_INEXISTENT) {
2473                 if (check.empty())
2474                         return m_clients.sendToAll(&pkt);
2475                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2476                 if (p)
2477                         m_clients.send(p->getPeerId(), 0, &pkt, true);
2478         } else {
2479                 if (check.empty() || getPlayerName(peer_id) == check)
2480                         Send(&pkt);
2481         }
2482 }
2483
2484 void Server::sendDetachedInventories(session_t peer_id)
2485 {
2486         for (const auto &detached_inventory : m_detached_inventories) {
2487                 const std::string &name = detached_inventory.first;
2488                 //Inventory *inv = i->second;
2489                 sendDetachedInventory(name, peer_id);
2490         }
2491 }
2492
2493 /*
2494         Something random
2495 */
2496
2497 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2498 {
2499         PlayerSAO *playersao = getPlayerSAO(peer_id);
2500         // In some rare cases this can be NULL -- if the player is disconnected
2501         // when a Lua function modifies l_punch, for example
2502         if (!playersao)
2503                 return;
2504
2505         infostream << "Server::DiePlayer(): Player "
2506                         << playersao->getPlayer()->getName()
2507                         << " dies" << std::endl;
2508
2509         playersao->setHP(0, reason);
2510
2511         // Trigger scripted stuff
2512         m_script->on_dieplayer(playersao, reason);
2513
2514         SendPlayerHP(peer_id);
2515         SendDeathscreen(peer_id, false, v3f(0,0,0));
2516 }
2517
2518 void Server::RespawnPlayer(session_t peer_id)
2519 {
2520         PlayerSAO *playersao = getPlayerSAO(peer_id);
2521         assert(playersao);
2522
2523         infostream << "Server::RespawnPlayer(): Player "
2524                         << playersao->getPlayer()->getName()
2525                         << " respawns" << std::endl;
2526
2527         playersao->setHP(playersao->accessObjectProperties()->hp_max,
2528                         PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2529         playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2530
2531         bool repositioned = m_script->on_respawnplayer(playersao);
2532         if (!repositioned) {
2533                 // setPos will send the new position to client
2534                 playersao->setPos(findSpawnPos());
2535         }
2536
2537         SendPlayerHP(peer_id);
2538 }
2539
2540
2541 void Server::DenySudoAccess(session_t peer_id)
2542 {
2543         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2544         Send(&pkt);
2545 }
2546
2547
2548 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2549                 const std::string &str_reason, bool reconnect)
2550 {
2551         SendAccessDenied(peer_id, reason, str_reason, reconnect);
2552
2553         m_clients.event(peer_id, CSE_SetDenied);
2554         DisconnectPeer(peer_id);
2555 }
2556
2557
2558 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2559                 const std::string &custom_reason)
2560 {
2561         SendAccessDenied(peer_id, reason, custom_reason);
2562         m_clients.event(peer_id, CSE_SetDenied);
2563         DisconnectPeer(peer_id);
2564 }
2565
2566 // 13/03/15: remove this function when protocol version 25 will become
2567 // the minimum version for MT users, maybe in 1 year
2568 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2569 {
2570         SendAccessDenied_Legacy(peer_id, reason);
2571         m_clients.event(peer_id, CSE_SetDenied);
2572         DisconnectPeer(peer_id);
2573 }
2574
2575 void Server::DisconnectPeer(session_t peer_id)
2576 {
2577         m_modchannel_mgr->leaveAllChannels(peer_id);
2578         m_con->DisconnectPeer(peer_id);
2579 }
2580
2581 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2582 {
2583         if (!forSudoMode) {
2584                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2585
2586                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2587
2588                 // Right now, the auth mechs don't change between login and sudo mode.
2589                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2590                 client->allowed_sudo_mechs = sudo_auth_mechs;
2591
2592                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2593                                 << g_settings->getFloat("dedicated_server_step")
2594                                 << sudo_auth_mechs;
2595
2596                 Send(&resp_pkt);
2597                 m_clients.event(peer_id, CSE_AuthAccept);
2598         } else {
2599                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2600
2601                 // We only support SRP right now
2602                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2603
2604                 resp_pkt << sudo_auth_mechs;
2605                 Send(&resp_pkt);
2606                 m_clients.event(peer_id, CSE_SudoSuccess);
2607         }
2608 }
2609
2610 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2611 {
2612         std::wstring message;
2613         {
2614                 /*
2615                         Clear references to playing sounds
2616                 */
2617                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2618                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2619                         ServerPlayingSound &psound = i->second;
2620                         psound.clients.erase(peer_id);
2621                         if (psound.clients.empty())
2622                                 m_playing_sounds.erase(i++);
2623                         else
2624                                 ++i;
2625                 }
2626
2627                 // clear formspec info so the next client can't abuse the current state
2628                 m_formspec_state_data.erase(peer_id);
2629
2630                 RemotePlayer *player = m_env->getPlayer(peer_id);
2631
2632                 /* Run scripts and remove from environment */
2633                 if (player) {
2634                         PlayerSAO *playersao = player->getPlayerSAO();
2635                         assert(playersao);
2636
2637                         // inform connected clients
2638                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2639                         // (u16) 1 + std::string represents a vector serialization representation
2640                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
2641                         m_clients.sendToAll(&notice);
2642                         // run scripts
2643                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2644
2645                         playersao->disconnected();
2646                 }
2647
2648                 /*
2649                         Print out action
2650                 */
2651                 {
2652                         if (player && reason != CDR_DENY) {
2653                                 std::ostringstream os(std::ios_base::binary);
2654                                 std::vector<session_t> clients = m_clients.getClientIDs();
2655
2656                                 for (const session_t client_id : clients) {
2657                                         // Get player
2658                                         RemotePlayer *player = m_env->getPlayer(client_id);
2659                                         if (!player)
2660                                                 continue;
2661
2662                                         // Get name of player
2663                                         os << player->getName() << " ";
2664                                 }
2665
2666                                 std::string name = player->getName();
2667                                 actionstream << name << " "
2668                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2669                                                 << " List of players: " << os.str() << std::endl;
2670                                 if (m_admin_chat)
2671                                         m_admin_chat->outgoing_queue.push_back(
2672                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2673                         }
2674                 }
2675                 {
2676                         MutexAutoLock env_lock(m_env_mutex);
2677                         m_clients.DeleteClient(peer_id);
2678                 }
2679         }
2680
2681         // Send leave chat message to all remaining clients
2682         if (!message.empty()) {
2683                 SendChatMessage(PEER_ID_INEXISTENT,
2684                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2685         }
2686 }
2687
2688 void Server::UpdateCrafting(RemotePlayer *player)
2689 {
2690         // Get a preview for crafting
2691         ItemStack preview;
2692         InventoryLocation loc;
2693         loc.setPlayer(player->getName());
2694         std::vector<ItemStack> output_replacements;
2695         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2696         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2697                         (&player->inventory)->getList("craft"), loc);
2698
2699         // Put the new preview in
2700         InventoryList *plist = player->inventory.getList("craftpreview");
2701         sanity_check(plist);
2702         sanity_check(plist->getSize() >= 1);
2703         plist->changeItem(0, preview);
2704 }
2705
2706 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2707 {
2708         if (evt->type == CET_NICK_ADD) {
2709                 // The terminal informed us of its nick choice
2710                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2711                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2712                         errorstream << "You haven't set up an account." << std::endl
2713                                 << "Please log in using the client as '"
2714                                 << m_admin_nick << "' with a secure password." << std::endl
2715                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2716                                 << "and everybody can claim the user account instead of you," << std::endl
2717                                 << "giving them full control over this server." << std::endl;
2718                 }
2719         } else {
2720                 assert(evt->type == CET_CHAT);
2721                 handleAdminChat((ChatEventChat *)evt);
2722         }
2723 }
2724
2725 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2726         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2727 {
2728         // If something goes wrong, this player is to blame
2729         RollbackScopeActor rollback_scope(m_rollback,
2730                 std::string("player:") + name);
2731
2732         if (g_settings->getBool("strip_color_codes"))
2733                 wmessage = unescape_enriched(wmessage);
2734
2735         if (player) {
2736                 switch (player->canSendChatMessage()) {
2737                         case RPLAYER_CHATRESULT_FLOODING: {
2738                                 std::wstringstream ws;
2739                                 ws << L"You cannot send more messages. You are limited to "
2740                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2741                                    << L" messages per 10 seconds.";
2742                                 return ws.str();
2743                         }
2744                         case RPLAYER_CHATRESULT_KICK:
2745                                 DenyAccess_Legacy(player->getPeerId(),
2746                                                 L"You have been kicked due to message flooding.");
2747                                 return L"";
2748                         case RPLAYER_CHATRESULT_OK:
2749                                 break;
2750                         default:
2751                                 FATAL_ERROR("Unhandled chat filtering result found.");
2752                 }
2753         }
2754
2755         if (m_max_chatmessage_length > 0
2756                         && wmessage.length() > m_max_chatmessage_length) {
2757                 return L"Your message exceed the maximum chat message limit set on the server. "
2758                                 L"It was refused. Send a shorter message";
2759         }
2760
2761         // Run script hook, exit if script ate the chat message
2762         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2763                 return L"";
2764
2765         // Line to send
2766         std::wstring line;
2767         // Whether to send line to the player that sent the message, or to all players
2768         bool broadcast_line = true;
2769
2770         if (check_shout_priv && !checkPriv(name, "shout")) {
2771                 line += L"-!- You don't have permission to shout.";
2772                 broadcast_line = false;
2773         } else {
2774                 line += L"<";
2775                 line += wname;
2776                 line += L"> ";
2777                 line += wmessage;
2778         }
2779
2780         /*
2781                 Tell calling method to send the message to sender
2782         */
2783         if (!broadcast_line)
2784                 return line;
2785
2786         /*
2787                 Send the message to others
2788         */
2789         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2790
2791         std::vector<session_t> clients = m_clients.getClientIDs();
2792
2793         /*
2794                 Send the message back to the inital sender
2795                 if they are using protocol version >= 29
2796         */
2797
2798         session_t peer_id_to_avoid_sending =
2799                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
2800
2801         if (player && player->protocol_version >= 29)
2802                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2803
2804         for (u16 cid : clients) {
2805                 if (cid != peer_id_to_avoid_sending)
2806                         SendChatMessage(cid, ChatMessage(line));
2807         }
2808         return L"";
2809 }
2810
2811 void Server::handleAdminChat(const ChatEventChat *evt)
2812 {
2813         std::string name = evt->nick;
2814         std::wstring wname = utf8_to_wide(name);
2815         std::wstring wmessage = evt->evt_msg;
2816
2817         std::wstring answer = handleChat(name, wname, wmessage);
2818
2819         // If asked to send answer to sender
2820         if (!answer.empty()) {
2821                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2822         }
2823 }
2824
2825 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
2826 {
2827         RemoteClient *client = getClientNoEx(peer_id,state_min);
2828         if(!client)
2829                 throw ClientNotFoundException("Client not found");
2830
2831         return client;
2832 }
2833 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
2834 {
2835         return m_clients.getClientNoEx(peer_id, state_min);
2836 }
2837
2838 std::string Server::getPlayerName(session_t peer_id)
2839 {
2840         RemotePlayer *player = m_env->getPlayer(peer_id);
2841         if (!player)
2842                 return "[id="+itos(peer_id)+"]";
2843         return player->getName();
2844 }
2845
2846 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
2847 {
2848         RemotePlayer *player = m_env->getPlayer(peer_id);
2849         if (!player)
2850                 return NULL;
2851         return player->getPlayerSAO();
2852 }
2853
2854 std::wstring Server::getStatusString()
2855 {
2856         std::wostringstream os(std::ios_base::binary);
2857         os<<L"# Server: ";
2858         // Version
2859         os<<L"version="<<narrow_to_wide(g_version_string);
2860         // Uptime
2861         os<<L", uptime="<<m_uptime.get();
2862         // Max lag estimate
2863         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2864         // Information about clients
2865         bool first = true;
2866         os<<L", clients={";
2867         std::vector<session_t> clients = m_clients.getClientIDs();
2868         for (session_t client_id : clients) {
2869                 // Get player
2870                 RemotePlayer *player = m_env->getPlayer(client_id);
2871                 // Get name of player
2872                 std::wstring name = L"unknown";
2873                 if (player)
2874                         name = narrow_to_wide(player->getName());
2875                 // Add name to information string
2876                 if(!first)
2877                         os << L", ";
2878                 else
2879                         first = false;
2880                 os << name;
2881         }
2882         os << L"}";
2883
2884         if (!((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
2885                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2886
2887         if (!g_settings->get("motd").empty())
2888                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2889         return os.str();
2890 }
2891
2892 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2893 {
2894         std::set<std::string> privs;
2895         m_script->getAuth(name, NULL, &privs);
2896         return privs;
2897 }
2898
2899 bool Server::checkPriv(const std::string &name, const std::string &priv)
2900 {
2901         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2902         return (privs.count(priv) != 0);
2903 }
2904
2905 void Server::reportPrivsModified(const std::string &name)
2906 {
2907         if (name.empty()) {
2908                 std::vector<session_t> clients = m_clients.getClientIDs();
2909                 for (const session_t client_id : clients) {
2910                         RemotePlayer *player = m_env->getPlayer(client_id);
2911                         reportPrivsModified(player->getName());
2912                 }
2913         } else {
2914                 RemotePlayer *player = m_env->getPlayer(name.c_str());
2915                 if (!player)
2916                         return;
2917                 SendPlayerPrivileges(player->getPeerId());
2918                 PlayerSAO *sao = player->getPlayerSAO();
2919                 if(!sao)
2920                         return;
2921                 sao->updatePrivileges(
2922                                 getPlayerEffectivePrivs(name),
2923                                 isSingleplayer());
2924         }
2925 }
2926
2927 void Server::reportInventoryFormspecModified(const std::string &name)
2928 {
2929         RemotePlayer *player = m_env->getPlayer(name.c_str());
2930         if (!player)
2931                 return;
2932         SendPlayerInventoryFormspec(player->getPeerId());
2933 }
2934
2935 void Server::reportFormspecPrependModified(const std::string &name)
2936 {
2937         RemotePlayer *player = m_env->getPlayer(name.c_str());
2938         if (!player)
2939                 return;
2940         SendPlayerFormspecPrepend(player->getPeerId());
2941 }
2942
2943 void Server::setIpBanned(const std::string &ip, const std::string &name)
2944 {
2945         m_banmanager->add(ip, name);
2946 }
2947
2948 void Server::unsetIpBanned(const std::string &ip_or_name)
2949 {
2950         m_banmanager->remove(ip_or_name);
2951 }
2952
2953 std::string Server::getBanDescription(const std::string &ip_or_name)
2954 {
2955         return m_banmanager->getBanDescription(ip_or_name);
2956 }
2957
2958 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2959 {
2960         // m_env will be NULL if the server is initializing
2961         if (!m_env)
2962                 return;
2963
2964         if (m_admin_nick == name && !m_admin_nick.empty()) {
2965                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
2966         }
2967
2968         RemotePlayer *player = m_env->getPlayer(name);
2969         if (!player) {
2970                 return;
2971         }
2972
2973         if (player->getPeerId() == PEER_ID_INEXISTENT)
2974                 return;
2975
2976         SendChatMessage(player->getPeerId(), ChatMessage(msg));
2977 }
2978
2979 bool Server::showFormspec(const char *playername, const std::string &formspec,
2980         const std::string &formname)
2981 {
2982         // m_env will be NULL if the server is initializing
2983         if (!m_env)
2984                 return false;
2985
2986         RemotePlayer *player = m_env->getPlayer(playername);
2987         if (!player)
2988                 return false;
2989
2990         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
2991         return true;
2992 }
2993
2994 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
2995 {
2996         if (!player)
2997                 return -1;
2998
2999         u32 id = player->addHud(form);
3000
3001         SendHUDAdd(player->getPeerId(), id, form);
3002
3003         return id;
3004 }
3005
3006 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3007         if (!player)
3008                 return false;
3009
3010         HudElement* todel = player->removeHud(id);
3011
3012         if (!todel)
3013                 return false;
3014
3015         delete todel;
3016
3017         SendHUDRemove(player->getPeerId(), id);
3018         return true;
3019 }
3020
3021 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3022 {
3023         if (!player)
3024                 return false;
3025
3026         SendHUDChange(player->getPeerId(), id, stat, data);
3027         return true;
3028 }
3029
3030 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3031 {
3032         if (!player)
3033                 return false;
3034
3035         SendHUDSetFlags(player->getPeerId(), flags, mask);
3036         player->hud_flags &= ~mask;
3037         player->hud_flags |= flags;
3038
3039         PlayerSAO* playersao = player->getPlayerSAO();
3040
3041         if (!playersao)
3042                 return false;
3043
3044         m_script->player_event(playersao, "hud_changed");
3045         return true;
3046 }
3047
3048 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3049 {
3050         if (!player)
3051                 return false;
3052
3053         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3054                 return false;
3055
3056         player->setHotbarItemcount(hotbar_itemcount);
3057         std::ostringstream os(std::ios::binary);
3058         writeS32(os, hotbar_itemcount);
3059         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3060         return true;
3061 }
3062
3063 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3064 {
3065         if (!player)
3066                 return;
3067
3068         player->setHotbarImage(name);
3069         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3070 }
3071
3072 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3073 {
3074         if (!player)
3075                 return;
3076
3077         player->setHotbarSelectedImage(name);
3078         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3079 }
3080
3081 Address Server::getPeerAddress(session_t peer_id)
3082 {
3083         return m_con->GetPeerAddress(peer_id);
3084 }
3085
3086 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3087                 v2s32 animation_frames[4], f32 frame_speed)
3088 {
3089         sanity_check(player);
3090         player->setLocalAnimations(animation_frames, frame_speed);
3091         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3092 }
3093
3094 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3095 {
3096         sanity_check(player);
3097         player->eye_offset_first = first;
3098         player->eye_offset_third = third;
3099         SendEyeOffset(player->getPeerId(), first, third);
3100 }
3101
3102 void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3103         const std::string &type, const std::vector<std::string> &params,
3104         bool &clouds)
3105 {
3106         sanity_check(player);
3107         player->setSky(bgcolor, type, params, clouds);
3108         SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
3109 }
3110
3111 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3112 {
3113         sanity_check(player);
3114         player->setCloudParams(params);
3115         SendCloudParams(player->getPeerId(), params);
3116 }
3117
3118 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3119         float ratio)
3120 {
3121         if (!player)
3122                 return false;
3123
3124         player->overrideDayNightRatio(do_override, ratio);
3125         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3126         return true;
3127 }
3128
3129 void Server::notifyPlayers(const std::wstring &msg)
3130 {
3131         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3132 }
3133
3134 void Server::spawnParticle(const std::string &playername, v3f pos,
3135         v3f velocity, v3f acceleration,
3136         float expirationtime, float size, bool
3137         collisiondetection, bool collision_removal,
3138         bool vertical, const std::string &texture,
3139         const struct TileAnimationParams &animation, u8 glow)
3140 {
3141         // m_env will be NULL if the server is initializing
3142         if (!m_env)
3143                 return;
3144
3145         session_t peer_id = PEER_ID_INEXISTENT;
3146         u16 proto_ver = 0;
3147         if (!playername.empty()) {
3148                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3149                 if (!player)
3150                         return;
3151                 peer_id = player->getPeerId();
3152                 proto_ver = player->protocol_version;
3153         }
3154
3155         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3156                         expirationtime, size, collisiondetection,
3157                         collision_removal, vertical, texture, animation, glow);
3158 }
3159
3160 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3161         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3162         float minexptime, float maxexptime, float minsize, float maxsize,
3163         bool collisiondetection, bool collision_removal,
3164         ServerActiveObject *attached, bool vertical, const std::string &texture,
3165         const std::string &playername, const struct TileAnimationParams &animation,
3166         u8 glow)
3167 {
3168         // m_env will be NULL if the server is initializing
3169         if (!m_env)
3170                 return -1;
3171
3172         session_t peer_id = PEER_ID_INEXISTENT;
3173         u16 proto_ver = 0;
3174         if (!playername.empty()) {
3175                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3176                 if (!player)
3177                         return -1;
3178                 peer_id = player->getPeerId();
3179                 proto_ver = player->protocol_version;
3180         }
3181
3182         u16 attached_id = attached ? attached->getId() : 0;
3183
3184         u32 id;
3185         if (attached_id == 0)
3186                 id = m_env->addParticleSpawner(spawntime);
3187         else
3188                 id = m_env->addParticleSpawner(spawntime, attached_id);
3189
3190         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3191                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3192                 minexptime, maxexptime, minsize, maxsize,
3193                 collisiondetection, collision_removal, attached_id, vertical,
3194                 texture, id, animation, glow);
3195
3196         return id;
3197 }
3198
3199 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3200 {
3201         // m_env will be NULL if the server is initializing
3202         if (!m_env)
3203                 throw ServerError("Can't delete particle spawners during initialisation!");
3204
3205         session_t peer_id = PEER_ID_INEXISTENT;
3206         if (!playername.empty()) {
3207                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3208                 if (!player)
3209                         return;
3210                 peer_id = player->getPeerId();
3211         }
3212
3213         m_env->deleteParticleSpawner(id);
3214         SendDeleteParticleSpawner(peer_id, id);
3215 }
3216
3217 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3218 {
3219         if(m_detached_inventories.count(name) > 0){
3220                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3221                 delete m_detached_inventories[name];
3222         } else {
3223                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3224         }
3225         Inventory *inv = new Inventory(m_itemdef);
3226         sanity_check(inv);
3227         m_detached_inventories[name] = inv;
3228         m_detached_inventories_player[name] = player;
3229         //TODO find a better way to do this
3230         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3231         return inv;
3232 }
3233
3234 // actions: time-reversed list
3235 // Return value: success/failure
3236 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3237                 std::list<std::string> *log)
3238 {
3239         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3240         ServerMap *map = (ServerMap*)(&m_env->getMap());
3241
3242         // Fail if no actions to handle
3243         if(actions.empty()){
3244                 log->push_back("Nothing to do.");
3245                 return false;
3246         }
3247
3248         int num_tried = 0;
3249         int num_failed = 0;
3250
3251         for (const RollbackAction &action : actions) {
3252                 num_tried++;
3253                 bool success = action.applyRevert(map, this, this);
3254                 if(!success){
3255                         num_failed++;
3256                         std::ostringstream os;
3257                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3258                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3259                         if (log)
3260                                 log->push_back(os.str());
3261                 }else{
3262                         std::ostringstream os;
3263                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3264                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3265                         if (log)
3266                                 log->push_back(os.str());
3267                 }
3268         }
3269
3270         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3271                         <<" failed"<<std::endl;
3272
3273         // Call it done if less than half failed
3274         return num_failed <= num_tried/2;
3275 }
3276
3277 // IGameDef interface
3278 // Under envlock
3279 IItemDefManager *Server::getItemDefManager()
3280 {
3281         return m_itemdef;
3282 }
3283
3284 const NodeDefManager *Server::getNodeDefManager()
3285 {
3286         return m_nodedef;
3287 }
3288
3289 ICraftDefManager *Server::getCraftDefManager()
3290 {
3291         return m_craftdef;
3292 }
3293
3294 u16 Server::allocateUnknownNodeId(const std::string &name)
3295 {
3296         return m_nodedef->allocateDummy(name);
3297 }
3298
3299 MtEventManager *Server::getEventManager()
3300 {
3301         return m_event;
3302 }
3303
3304 IWritableItemDefManager *Server::getWritableItemDefManager()
3305 {
3306         return m_itemdef;
3307 }
3308
3309 NodeDefManager *Server::getWritableNodeDefManager()
3310 {
3311         return m_nodedef;
3312 }
3313
3314 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3315 {
3316         return m_craftdef;
3317 }
3318
3319 const std::vector<ModSpec> & Server::getMods() const
3320 {
3321         return m_modmgr->getMods();
3322 }
3323
3324 const ModSpec *Server::getModSpec(const std::string &modname) const
3325 {
3326         return m_modmgr->getModSpec(modname);
3327 }
3328
3329 void Server::getModNames(std::vector<std::string> &modlist)
3330 {
3331         m_modmgr->getModNames(modlist);
3332 }
3333
3334 std::string Server::getBuiltinLuaPath()
3335 {
3336         return porting::path_share + DIR_DELIM + "builtin";
3337 }
3338
3339 std::string Server::getModStoragePath() const
3340 {
3341         return m_path_world + DIR_DELIM + "mod_storage";
3342 }
3343
3344 v3f Server::findSpawnPos()
3345 {
3346         ServerMap &map = m_env->getServerMap();
3347         v3f nodeposf;
3348         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3349                 return nodeposf * BS;
3350         }
3351
3352         bool is_good = false;
3353         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3354         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3355
3356         // Try to find a good place a few times
3357         for(s32 i = 0; i < 4000 && !is_good; i++) {
3358                 s32 range = MYMIN(1 + i, range_max);
3359                 // We're going to try to throw the player to this position
3360                 v2s16 nodepos2d = v2s16(
3361                         -range + (myrand() % (range * 2)),
3362                         -range + (myrand() % (range * 2)));
3363
3364                 // Get spawn level at point
3365                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3366                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3367                 // the mapgen to signify an unsuitable spawn position
3368                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3369                         continue;
3370
3371                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3372
3373                 s32 air_count = 0;
3374                 for (s32 i = 0; i < 10; i++) {
3375                         v3s16 blockpos = getNodeBlockPos(nodepos);
3376                         map.emergeBlock(blockpos, true);
3377                         content_t c = map.getNodeNoEx(nodepos).getContent();
3378                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3379                                 air_count++;
3380                                 if (air_count >= 2) {
3381                                         nodeposf = intToFloat(nodepos, BS);
3382                                         // Don't spawn the player outside map boundaries
3383                                         if (objectpos_over_limit(nodeposf))
3384                                                 continue;
3385                                         is_good = true;
3386                                         break;
3387                                 }
3388                         }
3389                         nodepos.Y++;
3390                 }
3391         }
3392
3393         return nodeposf;
3394 }
3395
3396 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3397 {
3398         m_shutdown_timer = delay;
3399         m_shutdown_msg = msg;
3400         m_shutdown_ask_reconnect = reconnect;
3401
3402         if (delay == 0.0f) {
3403         // No delay, shutdown immediately
3404                 m_shutdown_requested = true;
3405                 // only print to the infostream, a chat message saying
3406                 // "Server Shutting Down" is sent when the server destructs.
3407                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3408         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3409         // Negative delay, cancel shutdown if requested
3410                 m_shutdown_timer = 0.0f;
3411                 m_shutdown_msg = "";
3412                 m_shutdown_ask_reconnect = false;
3413                 m_shutdown_requested = false;
3414                 std::wstringstream ws;
3415
3416                 ws << L"*** Server shutdown canceled.";
3417
3418                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3419                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3420         } else if (delay > 0.0f) {
3421         // Positive delay, tell the clients when the server will shut down
3422                 std::wstringstream ws;
3423
3424                 ws << L"*** Server shutting down in "
3425                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3426                                 << ".";
3427
3428                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3429                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3430         }
3431 }
3432
3433 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3434 {
3435         /*
3436                 Try to get an existing player
3437         */
3438         RemotePlayer *player = m_env->getPlayer(name);
3439
3440         // If player is already connected, cancel
3441         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3442                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3443                 return NULL;
3444         }
3445
3446         /*
3447                 If player with the wanted peer_id already exists, cancel.
3448         */
3449         if (m_env->getPlayer(peer_id)) {
3450                 infostream<<"emergePlayer(): Player with wrong name but same"
3451                                 " peer_id already exists"<<std::endl;
3452                 return NULL;
3453         }
3454
3455         if (!player) {
3456                 player = new RemotePlayer(name, idef());
3457         }
3458
3459         bool newplayer = false;
3460
3461         // Load player
3462         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3463
3464         // Complete init with server parts
3465         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3466         player->protocol_version = proto_version;
3467
3468         /* Run scripts */
3469         if (newplayer) {
3470                 m_script->on_newplayer(playersao);
3471         }
3472
3473         return playersao;
3474 }
3475
3476 bool Server::registerModStorage(ModMetadata *storage)
3477 {
3478         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3479                 errorstream << "Unable to register same mod storage twice. Storage name: "
3480                                 << storage->getModName() << std::endl;
3481                 return false;
3482         }
3483
3484         m_mod_storages[storage->getModName()] = storage;
3485         return true;
3486 }
3487
3488 void Server::unregisterModStorage(const std::string &name)
3489 {
3490         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3491         if (it != m_mod_storages.end()) {
3492                 // Save unconditionaly on unregistration
3493                 it->second->save(getModStoragePath());
3494                 m_mod_storages.erase(name);
3495         }
3496 }
3497
3498 void dedicated_server_loop(Server &server, bool &kill)
3499 {
3500         verbosestream<<"dedicated_server_loop()"<<std::endl;
3501
3502         IntervalLimiter m_profiler_interval;
3503
3504         static thread_local const float steplen =
3505                         g_settings->getFloat("dedicated_server_step");
3506         static thread_local const float profiler_print_interval =
3507                         g_settings->getFloat("profiler_print_interval");
3508
3509         for(;;) {
3510                 // This is kind of a hack but can be done like this
3511                 // because server.step() is very light
3512                 {
3513                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3514                         sleep_ms((int)(steplen*1000.0));
3515                 }
3516                 server.step(steplen);
3517
3518                 if (server.getShutdownRequested() || kill)
3519                         break;
3520
3521                 /*
3522                         Profiler
3523                 */
3524                 if (profiler_print_interval != 0) {
3525                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3526                         {
3527                                 infostream<<"Profiler:"<<std::endl;
3528                                 g_profiler->print(infostream);
3529                                 g_profiler->clear();
3530                         }
3531                 }
3532         }
3533
3534         infostream << "Dedicated server quitting" << std::endl;
3535 #if USE_CURL
3536         if (g_settings->getBool("server_announce"))
3537                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3538                         server.m_bind_addr.getPort());
3539 #endif
3540 }
3541
3542 /*
3543  * Mod channels
3544  */
3545
3546
3547 bool Server::joinModChannel(const std::string &channel)
3548 {
3549         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3550                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3551 }
3552
3553 bool Server::leaveModChannel(const std::string &channel)
3554 {
3555         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3556 }
3557
3558 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3559 {
3560         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3561                 return false;
3562
3563         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3564         return true;
3565 }
3566
3567 ModChannel* Server::getModChannel(const std::string &channel)
3568 {
3569         return m_modchannel_mgr->getModChannel(channel);
3570 }
3571
3572 void Server::broadcastModChannelMessage(const std::string &channel,
3573                 const std::string &message, session_t from_peer)
3574 {
3575         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3576         if (peers.empty())
3577                 return;
3578
3579         if (message.size() > STRING_MAX_LEN) {
3580                 warningstream << "ModChannel message too long, dropping before sending "
3581                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3582                                 << channel << ")" << std::endl;
3583                 return;
3584         }
3585
3586         std::string sender;
3587         if (from_peer != PEER_ID_SERVER) {
3588                 sender = getPlayerName(from_peer);
3589         }
3590
3591         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3592                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3593         resp_pkt << channel << sender << message;
3594         for (session_t peer_id : peers) {
3595                 // Ignore sender
3596                 if (peer_id == from_peer)
3597                         continue;
3598
3599                 Send(peer_id, &resp_pkt);
3600         }
3601
3602         if (from_peer != PEER_ID_SERVER) {
3603                 m_script->on_modchannel_message(channel, sender, message);
3604         }
3605 }