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