Fix randomly rejected form field submits (#8091)
[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                 //but make sure there wasn't another one open in meantime
1581                 const auto it = m_formspec_state_data.find(peer_id);
1582                 if (it != m_formspec_state_data.end() && it->second == formname) {
1583                         m_formspec_state_data.erase(peer_id);
1584                 }
1585                 pkt.putLongString("");
1586         } else {
1587                 m_formspec_state_data[peer_id] = formname;
1588                 pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1589         }
1590         pkt << formname;
1591
1592         Send(&pkt);
1593 }
1594
1595 // Spawns a particle on peer with peer_id
1596 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
1597                                 v3f pos, v3f velocity, v3f acceleration,
1598                                 float expirationtime, float size, bool collisiondetection,
1599                                 bool collision_removal, bool object_collision,
1600                                 bool vertical, const std::string &texture,
1601                                 const struct TileAnimationParams &animation, u8 glow)
1602 {
1603         static thread_local const float radius =
1604                         g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1605
1606         if (peer_id == PEER_ID_INEXISTENT) {
1607                 std::vector<session_t> clients = m_clients.getClientIDs();
1608
1609                 for (const session_t client_id : clients) {
1610                         RemotePlayer *player = m_env->getPlayer(client_id);
1611                         if (!player)
1612                                 continue;
1613
1614                         PlayerSAO *sao = player->getPlayerSAO();
1615                         if (!sao)
1616                                 continue;
1617
1618                         // Do not send to distant clients
1619                         if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
1620                                 continue;
1621
1622                         SendSpawnParticle(client_id, player->protocol_version,
1623                                         pos, velocity, acceleration,
1624                                         expirationtime, size, collisiondetection, collision_removal,
1625                                         object_collision, vertical, texture, animation, glow);
1626                 }
1627                 return;
1628         }
1629
1630         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1631
1632         pkt << pos << velocity << acceleration << expirationtime
1633                         << size << collisiondetection;
1634         pkt.putLongString(texture);
1635         pkt << vertical;
1636         pkt << collision_removal;
1637         // This is horrible but required (why are there two ways to serialize pkts?)
1638         std::ostringstream os(std::ios_base::binary);
1639         animation.serialize(os, protocol_version);
1640         pkt.putRawString(os.str());
1641         pkt << glow;
1642         pkt << object_collision;
1643
1644         Send(&pkt);
1645 }
1646
1647 // Adds a ParticleSpawner on peer with peer_id
1648 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
1649         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1650         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1651         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1652         bool object_collision, u16 attached_id, bool vertical, const std::string &texture, u32 id,
1653         const struct TileAnimationParams &animation, u8 glow)
1654 {
1655         if (peer_id == PEER_ID_INEXISTENT) {
1656                 // This sucks and should be replaced:
1657                 std::vector<session_t> clients = m_clients.getClientIDs();
1658                 for (const session_t client_id : clients) {
1659                         RemotePlayer *player = m_env->getPlayer(client_id);
1660                         if (!player)
1661                                 continue;
1662                         SendAddParticleSpawner(client_id, player->protocol_version,
1663                                         amount, spawntime, minpos, maxpos,
1664                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1665                                         minsize, maxsize, collisiondetection, collision_removal,
1666                                         object_collision, attached_id, vertical, texture, id,
1667                                         animation, glow);
1668                 }
1669                 return;
1670         }
1671
1672         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1673
1674         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1675                         << minacc << maxacc << minexptime << maxexptime << minsize
1676                         << maxsize << collisiondetection;
1677
1678         pkt.putLongString(texture);
1679
1680         pkt << id << vertical;
1681         pkt << collision_removal;
1682         pkt << attached_id;
1683         // This is horrible but required
1684         std::ostringstream os(std::ios_base::binary);
1685         animation.serialize(os, protocol_version);
1686         pkt.putRawString(os.str());
1687         pkt << glow;
1688         pkt << object_collision;
1689
1690         Send(&pkt);
1691 }
1692
1693 void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
1694 {
1695         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
1696
1697         // Ugly error in this packet
1698         pkt << id;
1699
1700         if (peer_id != PEER_ID_INEXISTENT)
1701                 Send(&pkt);
1702         else
1703                 m_clients.sendToAll(&pkt);
1704
1705 }
1706
1707 void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
1708 {
1709         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1710
1711         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1712                         << form->text << form->number << form->item << form->dir
1713                         << form->align << form->offset << form->world_pos << form->size;
1714
1715         Send(&pkt);
1716 }
1717
1718 void Server::SendHUDRemove(session_t peer_id, u32 id)
1719 {
1720         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1721         pkt << id;
1722         Send(&pkt);
1723 }
1724
1725 void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
1726 {
1727         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1728         pkt << id << (u8) stat;
1729
1730         switch (stat) {
1731                 case HUD_STAT_POS:
1732                 case HUD_STAT_SCALE:
1733                 case HUD_STAT_ALIGN:
1734                 case HUD_STAT_OFFSET:
1735                         pkt << *(v2f *) value;
1736                         break;
1737                 case HUD_STAT_NAME:
1738                 case HUD_STAT_TEXT:
1739                         pkt << *(std::string *) value;
1740                         break;
1741                 case HUD_STAT_WORLD_POS:
1742                         pkt << *(v3f *) value;
1743                         break;
1744                 case HUD_STAT_SIZE:
1745                         pkt << *(v2s32 *) value;
1746                         break;
1747                 case HUD_STAT_NUMBER:
1748                 case HUD_STAT_ITEM:
1749                 case HUD_STAT_DIR:
1750                 default:
1751                         pkt << *(u32 *) value;
1752                         break;
1753         }
1754
1755         Send(&pkt);
1756 }
1757
1758 void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
1759 {
1760         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1761
1762         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1763
1764         pkt << flags << mask;
1765
1766         Send(&pkt);
1767 }
1768
1769 void Server::SendHUDSetParam(session_t peer_id, u16 param, const std::string &value)
1770 {
1771         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1772         pkt << param << value;
1773         Send(&pkt);
1774 }
1775
1776 void Server::SendSetSky(session_t peer_id, const video::SColor &bgcolor,
1777                 const std::string &type, const std::vector<std::string> &params,
1778                 bool &clouds)
1779 {
1780         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1781         pkt << bgcolor << type << (u16) params.size();
1782
1783         for (const std::string &param : params)
1784                 pkt << param;
1785
1786         pkt << clouds;
1787
1788         Send(&pkt);
1789 }
1790
1791 void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
1792 {
1793         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1794         pkt << params.density << params.color_bright << params.color_ambient
1795                         << params.height << params.thickness << params.speed;
1796         Send(&pkt);
1797 }
1798
1799 void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
1800                 float ratio)
1801 {
1802         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1803                         1 + 2, peer_id);
1804
1805         pkt << do_override << (u16) (ratio * 65535);
1806
1807         Send(&pkt);
1808 }
1809
1810 void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
1811 {
1812         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1813         pkt << time << time_speed;
1814
1815         if (peer_id == PEER_ID_INEXISTENT) {
1816                 m_clients.sendToAll(&pkt);
1817         }
1818         else {
1819                 Send(&pkt);
1820         }
1821 }
1822
1823 void Server::SendPlayerHP(session_t peer_id)
1824 {
1825         PlayerSAO *playersao = getPlayerSAO(peer_id);
1826         // In some rare case if the player is disconnected
1827         // while Lua call l_punch, for example, this can be NULL
1828         if (!playersao)
1829                 return;
1830
1831         SendHP(peer_id, playersao->getHP());
1832         m_script->player_event(playersao,"health_changed");
1833
1834         // Send to other clients
1835         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1836         ActiveObjectMessage aom(playersao->getId(), true, str);
1837         playersao->m_messages_out.push(aom);
1838 }
1839
1840 void Server::SendPlayerBreath(PlayerSAO *sao)
1841 {
1842         assert(sao);
1843
1844         m_script->player_event(sao, "breath_changed");
1845         SendBreath(sao->getPeerID(), sao->getBreath());
1846 }
1847
1848 void Server::SendMovePlayer(session_t peer_id)
1849 {
1850         RemotePlayer *player = m_env->getPlayer(peer_id);
1851         assert(player);
1852         PlayerSAO *sao = player->getPlayerSAO();
1853         assert(sao);
1854
1855         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1856         pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
1857
1858         {
1859                 v3f pos = sao->getBasePosition();
1860                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1861                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1862                                 << " pitch=" << sao->getLookPitch()
1863                                 << " yaw=" << sao->getRotation().Y
1864                                 << std::endl;
1865         }
1866
1867         Send(&pkt);
1868 }
1869
1870 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1871                 f32 animation_speed)
1872 {
1873         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1874                 peer_id);
1875
1876         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1877                         << animation_frames[3] << animation_speed;
1878
1879         Send(&pkt);
1880 }
1881
1882 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1883 {
1884         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1885         pkt << first << third;
1886         Send(&pkt);
1887 }
1888
1889 void Server::SendPlayerPrivileges(session_t peer_id)
1890 {
1891         RemotePlayer *player = m_env->getPlayer(peer_id);
1892         assert(player);
1893         if(player->getPeerId() == PEER_ID_INEXISTENT)
1894                 return;
1895
1896         std::set<std::string> privs;
1897         m_script->getAuth(player->getName(), NULL, &privs);
1898
1899         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1900         pkt << (u16) privs.size();
1901
1902         for (const std::string &priv : privs) {
1903                 pkt << priv;
1904         }
1905
1906         Send(&pkt);
1907 }
1908
1909 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1910 {
1911         RemotePlayer *player = m_env->getPlayer(peer_id);
1912         assert(player);
1913         if (player->getPeerId() == PEER_ID_INEXISTENT)
1914                 return;
1915
1916         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1917         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1918         Send(&pkt);
1919 }
1920
1921 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1922 {
1923         RemotePlayer *player = m_env->getPlayer(peer_id);
1924         assert(player);
1925         if (player->getPeerId() == PEER_ID_INEXISTENT)
1926                 return;
1927
1928         NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1929         pkt << FORMSPEC_VERSION_STRING + player->formspec_prepend;
1930         Send(&pkt);
1931 }
1932
1933 u32 Server::SendActiveObjectRemoveAdd(session_t peer_id, const std::string &datas)
1934 {
1935         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1936         pkt.putRawString(datas.c_str(), datas.size());
1937         Send(&pkt);
1938         return pkt.getSize();
1939 }
1940
1941 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
1942                 bool reliable)
1943 {
1944         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1945                         datas.size(), peer_id);
1946
1947         pkt.putRawString(datas.c_str(), datas.size());
1948
1949         m_clients.send(pkt.getPeerId(),
1950                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1951                         &pkt, reliable);
1952 }
1953
1954 void Server::SendCSMRestrictionFlags(session_t peer_id)
1955 {
1956         NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
1957                 sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
1958         pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
1959         Send(&pkt);
1960 }
1961
1962 s32 Server::playSound(const SimpleSoundSpec &spec,
1963                 const ServerSoundParams &params)
1964 {
1965         // Find out initial position of sound
1966         bool pos_exists = false;
1967         v3f pos = params.getPos(m_env, &pos_exists);
1968         // If position is not found while it should be, cancel sound
1969         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1970                 return -1;
1971
1972         // Filter destination clients
1973         std::vector<session_t> dst_clients;
1974         if(!params.to_player.empty()) {
1975                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
1976                 if(!player){
1977                         infostream<<"Server::playSound: Player \""<<params.to_player
1978                                         <<"\" not found"<<std::endl;
1979                         return -1;
1980                 }
1981                 if (player->getPeerId() == PEER_ID_INEXISTENT) {
1982                         infostream<<"Server::playSound: Player \""<<params.to_player
1983                                         <<"\" not connected"<<std::endl;
1984                         return -1;
1985                 }
1986                 dst_clients.push_back(player->getPeerId());
1987         } else {
1988                 std::vector<session_t> clients = m_clients.getClientIDs();
1989
1990                 for (const session_t client_id : clients) {
1991                         RemotePlayer *player = m_env->getPlayer(client_id);
1992                         if (!player)
1993                                 continue;
1994
1995                         PlayerSAO *sao = player->getPlayerSAO();
1996                         if (!sao)
1997                                 continue;
1998
1999                         if (pos_exists) {
2000                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2001                                                 params.max_hear_distance)
2002                                         continue;
2003                         }
2004                         dst_clients.push_back(client_id);
2005                 }
2006         }
2007
2008         if(dst_clients.empty())
2009                 return -1;
2010
2011         // Create the sound
2012         s32 id = m_next_sound_id++;
2013         // The sound will exist as a reference in m_playing_sounds
2014         m_playing_sounds[id] = ServerPlayingSound();
2015         ServerPlayingSound &psound = m_playing_sounds[id];
2016         psound.params = params;
2017         psound.spec = spec;
2018
2019         float gain = params.gain * spec.gain;
2020         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2021         pkt << id << spec.name << gain
2022                         << (u8) params.type << pos << params.object
2023                         << params.loop << params.fade << params.pitch;
2024
2025         // Backwards compability
2026         bool play_sound = gain > 0;
2027
2028         for (const u16 dst_client : dst_clients) {
2029                 if (play_sound || m_clients.getProtocolVersion(dst_client) >= 32) {
2030                         psound.clients.insert(dst_client);
2031                         m_clients.send(dst_client, 0, &pkt, true);
2032                 }
2033         }
2034         return id;
2035 }
2036 void Server::stopSound(s32 handle)
2037 {
2038         // Get sound reference
2039         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2040                 m_playing_sounds.find(handle);
2041         if (i == m_playing_sounds.end())
2042                 return;
2043         ServerPlayingSound &psound = i->second;
2044
2045         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2046         pkt << handle;
2047
2048         for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2049                         si != psound.clients.end(); ++si) {
2050                 // Send as reliable
2051                 m_clients.send(*si, 0, &pkt, true);
2052         }
2053         // Remove sound reference
2054         m_playing_sounds.erase(i);
2055 }
2056
2057 void Server::fadeSound(s32 handle, float step, float gain)
2058 {
2059         // Get sound reference
2060         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2061                 m_playing_sounds.find(handle);
2062         if (i == m_playing_sounds.end())
2063                 return;
2064
2065         ServerPlayingSound &psound = i->second;
2066         psound.params.gain = gain;
2067
2068         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2069         pkt << handle << step << gain;
2070
2071         // Backwards compability
2072         bool play_sound = gain > 0;
2073         ServerPlayingSound compat_psound = psound;
2074         compat_psound.clients.clear();
2075
2076         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2077         compat_pkt << handle;
2078
2079         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2080                         it != psound.clients.end();) {
2081                 if (m_clients.getProtocolVersion(*it) >= 32) {
2082                         // Send as reliable
2083                         m_clients.send(*it, 0, &pkt, true);
2084                         ++it;
2085                 } else {
2086                         compat_psound.clients.insert(*it);
2087                         // Stop old sound
2088                         m_clients.send(*it, 0, &compat_pkt, true);
2089                         psound.clients.erase(it++);
2090                 }
2091         }
2092
2093         // Remove sound reference
2094         if (!play_sound || psound.clients.empty())
2095                 m_playing_sounds.erase(i);
2096
2097         if (play_sound && !compat_psound.clients.empty()) {
2098                 // Play new sound volume on older clients
2099                 playSound(compat_psound.spec, compat_psound.params);
2100         }
2101 }
2102
2103 void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
2104                 float far_d_nodes)
2105 {
2106         float maxd = far_d_nodes * BS;
2107         v3f p_f = intToFloat(p, BS);
2108         v3s16 block_pos = getNodeBlockPos(p);
2109
2110         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2111         pkt << p;
2112
2113         std::vector<session_t> clients = m_clients.getClientIDs();
2114         m_clients.lock();
2115
2116         for (session_t client_id : clients) {
2117                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2118                 if (!client)
2119                         continue;
2120
2121                 RemotePlayer *player = m_env->getPlayer(client_id);
2122                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2123
2124                 // If player is far away, only set modified blocks not sent
2125                 if (!client->isBlockSent(block_pos) || (sao &&
2126                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2127                         if (far_players)
2128                                 far_players->emplace(client_id);
2129                         else
2130                                 client->SetBlockNotSent(block_pos);
2131                         continue;
2132                 }
2133
2134                 // Send as reliable
2135                 m_clients.send(client_id, 0, &pkt, true);
2136         }
2137
2138         m_clients.unlock();
2139 }
2140
2141 void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
2142                 float far_d_nodes, bool remove_metadata)
2143 {
2144         float maxd = far_d_nodes * BS;
2145         v3f p_f = intToFloat(p, BS);
2146         v3s16 block_pos = getNodeBlockPos(p);
2147
2148         NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2149         pkt << p << n.param0 << n.param1 << n.param2
2150                         << (u8) (remove_metadata ? 0 : 1);
2151
2152         std::vector<session_t> clients = m_clients.getClientIDs();
2153         m_clients.lock();
2154
2155         for (session_t client_id : clients) {
2156                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2157                 if (!client)
2158                         continue;
2159
2160                 RemotePlayer *player = m_env->getPlayer(client_id);
2161                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2162
2163                 // If player is far away, only set modified blocks not sent
2164                 if (!client->isBlockSent(block_pos) || (sao &&
2165                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2166                         if (far_players)
2167                                 far_players->emplace(client_id);
2168                         else
2169                                 client->SetBlockNotSent(block_pos);
2170                         continue;
2171                 }
2172
2173                 // Send as reliable
2174                 m_clients.send(client_id, 0, &pkt, true);
2175         }
2176
2177         m_clients.unlock();
2178 }
2179
2180 void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes)
2181 {
2182         float maxd = far_d_nodes * BS;
2183         NodeMetadataList meta_updates_list(false);
2184         std::vector<session_t> clients = m_clients.getClientIDs();
2185
2186         m_clients.lock();
2187
2188         for (session_t i : clients) {
2189                 RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2190                 if (!client)
2191                         continue;
2192
2193                 ServerActiveObject *player = m_env->getActiveObject(i);
2194                 v3f player_pos = player ? player->getBasePosition() : v3f();
2195
2196                 for (const v3s16 &pos : meta_updates) {
2197                         NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
2198
2199                         if (!meta)
2200                                 continue;
2201
2202                         v3s16 block_pos = getNodeBlockPos(pos);
2203                         if (!client->isBlockSent(block_pos) || (player &&
2204                                         player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) {
2205                                 client->SetBlockNotSent(block_pos);
2206                                 continue;
2207                         }
2208
2209                         // Add the change to send list
2210                         meta_updates_list.set(pos, meta);
2211                 }
2212                 if (meta_updates_list.size() == 0)
2213                         continue;
2214
2215                 // Send the meta changes
2216                 std::ostringstream os(std::ios::binary);
2217                 meta_updates_list.serialize(os, client->net_proto_version, false, true);
2218                 std::ostringstream oss(std::ios::binary);
2219                 compressZlib(os.str(), oss);
2220
2221                 NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0);
2222                 pkt.putLongString(oss.str());
2223                 m_clients.send(i, 0, &pkt, true);
2224
2225                 meta_updates_list.clear();
2226         }
2227
2228         m_clients.unlock();
2229 }
2230
2231 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2232                 u16 net_proto_version)
2233 {
2234         /*
2235                 Create a packet with the block in the right format
2236         */
2237
2238         std::ostringstream os(std::ios_base::binary);
2239         block->serialize(os, ver, false);
2240         block->serializeNetworkSpecific(os);
2241         std::string s = os.str();
2242
2243         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2244
2245         pkt << block->getPos();
2246         pkt.putRawString(s.c_str(), s.size());
2247         Send(&pkt);
2248 }
2249
2250 void Server::SendBlocks(float dtime)
2251 {
2252         MutexAutoLock envlock(m_env_mutex);
2253         //TODO check if one big lock could be faster then multiple small ones
2254
2255         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2256
2257         std::vector<PrioritySortedBlockTransfer> queue;
2258
2259         u32 total_sending = 0;
2260
2261         {
2262                 ScopeProfiler sp2(g_profiler, "Server: selecting blocks for sending");
2263
2264                 std::vector<session_t> clients = m_clients.getClientIDs();
2265
2266                 m_clients.lock();
2267                 for (const session_t client_id : clients) {
2268                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2269
2270                         if (!client)
2271                                 continue;
2272
2273                         total_sending += client->getSendingCount();
2274                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2275                 }
2276                 m_clients.unlock();
2277         }
2278
2279         // Sort.
2280         // Lowest priority number comes first.
2281         // Lowest is most important.
2282         std::sort(queue.begin(), queue.end());
2283
2284         m_clients.lock();
2285
2286         // Maximal total count calculation
2287         // The per-client block sends is halved with the maximal online users
2288         u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2289                 g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2290
2291         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2292                 if (total_sending >= max_blocks_to_send)
2293                         break;
2294
2295                 MapBlock *block = nullptr;
2296                 try {
2297                         block = m_env->getMap().getBlockNoCreate(block_to_send.pos);
2298                 } catch (const InvalidPositionException &e) {
2299                         continue;
2300                 }
2301
2302                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2303                                 CS_Active);
2304                 if (!client)
2305                         continue;
2306
2307                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2308                                 client->net_proto_version);
2309
2310                 client->SentBlock(block_to_send.pos);
2311                 total_sending++;
2312         }
2313         m_clients.unlock();
2314 }
2315
2316 void Server::fillMediaCache()
2317 {
2318         infostream<<"Server: Calculating media file checksums"<<std::endl;
2319
2320         // Collect all media file paths
2321         std::vector<std::string> paths;
2322         m_modmgr->getModsMediaPaths(paths);
2323         fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2324         fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2325
2326         // Collect media file information from paths into cache
2327         for (const std::string &mediapath : paths) {
2328                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2329                 for (const fs::DirListNode &dln : dirlist) {
2330                         if (dln.dir) // Ignode dirs
2331                                 continue;
2332                         std::string filename = dln.name;
2333                         // If name contains illegal characters, ignore the file
2334                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2335                                 infostream<<"Server: ignoring illegal file name: \""
2336                                                 << filename << "\"" << std::endl;
2337                                 continue;
2338                         }
2339                         // If name is not in a supported format, ignore it
2340                         const char *supported_ext[] = {
2341                                 ".png", ".jpg", ".bmp", ".tga",
2342                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2343                                 ".ogg",
2344                                 ".x", ".b3d", ".md2", ".obj",
2345                                 // Custom translation file format
2346                                 ".tr",
2347                                 NULL
2348                         };
2349                         if (removeStringEnd(filename, supported_ext).empty()){
2350                                 infostream << "Server: ignoring unsupported file extension: \""
2351                                                 << filename << "\"" << std::endl;
2352                                 continue;
2353                         }
2354                         // Ok, attempt to load the file and add to cache
2355                         std::string filepath;
2356                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2357
2358                         // Read data
2359                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2360                         if (!fis.good()) {
2361                                 errorstream << "Server::fillMediaCache(): Could not open \""
2362                                                 << filename << "\" for reading" << std::endl;
2363                                 continue;
2364                         }
2365                         std::ostringstream tmp_os(std::ios_base::binary);
2366                         bool bad = false;
2367                         for(;;) {
2368                                 char buf[1024];
2369                                 fis.read(buf, 1024);
2370                                 std::streamsize len = fis.gcount();
2371                                 tmp_os.write(buf, len);
2372                                 if (fis.eof())
2373                                         break;
2374                                 if (!fis.good()) {
2375                                         bad = true;
2376                                         break;
2377                                 }
2378                         }
2379                         if(bad) {
2380                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2381                                                 << filename << "\"" << std::endl;
2382                                 continue;
2383                         }
2384                         if(tmp_os.str().length() == 0) {
2385                                 errorstream << "Server::fillMediaCache(): Empty file \""
2386                                                 << filepath << "\"" << std::endl;
2387                                 continue;
2388                         }
2389
2390                         SHA1 sha1;
2391                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2392
2393                         unsigned char *digest = sha1.getDigest();
2394                         std::string sha1_base64 = base64_encode(digest, 20);
2395                         std::string sha1_hex = hex_encode((char*)digest, 20);
2396                         free(digest);
2397
2398                         // Put in list
2399                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2400                         verbosestream << "Server: " << sha1_hex << " is " << filename
2401                                         << std::endl;
2402                 }
2403         }
2404 }
2405
2406 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2407 {
2408         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2409                 << std::endl;
2410
2411         // Make packet
2412         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2413
2414         u16 media_sent = 0;
2415         std::string lang_suffix;
2416         lang_suffix.append(".").append(lang_code).append(".tr");
2417         for (const auto &i : m_media) {
2418                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2419                         continue;
2420                 media_sent++;
2421         }
2422
2423         pkt << media_sent;
2424
2425         for (const auto &i : m_media) {
2426                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2427                         continue;
2428                 pkt << i.first << i.second.sha1_digest;
2429         }
2430
2431         pkt << g_settings->get("remote_media");
2432         Send(&pkt);
2433 }
2434
2435 struct SendableMedia
2436 {
2437         std::string name;
2438         std::string path;
2439         std::string data;
2440
2441         SendableMedia(const std::string &name_="", const std::string &path_="",
2442                       const std::string &data_=""):
2443                 name(name_),
2444                 path(path_),
2445                 data(data_)
2446         {}
2447 };
2448
2449 void Server::sendRequestedMedia(session_t peer_id,
2450                 const std::vector<std::string> &tosend)
2451 {
2452         verbosestream<<"Server::sendRequestedMedia(): "
2453                         <<"Sending files to client"<<std::endl;
2454
2455         /* Read files */
2456
2457         // Put 5kB in one bunch (this is not accurate)
2458         u32 bytes_per_bunch = 5000;
2459
2460         std::vector< std::vector<SendableMedia> > file_bunches;
2461         file_bunches.emplace_back();
2462
2463         u32 file_size_bunch_total = 0;
2464
2465         for (const std::string &name : tosend) {
2466                 if (m_media.find(name) == m_media.end()) {
2467                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2468                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2469                         continue;
2470                 }
2471
2472                 //TODO get path + name
2473                 std::string tpath = m_media[name].path;
2474
2475                 // Read data
2476                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2477                 if(!fis.good()){
2478                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2479                                         <<tpath<<"\" for reading"<<std::endl;
2480                         continue;
2481                 }
2482                 std::ostringstream tmp_os(std::ios_base::binary);
2483                 bool bad = false;
2484                 for(;;) {
2485                         char buf[1024];
2486                         fis.read(buf, 1024);
2487                         std::streamsize len = fis.gcount();
2488                         tmp_os.write(buf, len);
2489                         file_size_bunch_total += len;
2490                         if(fis.eof())
2491                                 break;
2492                         if(!fis.good()) {
2493                                 bad = true;
2494                                 break;
2495                         }
2496                 }
2497                 if (bad) {
2498                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2499                                         <<name<<"\""<<std::endl;
2500                         continue;
2501                 }
2502                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2503                                 <<tname<<"\""<<std::endl;*/
2504                 // Put in list
2505                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2506
2507                 // Start next bunch if got enough data
2508                 if(file_size_bunch_total >= bytes_per_bunch) {
2509                         file_bunches.emplace_back();
2510                         file_size_bunch_total = 0;
2511                 }
2512
2513         }
2514
2515         /* Create and send packets */
2516
2517         u16 num_bunches = file_bunches.size();
2518         for (u16 i = 0; i < num_bunches; i++) {
2519                 /*
2520                         u16 command
2521                         u16 total number of texture bunches
2522                         u16 index of this bunch
2523                         u32 number of files in this bunch
2524                         for each file {
2525                                 u16 length of name
2526                                 string name
2527                                 u32 length of data
2528                                 data
2529                         }
2530                 */
2531
2532                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2533                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2534
2535                 for (const SendableMedia &j : file_bunches[i]) {
2536                         pkt << j.name;
2537                         pkt.putLongString(j.data);
2538                 }
2539
2540                 verbosestream << "Server::sendRequestedMedia(): bunch "
2541                                 << i << "/" << num_bunches
2542                                 << " files=" << file_bunches[i].size()
2543                                 << " size="  << pkt.getSize() << std::endl;
2544                 Send(&pkt);
2545         }
2546 }
2547
2548 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
2549 {
2550         const auto &inv_it = m_detached_inventories.find(name);
2551         const auto &player_it = m_detached_inventories_player.find(name);
2552
2553         if (player_it == m_detached_inventories_player.end() ||
2554                         player_it->second.empty()) {
2555                 // OK. Send to everyone
2556         } else {
2557                 RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
2558                 if (!p)
2559                         return; // Player is offline
2560
2561                 if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
2562                         return; // Caller requested send to a different player, so don't send.
2563
2564                 peer_id = p->getPeerId();
2565         }
2566
2567         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2568         pkt << name;
2569
2570         if (inv_it == m_detached_inventories.end()) {
2571                 pkt << false; // Remove inventory
2572         } else {
2573                 pkt << true; // Update inventory
2574
2575                 // Serialization & NetworkPacket isn't a love story
2576                 std::ostringstream os(std::ios_base::binary);
2577                 inv_it->second->serialize(os);
2578                 pkt << os.str();
2579         }
2580
2581         if (peer_id == PEER_ID_INEXISTENT)
2582                 m_clients.sendToAll(&pkt);
2583         else
2584                 Send(&pkt);
2585 }
2586
2587 void Server::sendDetachedInventories(session_t peer_id)
2588 {
2589         for (const auto &detached_inventory : m_detached_inventories) {
2590                 const std::string &name = detached_inventory.first;
2591                 //Inventory *inv = i->second;
2592                 sendDetachedInventory(name, peer_id);
2593         }
2594 }
2595
2596 /*
2597         Something random
2598 */
2599
2600 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2601 {
2602         PlayerSAO *playersao = getPlayerSAO(peer_id);
2603         // In some rare cases this can be NULL -- if the player is disconnected
2604         // when a Lua function modifies l_punch, for example
2605         if (!playersao)
2606                 return;
2607
2608         infostream << "Server::DiePlayer(): Player "
2609                         << playersao->getPlayer()->getName()
2610                         << " dies" << std::endl;
2611
2612         playersao->setHP(0, reason);
2613         playersao->clearParentAttachment();
2614
2615         // Trigger scripted stuff
2616         m_script->on_dieplayer(playersao, reason);
2617
2618         SendPlayerHP(peer_id);
2619         SendDeathscreen(peer_id, false, v3f(0,0,0));
2620 }
2621
2622 void Server::RespawnPlayer(session_t peer_id)
2623 {
2624         PlayerSAO *playersao = getPlayerSAO(peer_id);
2625         assert(playersao);
2626
2627         infostream << "Server::RespawnPlayer(): Player "
2628                         << playersao->getPlayer()->getName()
2629                         << " respawns" << std::endl;
2630
2631         playersao->setHP(playersao->accessObjectProperties()->hp_max,
2632                         PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2633         playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2634
2635         bool repositioned = m_script->on_respawnplayer(playersao);
2636         if (!repositioned) {
2637                 // setPos will send the new position to client
2638                 playersao->setPos(findSpawnPos());
2639         }
2640
2641         SendPlayerHP(peer_id);
2642 }
2643
2644
2645 void Server::DenySudoAccess(session_t peer_id)
2646 {
2647         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2648         Send(&pkt);
2649 }
2650
2651
2652 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2653                 const std::string &str_reason, bool reconnect)
2654 {
2655         SendAccessDenied(peer_id, reason, str_reason, reconnect);
2656
2657         m_clients.event(peer_id, CSE_SetDenied);
2658         DisconnectPeer(peer_id);
2659 }
2660
2661
2662 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2663                 const std::string &custom_reason)
2664 {
2665         SendAccessDenied(peer_id, reason, custom_reason);
2666         m_clients.event(peer_id, CSE_SetDenied);
2667         DisconnectPeer(peer_id);
2668 }
2669
2670 // 13/03/15: remove this function when protocol version 25 will become
2671 // the minimum version for MT users, maybe in 1 year
2672 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2673 {
2674         SendAccessDenied_Legacy(peer_id, reason);
2675         m_clients.event(peer_id, CSE_SetDenied);
2676         DisconnectPeer(peer_id);
2677 }
2678
2679 void Server::DisconnectPeer(session_t peer_id)
2680 {
2681         m_modchannel_mgr->leaveAllChannels(peer_id);
2682         m_con->DisconnectPeer(peer_id);
2683 }
2684
2685 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2686 {
2687         if (!forSudoMode) {
2688                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2689
2690                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2691
2692                 // Right now, the auth mechs don't change between login and sudo mode.
2693                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2694                 client->allowed_sudo_mechs = sudo_auth_mechs;
2695
2696                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2697                                 << g_settings->getFloat("dedicated_server_step")
2698                                 << sudo_auth_mechs;
2699
2700                 Send(&resp_pkt);
2701                 m_clients.event(peer_id, CSE_AuthAccept);
2702         } else {
2703                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2704
2705                 // We only support SRP right now
2706                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2707
2708                 resp_pkt << sudo_auth_mechs;
2709                 Send(&resp_pkt);
2710                 m_clients.event(peer_id, CSE_SudoSuccess);
2711         }
2712 }
2713
2714 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2715 {
2716         std::wstring message;
2717         {
2718                 /*
2719                         Clear references to playing sounds
2720                 */
2721                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2722                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2723                         ServerPlayingSound &psound = i->second;
2724                         psound.clients.erase(peer_id);
2725                         if (psound.clients.empty())
2726                                 m_playing_sounds.erase(i++);
2727                         else
2728                                 ++i;
2729                 }
2730
2731                 // clear formspec info so the next client can't abuse the current state
2732                 m_formspec_state_data.erase(peer_id);
2733
2734                 RemotePlayer *player = m_env->getPlayer(peer_id);
2735
2736                 /* Run scripts and remove from environment */
2737                 if (player) {
2738                         PlayerSAO *playersao = player->getPlayerSAO();
2739                         assert(playersao);
2740
2741                         playersao->clearChildAttachments();
2742                         playersao->clearParentAttachment();
2743
2744                         // inform connected clients
2745                         const std::string &player_name = player->getName();
2746                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2747                         // (u16) 1 + std::string represents a vector serialization representation
2748                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
2749                         m_clients.sendToAll(&notice);
2750                         // run scripts
2751                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2752
2753                         playersao->disconnected();
2754                 }
2755
2756                 /*
2757                         Print out action
2758                 */
2759                 {
2760                         if (player && reason != CDR_DENY) {
2761                                 std::ostringstream os(std::ios_base::binary);
2762                                 std::vector<session_t> clients = m_clients.getClientIDs();
2763
2764                                 for (const session_t client_id : clients) {
2765                                         // Get player
2766                                         RemotePlayer *player = m_env->getPlayer(client_id);
2767                                         if (!player)
2768                                                 continue;
2769
2770                                         // Get name of player
2771                                         os << player->getName() << " ";
2772                                 }
2773
2774                                 std::string name = player->getName();
2775                                 actionstream << name << " "
2776                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2777                                                 << " List of players: " << os.str() << std::endl;
2778                                 if (m_admin_chat)
2779                                         m_admin_chat->outgoing_queue.push_back(
2780                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2781                         }
2782                 }
2783                 {
2784                         MutexAutoLock env_lock(m_env_mutex);
2785                         m_clients.DeleteClient(peer_id);
2786                 }
2787         }
2788
2789         // Send leave chat message to all remaining clients
2790         if (!message.empty()) {
2791                 SendChatMessage(PEER_ID_INEXISTENT,
2792                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2793         }
2794 }
2795
2796 void Server::UpdateCrafting(RemotePlayer *player)
2797 {
2798         InventoryList *clist = player->inventory.getList("craft");
2799         if (!clist || clist->getSize() == 0)
2800                 return;
2801
2802         // Get a preview for crafting
2803         ItemStack preview;
2804         InventoryLocation loc;
2805         loc.setPlayer(player->getName());
2806         std::vector<ItemStack> output_replacements;
2807         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2808         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2809                         clist, loc);
2810
2811         InventoryList *plist = player->inventory.getList("craftpreview");
2812         if (plist && plist->getSize() >= 1) {
2813                 // Put the new preview in
2814                 plist->changeItem(0, preview);
2815         }
2816 }
2817
2818 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2819 {
2820         if (evt->type == CET_NICK_ADD) {
2821                 // The terminal informed us of its nick choice
2822                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2823                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2824                         errorstream << "You haven't set up an account." << std::endl
2825                                 << "Please log in using the client as '"
2826                                 << m_admin_nick << "' with a secure password." << std::endl
2827                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2828                                 << "and everybody can claim the user account instead of you," << std::endl
2829                                 << "giving them full control over this server." << std::endl;
2830                 }
2831         } else {
2832                 assert(evt->type == CET_CHAT);
2833                 handleAdminChat((ChatEventChat *)evt);
2834         }
2835 }
2836
2837 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2838         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2839 {
2840         // If something goes wrong, this player is to blame
2841         RollbackScopeActor rollback_scope(m_rollback,
2842                 std::string("player:") + name);
2843
2844         if (g_settings->getBool("strip_color_codes"))
2845                 wmessage = unescape_enriched(wmessage);
2846
2847         if (player) {
2848                 switch (player->canSendChatMessage()) {
2849                         case RPLAYER_CHATRESULT_FLOODING: {
2850                                 std::wstringstream ws;
2851                                 ws << L"You cannot send more messages. You are limited to "
2852                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2853                                    << L" messages per 10 seconds.";
2854                                 return ws.str();
2855                         }
2856                         case RPLAYER_CHATRESULT_KICK:
2857                                 DenyAccess_Legacy(player->getPeerId(),
2858                                                 L"You have been kicked due to message flooding.");
2859                                 return L"";
2860                         case RPLAYER_CHATRESULT_OK:
2861                                 break;
2862                         default:
2863                                 FATAL_ERROR("Unhandled chat filtering result found.");
2864                 }
2865         }
2866
2867         if (m_max_chatmessage_length > 0
2868                         && wmessage.length() > m_max_chatmessage_length) {
2869                 return L"Your message exceed the maximum chat message limit set on the server. "
2870                                 L"It was refused. Send a shorter message";
2871         }
2872
2873         // Run script hook, exit if script ate the chat message
2874         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2875                 return L"";
2876
2877         // Line to send
2878         std::wstring line;
2879         // Whether to send line to the player that sent the message, or to all players
2880         bool broadcast_line = true;
2881
2882         if (check_shout_priv && !checkPriv(name, "shout")) {
2883                 line += L"-!- You don't have permission to shout.";
2884                 broadcast_line = false;
2885         } else {
2886                 line += L"<";
2887                 line += wname;
2888                 line += L"> ";
2889                 line += wmessage;
2890         }
2891
2892         /*
2893                 Tell calling method to send the message to sender
2894         */
2895         if (!broadcast_line)
2896                 return line;
2897
2898         /*
2899                 Send the message to others
2900         */
2901         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2902
2903         std::vector<session_t> clients = m_clients.getClientIDs();
2904
2905         /*
2906                 Send the message back to the inital sender
2907                 if they are using protocol version >= 29
2908         */
2909
2910         session_t peer_id_to_avoid_sending =
2911                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
2912
2913         if (player && player->protocol_version >= 29)
2914                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2915
2916         for (u16 cid : clients) {
2917                 if (cid != peer_id_to_avoid_sending)
2918                         SendChatMessage(cid, ChatMessage(line));
2919         }
2920         return L"";
2921 }
2922
2923 void Server::handleAdminChat(const ChatEventChat *evt)
2924 {
2925         std::string name = evt->nick;
2926         std::wstring wname = utf8_to_wide(name);
2927         std::wstring wmessage = evt->evt_msg;
2928
2929         std::wstring answer = handleChat(name, wname, wmessage);
2930
2931         // If asked to send answer to sender
2932         if (!answer.empty()) {
2933                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2934         }
2935 }
2936
2937 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
2938 {
2939         RemoteClient *client = getClientNoEx(peer_id,state_min);
2940         if(!client)
2941                 throw ClientNotFoundException("Client not found");
2942
2943         return client;
2944 }
2945 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
2946 {
2947         return m_clients.getClientNoEx(peer_id, state_min);
2948 }
2949
2950 std::string Server::getPlayerName(session_t peer_id)
2951 {
2952         RemotePlayer *player = m_env->getPlayer(peer_id);
2953         if (!player)
2954                 return "[id="+itos(peer_id)+"]";
2955         return player->getName();
2956 }
2957
2958 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
2959 {
2960         RemotePlayer *player = m_env->getPlayer(peer_id);
2961         if (!player)
2962                 return NULL;
2963         return player->getPlayerSAO();
2964 }
2965
2966 std::wstring Server::getStatusString()
2967 {
2968         std::wostringstream os(std::ios_base::binary);
2969         os << L"# Server: ";
2970         // Version
2971         os << L"version=" << narrow_to_wide(g_version_string);
2972         // Uptime
2973         os << L", uptime=" << m_uptime.get();
2974         // Max lag estimate
2975         os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
2976
2977         // Information about clients
2978         bool first = true;
2979         os << L", clients={";
2980         if (m_env) {
2981                 std::vector<session_t> clients = m_clients.getClientIDs();
2982                 for (session_t client_id : clients) {
2983                         RemotePlayer *player = m_env->getPlayer(client_id);
2984
2985                         // Get name of player
2986                         std::wstring name = L"unknown";
2987                         if (player)
2988                                 name = narrow_to_wide(player->getName());
2989
2990                         // Add name to information string
2991                         if (!first)
2992                                 os << L", ";
2993                         else
2994                                 first = false;
2995
2996                         os << name;
2997                 }
2998         }
2999         os << L"}";
3000
3001         if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3002                 os << std::endl << L"# Server: " << " WARNING: Map saving is disabled.";
3003
3004         if (!g_settings->get("motd").empty())
3005                 os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd"));
3006
3007         return os.str();
3008 }
3009
3010 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3011 {
3012         std::set<std::string> privs;
3013         m_script->getAuth(name, NULL, &privs);
3014         return privs;
3015 }
3016
3017 bool Server::checkPriv(const std::string &name, const std::string &priv)
3018 {
3019         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3020         return (privs.count(priv) != 0);
3021 }
3022
3023 void Server::reportPrivsModified(const std::string &name)
3024 {
3025         if (name.empty()) {
3026                 std::vector<session_t> clients = m_clients.getClientIDs();
3027                 for (const session_t client_id : clients) {
3028                         RemotePlayer *player = m_env->getPlayer(client_id);
3029                         reportPrivsModified(player->getName());
3030                 }
3031         } else {
3032                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3033                 if (!player)
3034                         return;
3035                 SendPlayerPrivileges(player->getPeerId());
3036                 PlayerSAO *sao = player->getPlayerSAO();
3037                 if(!sao)
3038                         return;
3039                 sao->updatePrivileges(
3040                                 getPlayerEffectivePrivs(name),
3041                                 isSingleplayer());
3042         }
3043 }
3044
3045 void Server::reportInventoryFormspecModified(const std::string &name)
3046 {
3047         RemotePlayer *player = m_env->getPlayer(name.c_str());
3048         if (!player)
3049                 return;
3050         SendPlayerInventoryFormspec(player->getPeerId());
3051 }
3052
3053 void Server::reportFormspecPrependModified(const std::string &name)
3054 {
3055         RemotePlayer *player = m_env->getPlayer(name.c_str());
3056         if (!player)
3057                 return;
3058         SendPlayerFormspecPrepend(player->getPeerId());
3059 }
3060
3061 void Server::setIpBanned(const std::string &ip, const std::string &name)
3062 {
3063         m_banmanager->add(ip, name);
3064 }
3065
3066 void Server::unsetIpBanned(const std::string &ip_or_name)
3067 {
3068         m_banmanager->remove(ip_or_name);
3069 }
3070
3071 std::string Server::getBanDescription(const std::string &ip_or_name)
3072 {
3073         return m_banmanager->getBanDescription(ip_or_name);
3074 }
3075
3076 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3077 {
3078         // m_env will be NULL if the server is initializing
3079         if (!m_env)
3080                 return;
3081
3082         if (m_admin_nick == name && !m_admin_nick.empty()) {
3083                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3084         }
3085
3086         RemotePlayer *player = m_env->getPlayer(name);
3087         if (!player) {
3088                 return;
3089         }
3090
3091         if (player->getPeerId() == PEER_ID_INEXISTENT)
3092                 return;
3093
3094         SendChatMessage(player->getPeerId(), ChatMessage(msg));
3095 }
3096
3097 bool Server::showFormspec(const char *playername, const std::string &formspec,
3098         const std::string &formname)
3099 {
3100         // m_env will be NULL if the server is initializing
3101         if (!m_env)
3102                 return false;
3103
3104         RemotePlayer *player = m_env->getPlayer(playername);
3105         if (!player)
3106                 return false;
3107
3108         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3109         return true;
3110 }
3111
3112 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3113 {
3114         if (!player)
3115                 return -1;
3116
3117         u32 id = player->addHud(form);
3118
3119         SendHUDAdd(player->getPeerId(), id, form);
3120
3121         return id;
3122 }
3123
3124 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3125         if (!player)
3126                 return false;
3127
3128         HudElement* todel = player->removeHud(id);
3129
3130         if (!todel)
3131                 return false;
3132
3133         delete todel;
3134
3135         SendHUDRemove(player->getPeerId(), id);
3136         return true;
3137 }
3138
3139 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3140 {
3141         if (!player)
3142                 return false;
3143
3144         SendHUDChange(player->getPeerId(), id, stat, data);
3145         return true;
3146 }
3147
3148 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3149 {
3150         if (!player)
3151                 return false;
3152
3153         SendHUDSetFlags(player->getPeerId(), flags, mask);
3154         player->hud_flags &= ~mask;
3155         player->hud_flags |= flags;
3156
3157         PlayerSAO* playersao = player->getPlayerSAO();
3158
3159         if (!playersao)
3160                 return false;
3161
3162         m_script->player_event(playersao, "hud_changed");
3163         return true;
3164 }
3165
3166 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3167 {
3168         if (!player)
3169                 return false;
3170
3171         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3172                 return false;
3173
3174         player->setHotbarItemcount(hotbar_itemcount);
3175         std::ostringstream os(std::ios::binary);
3176         writeS32(os, hotbar_itemcount);
3177         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3178         return true;
3179 }
3180
3181 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3182 {
3183         if (!player)
3184                 return;
3185
3186         player->setHotbarImage(name);
3187         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3188 }
3189
3190 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3191 {
3192         if (!player)
3193                 return;
3194
3195         player->setHotbarSelectedImage(name);
3196         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3197 }
3198
3199 Address Server::getPeerAddress(session_t peer_id)
3200 {
3201         return m_con->GetPeerAddress(peer_id);
3202 }
3203
3204 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3205                 v2s32 animation_frames[4], f32 frame_speed)
3206 {
3207         sanity_check(player);
3208         player->setLocalAnimations(animation_frames, frame_speed);
3209         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3210 }
3211
3212 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3213 {
3214         sanity_check(player);
3215         player->eye_offset_first = first;
3216         player->eye_offset_third = third;
3217         SendEyeOffset(player->getPeerId(), first, third);
3218 }
3219
3220 void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3221         const std::string &type, const std::vector<std::string> &params,
3222         bool &clouds)
3223 {
3224         sanity_check(player);
3225         player->setSky(bgcolor, type, params, clouds);
3226         SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
3227 }
3228
3229 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3230 {
3231         sanity_check(player);
3232         player->setCloudParams(params);
3233         SendCloudParams(player->getPeerId(), params);
3234 }
3235
3236 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3237         float ratio)
3238 {
3239         if (!player)
3240                 return false;
3241
3242         player->overrideDayNightRatio(do_override, ratio);
3243         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3244         return true;
3245 }
3246
3247 void Server::notifyPlayers(const std::wstring &msg)
3248 {
3249         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3250 }
3251
3252 void Server::spawnParticle(const std::string &playername, v3f pos,
3253         v3f velocity, v3f acceleration,
3254         float expirationtime, float size, bool
3255         collisiondetection, bool collision_removal, bool object_collision,
3256         bool vertical, const std::string &texture,
3257         const struct TileAnimationParams &animation, u8 glow)
3258 {
3259         // m_env will be NULL if the server is initializing
3260         if (!m_env)
3261                 return;
3262
3263         session_t peer_id = PEER_ID_INEXISTENT;
3264         u16 proto_ver = 0;
3265         if (!playername.empty()) {
3266                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3267                 if (!player)
3268                         return;
3269                 peer_id = player->getPeerId();
3270                 proto_ver = player->protocol_version;
3271         }
3272
3273         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3274                         expirationtime, size, collisiondetection, collision_removal,
3275                         object_collision, vertical, texture, animation, glow);
3276 }
3277
3278 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3279         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3280         float minexptime, float maxexptime, float minsize, float maxsize,
3281         bool collisiondetection, bool collision_removal, bool object_collision,
3282         ServerActiveObject *attached, bool vertical, const std::string &texture,
3283         const std::string &playername, const struct TileAnimationParams &animation,
3284         u8 glow)
3285 {
3286         // m_env will be NULL if the server is initializing
3287         if (!m_env)
3288                 return -1;
3289
3290         session_t peer_id = PEER_ID_INEXISTENT;
3291         u16 proto_ver = 0;
3292         if (!playername.empty()) {
3293                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3294                 if (!player)
3295                         return -1;
3296                 peer_id = player->getPeerId();
3297                 proto_ver = player->protocol_version;
3298         }
3299
3300         u16 attached_id = attached ? attached->getId() : 0;
3301
3302         u32 id;
3303         if (attached_id == 0)
3304                 id = m_env->addParticleSpawner(spawntime);
3305         else
3306                 id = m_env->addParticleSpawner(spawntime, attached_id);
3307
3308         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3309                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3310                 minexptime, maxexptime, minsize, maxsize, collisiondetection,
3311                 collision_removal, object_collision, attached_id, vertical,
3312                 texture, id, animation, glow);
3313
3314         return id;
3315 }
3316
3317 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3318 {
3319         // m_env will be NULL if the server is initializing
3320         if (!m_env)
3321                 throw ServerError("Can't delete particle spawners during initialisation!");
3322
3323         session_t peer_id = PEER_ID_INEXISTENT;
3324         if (!playername.empty()) {
3325                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3326                 if (!player)
3327                         return;
3328                 peer_id = player->getPeerId();
3329         }
3330
3331         m_env->deleteParticleSpawner(id);
3332         SendDeleteParticleSpawner(peer_id, id);
3333 }
3334
3335 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3336 {
3337         if(m_detached_inventories.count(name) > 0){
3338                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3339                 delete m_detached_inventories[name];
3340         } else {
3341                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3342         }
3343         Inventory *inv = new Inventory(m_itemdef);
3344         sanity_check(inv);
3345         m_detached_inventories[name] = inv;
3346         m_detached_inventories_player[name] = player;
3347         //TODO find a better way to do this
3348         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3349         return inv;
3350 }
3351
3352 bool Server::removeDetachedInventory(const std::string &name)
3353 {
3354         const auto &inv_it = m_detached_inventories.find(name);
3355         if (inv_it == m_detached_inventories.end())
3356                 return false;
3357
3358         delete inv_it->second;
3359         m_detached_inventories.erase(inv_it);
3360
3361         const auto &player_it = m_detached_inventories_player.find(name);
3362         if (player_it != m_detached_inventories_player.end()) {
3363                 RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());
3364
3365                 if (player && player->getPeerId() != PEER_ID_INEXISTENT)
3366                         sendDetachedInventory(name, player->getPeerId());
3367
3368                 m_detached_inventories_player.erase(player_it);
3369         } else {
3370                 // Notify all players about the change
3371                 sendDetachedInventory(name, PEER_ID_INEXISTENT);
3372         }
3373         return true;
3374 }
3375
3376 // actions: time-reversed list
3377 // Return value: success/failure
3378 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3379                 std::list<std::string> *log)
3380 {
3381         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3382         ServerMap *map = (ServerMap*)(&m_env->getMap());
3383
3384         // Fail if no actions to handle
3385         if (actions.empty()) {
3386                 assert(log);
3387                 log->push_back("Nothing to do.");
3388                 return false;
3389         }
3390
3391         int num_tried = 0;
3392         int num_failed = 0;
3393
3394         for (const RollbackAction &action : actions) {
3395                 num_tried++;
3396                 bool success = action.applyRevert(map, this, this);
3397                 if(!success){
3398                         num_failed++;
3399                         std::ostringstream os;
3400                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3401                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3402                         if (log)
3403                                 log->push_back(os.str());
3404                 }else{
3405                         std::ostringstream os;
3406                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3407                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3408                         if (log)
3409                                 log->push_back(os.str());
3410                 }
3411         }
3412
3413         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3414                         <<" failed"<<std::endl;
3415
3416         // Call it done if less than half failed
3417         return num_failed <= num_tried/2;
3418 }
3419
3420 // IGameDef interface
3421 // Under envlock
3422 IItemDefManager *Server::getItemDefManager()
3423 {
3424         return m_itemdef;
3425 }
3426
3427 const NodeDefManager *Server::getNodeDefManager()
3428 {
3429         return m_nodedef;
3430 }
3431
3432 ICraftDefManager *Server::getCraftDefManager()
3433 {
3434         return m_craftdef;
3435 }
3436
3437 u16 Server::allocateUnknownNodeId(const std::string &name)
3438 {
3439         return m_nodedef->allocateDummy(name);
3440 }
3441
3442 IWritableItemDefManager *Server::getWritableItemDefManager()
3443 {
3444         return m_itemdef;
3445 }
3446
3447 NodeDefManager *Server::getWritableNodeDefManager()
3448 {
3449         return m_nodedef;
3450 }
3451
3452 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3453 {
3454         return m_craftdef;
3455 }
3456
3457 const std::vector<ModSpec> & Server::getMods() const
3458 {
3459         return m_modmgr->getMods();
3460 }
3461
3462 const ModSpec *Server::getModSpec(const std::string &modname) const
3463 {
3464         return m_modmgr->getModSpec(modname);
3465 }
3466
3467 void Server::getModNames(std::vector<std::string> &modlist)
3468 {
3469         m_modmgr->getModNames(modlist);
3470 }
3471
3472 std::string Server::getBuiltinLuaPath()
3473 {
3474         return porting::path_share + DIR_DELIM + "builtin";
3475 }
3476
3477 std::string Server::getModStoragePath() const
3478 {
3479         return m_path_world + DIR_DELIM + "mod_storage";
3480 }
3481
3482 v3f Server::findSpawnPos()
3483 {
3484         ServerMap &map = m_env->getServerMap();
3485         v3f nodeposf;
3486         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3487                 return nodeposf * BS;
3488         }
3489
3490         bool is_good = false;
3491         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3492         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3493
3494         // Try to find a good place a few times
3495         for(s32 i = 0; i < 4000 && !is_good; i++) {
3496                 s32 range = MYMIN(1 + i, range_max);
3497                 // We're going to try to throw the player to this position
3498                 v2s16 nodepos2d = v2s16(
3499                         -range + (myrand() % (range * 2)),
3500                         -range + (myrand() % (range * 2)));
3501
3502                 // Get spawn level at point
3503                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3504                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3505                 // the mapgen to signify an unsuitable spawn position
3506                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3507                         continue;
3508
3509                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3510
3511                 s32 air_count = 0;
3512                 for (s32 i = 0; i < 10; i++) {
3513                         v3s16 blockpos = getNodeBlockPos(nodepos);
3514                         map.emergeBlock(blockpos, true);
3515                         content_t c = map.getNodeNoEx(nodepos).getContent();
3516                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3517                                 air_count++;
3518                                 if (air_count >= 2) {
3519                                         nodeposf = intToFloat(nodepos, BS);
3520                                         // Don't spawn the player outside map boundaries
3521                                         if (objectpos_over_limit(nodeposf))
3522                                                 continue;
3523                                         is_good = true;
3524                                         break;
3525                                 }
3526                         }
3527                         nodepos.Y++;
3528                 }
3529         }
3530
3531         return nodeposf;
3532 }
3533
3534 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3535 {
3536         if (delay == 0.0f) {
3537         // No delay, shutdown immediately
3538                 m_shutdown_state.is_requested = true;
3539                 // only print to the infostream, a chat message saying
3540                 // "Server Shutting Down" is sent when the server destructs.
3541                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3542         } else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3543                 // Negative delay, cancel shutdown if requested
3544                 m_shutdown_state.reset();
3545                 std::wstringstream ws;
3546
3547                 ws << L"*** Server shutdown canceled.";
3548
3549                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3550                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3551                 // m_shutdown_* are already handled, skip.
3552                 return;
3553         } else if (delay > 0.0f) {
3554         // Positive delay, tell the clients when the server will shut down
3555                 std::wstringstream ws;
3556
3557                 ws << L"*** Server shutting down in "
3558                                 << duration_to_string(myround(delay)).c_str()
3559                                 << ".";
3560
3561                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3562                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3563         }
3564
3565         m_shutdown_state.trigger(delay, msg, reconnect);
3566 }
3567
3568 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3569 {
3570         /*
3571                 Try to get an existing player
3572         */
3573         RemotePlayer *player = m_env->getPlayer(name);
3574
3575         // If player is already connected, cancel
3576         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3577                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3578                 return NULL;
3579         }
3580
3581         /*
3582                 If player with the wanted peer_id already exists, cancel.
3583         */
3584         if (m_env->getPlayer(peer_id)) {
3585                 infostream<<"emergePlayer(): Player with wrong name but same"
3586                                 " peer_id already exists"<<std::endl;
3587                 return NULL;
3588         }
3589
3590         if (!player) {
3591                 player = new RemotePlayer(name, idef());
3592         }
3593
3594         bool newplayer = false;
3595
3596         // Load player
3597         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3598
3599         // Complete init with server parts
3600         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3601         player->protocol_version = proto_version;
3602
3603         /* Run scripts */
3604         if (newplayer) {
3605                 m_script->on_newplayer(playersao);
3606         }
3607
3608         return playersao;
3609 }
3610
3611 bool Server::registerModStorage(ModMetadata *storage)
3612 {
3613         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3614                 errorstream << "Unable to register same mod storage twice. Storage name: "
3615                                 << storage->getModName() << std::endl;
3616                 return false;
3617         }
3618
3619         m_mod_storages[storage->getModName()] = storage;
3620         return true;
3621 }
3622
3623 void Server::unregisterModStorage(const std::string &name)
3624 {
3625         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3626         if (it != m_mod_storages.end()) {
3627                 // Save unconditionaly on unregistration
3628                 it->second->save(getModStoragePath());
3629                 m_mod_storages.erase(name);
3630         }
3631 }
3632
3633 void dedicated_server_loop(Server &server, bool &kill)
3634 {
3635         verbosestream<<"dedicated_server_loop()"<<std::endl;
3636
3637         IntervalLimiter m_profiler_interval;
3638
3639         static thread_local const float steplen =
3640                         g_settings->getFloat("dedicated_server_step");
3641         static thread_local const float profiler_print_interval =
3642                         g_settings->getFloat("profiler_print_interval");
3643
3644         for(;;) {
3645                 // This is kind of a hack but can be done like this
3646                 // because server.step() is very light
3647                 {
3648                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3649                         sleep_ms((int)(steplen*1000.0));
3650                 }
3651                 server.step(steplen);
3652
3653                 if (server.isShutdownRequested() || kill)
3654                         break;
3655
3656                 /*
3657                         Profiler
3658                 */
3659                 if (profiler_print_interval != 0) {
3660                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3661                         {
3662                                 infostream<<"Profiler:"<<std::endl;
3663                                 g_profiler->print(infostream);
3664                                 g_profiler->clear();
3665                         }
3666                 }
3667         }
3668
3669         infostream << "Dedicated server quitting" << std::endl;
3670 #if USE_CURL
3671         if (g_settings->getBool("server_announce"))
3672                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3673                         server.m_bind_addr.getPort());
3674 #endif
3675 }
3676
3677 /*
3678  * Mod channels
3679  */
3680
3681
3682 bool Server::joinModChannel(const std::string &channel)
3683 {
3684         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3685                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3686 }
3687
3688 bool Server::leaveModChannel(const std::string &channel)
3689 {
3690         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3691 }
3692
3693 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3694 {
3695         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3696                 return false;
3697
3698         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3699         return true;
3700 }
3701
3702 ModChannel* Server::getModChannel(const std::string &channel)
3703 {
3704         return m_modchannel_mgr->getModChannel(channel);
3705 }
3706
3707 void Server::broadcastModChannelMessage(const std::string &channel,
3708                 const std::string &message, session_t from_peer)
3709 {
3710         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3711         if (peers.empty())
3712                 return;
3713
3714         if (message.size() > STRING_MAX_LEN) {
3715                 warningstream << "ModChannel message too long, dropping before sending "
3716                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3717                                 << channel << ")" << std::endl;
3718                 return;
3719         }
3720
3721         std::string sender;
3722         if (from_peer != PEER_ID_SERVER) {
3723                 sender = getPlayerName(from_peer);
3724         }
3725
3726         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3727                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3728         resp_pkt << channel << sender << message;
3729         for (session_t peer_id : peers) {
3730                 // Ignore sender
3731                 if (peer_id == from_peer)
3732                         continue;
3733
3734                 Send(peer_id, &resp_pkt);
3735         }
3736
3737         if (from_peer != PEER_ID_SERVER) {
3738                 m_script->on_modchannel_message(channel, sender, message);
3739         }
3740 }