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