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