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