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