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