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