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