Fix 2 log messages when player joined to game (#9477)
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/connection.h"
25 #include "network/networkprotocol.h"
26 #include "network/serveropcodes.h"
27 #include "ban.h"
28 #include "environment.h"
29 #include "map.h"
30 #include "threading/mutex_auto_lock.h"
31 #include "constants.h"
32 #include "voxel.h"
33 #include "config.h"
34 #include "version.h"
35 #include "filesys.h"
36 #include "mapblock.h"
37 #include "serverobject.h"
38 #include "genericobject.h"
39 #include "settings.h"
40 #include "profiler.h"
41 #include "log.h"
42 #include "scripting_server.h"
43 #include "nodedef.h"
44 #include "itemdef.h"
45 #include "craftdef.h"
46 #include "emerge.h"
47 #include "mapgen/mapgen.h"
48 #include "mapgen/mg_biome.h"
49 #include "content_mapnode.h"
50 #include "content_nodemeta.h"
51 #include "content_sao.h"
52 #include "content/mods.h"
53 #include "modchannels.h"
54 #include "serverlist.h"
55 #include "util/string.h"
56 #include "rollback.h"
57 #include "util/serialize.h"
58 #include "util/thread.h"
59 #include "defaultsettings.h"
60 #include "server/mods.h"
61 #include "util/base64.h"
62 #include "util/sha1.h"
63 #include "util/hex.h"
64 #include "database/database.h"
65 #include "chatmessage.h"
66 #include "chat_interface.h"
67 #include "remoteplayer.h"
68
69 class ClientNotFoundException : public BaseException
70 {
71 public:
72         ClientNotFoundException(const char *s):
73                 BaseException(s)
74         {}
75 };
76
77 class ServerThread : public Thread
78 {
79 public:
80
81         ServerThread(Server *server):
82                 Thread("Server"),
83                 m_server(server)
84         {}
85
86         void *run();
87
88 private:
89         Server *m_server;
90 };
91
92 void *ServerThread::run()
93 {
94         BEGIN_DEBUG_EXCEPTION_HANDLER
95
96         /*
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         /*
1022                 Print out action
1023         */
1024         {
1025                 Address addr = getPeerAddress(player->getPeerId());
1026                 std::string ip_str = addr.serializeString();
1027                 const std::vector<std::string> &names = m_clients.getPlayerNames();
1028
1029                 actionstream << player->getName() << " [" << ip_str << "] joins game. List of players: ";
1030
1031                 for (const std::string &name : names) {
1032                         actionstream << name << " ";
1033                 }
1034
1035                 actionstream << player->getName() <<std::endl;
1036         }
1037         return playersao;
1038 }
1039
1040 inline void Server::handleCommand(NetworkPacket *pkt)
1041 {
1042         const ToServerCommandHandler &opHandle = toServerCommandTable[pkt->getCommand()];
1043         (this->*opHandle.handler)(pkt);
1044 }
1045
1046 void Server::ProcessData(NetworkPacket *pkt)
1047 {
1048         // Environment is locked first.
1049         MutexAutoLock envlock(m_env_mutex);
1050
1051         ScopeProfiler sp(g_profiler, "Server: Process network packet (sum)");
1052         u32 peer_id = pkt->getPeerId();
1053
1054         try {
1055                 Address address = getPeerAddress(peer_id);
1056                 std::string addr_s = address.serializeString();
1057
1058                 if(m_banmanager->isIpBanned(addr_s)) {
1059                         std::string ban_name = m_banmanager->getBanName(addr_s);
1060                         infostream << "Server: A banned client tried to connect from "
1061                                         << addr_s << "; banned name was "
1062                                         << ban_name << std::endl;
1063                         // This actually doesn't seem to transfer to the client
1064                         DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
1065                                         + utf8_to_wide(ban_name));
1066                         return;
1067                 }
1068         }
1069         catch(con::PeerNotFoundException &e) {
1070                 /*
1071                  * no peer for this packet found
1072                  * most common reason is peer timeout, e.g. peer didn't
1073                  * respond for some time, your server was overloaded or
1074                  * things like that.
1075                  */
1076                 infostream << "Server::ProcessData(): Canceling: peer "
1077                                 << peer_id << " not found" << std::endl;
1078                 return;
1079         }
1080
1081         try {
1082                 ToServerCommand command = (ToServerCommand) pkt->getCommand();
1083
1084                 // Command must be handled into ToServerCommandHandler
1085                 if (command >= TOSERVER_NUM_MSG_TYPES) {
1086                         infostream << "Server: Ignoring unknown command "
1087                                          << command << std::endl;
1088                         return;
1089                 }
1090
1091                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1092                         handleCommand(pkt);
1093                         return;
1094                 }
1095
1096                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1097
1098                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1099                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1100                                         " serialization format invalid or not initialized."
1101                                         " Skipping incoming command=" << command << std::endl;
1102                         return;
1103                 }
1104
1105                 /* Handle commands related to client startup */
1106                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1107                         handleCommand(pkt);
1108                         return;
1109                 }
1110
1111                 if (m_clients.getClientState(peer_id) < CS_Active) {
1112                         if (command == TOSERVER_PLAYERPOS) return;
1113
1114                         errorstream << "Got packet command: " << command << " for peer id "
1115                                         << peer_id << " but client isn't active yet. Dropping packet "
1116                                         << std::endl;
1117                         return;
1118                 }
1119
1120                 handleCommand(pkt);
1121         } catch (SendFailedException &e) {
1122                 errorstream << "Server::ProcessData(): SendFailedException: "
1123                                 << "what=" << e.what()
1124                                 << std::endl;
1125         } catch (PacketError &e) {
1126                 actionstream << "Server::ProcessData(): PacketError: "
1127                                 << "what=" << e.what()
1128                                 << std::endl;
1129         }
1130 }
1131
1132 void Server::setTimeOfDay(u32 time)
1133 {
1134         m_env->setTimeOfDay(time);
1135         m_time_of_day_send_timer = 0;
1136 }
1137
1138 void Server::onMapEditEvent(const MapEditEvent &event)
1139 {
1140         if (m_ignore_map_edit_events_area.contains(event.getArea()))
1141                 return;
1142
1143         m_unsent_map_edit_queue.push(new MapEditEvent(event));
1144 }
1145
1146 Inventory* Server::getInventory(const InventoryLocation &loc)
1147 {
1148         switch (loc.type) {
1149         case InventoryLocation::UNDEFINED:
1150         case InventoryLocation::CURRENT_PLAYER:
1151                 break;
1152         case InventoryLocation::PLAYER:
1153         {
1154                 RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
1155                 if(!player)
1156                         return NULL;
1157                 PlayerSAO *playersao = player->getPlayerSAO();
1158                 if(!playersao)
1159                         return NULL;
1160                 return playersao->getInventory();
1161         }
1162                 break;
1163         case InventoryLocation::NODEMETA:
1164         {
1165                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1166                 if(!meta)
1167                         return NULL;
1168                 return meta->getInventory();
1169         }
1170                 break;
1171         case InventoryLocation::DETACHED:
1172         {
1173                 if(m_detached_inventories.count(loc.name) == 0)
1174                         return NULL;
1175                 return m_detached_inventories[loc.name];
1176         }
1177                 break;
1178         default:
1179                 sanity_check(false); // abort
1180                 break;
1181         }
1182         return NULL;
1183 }
1184
1185 void Server::setInventoryModified(const InventoryLocation &loc)
1186 {
1187         switch(loc.type){
1188         case InventoryLocation::UNDEFINED:
1189                 break;
1190         case InventoryLocation::PLAYER:
1191         {
1192
1193                 RemotePlayer *player = m_env->getPlayer(loc.name.c_str());
1194
1195                 if (!player)
1196                         return;
1197
1198                 player->setModified(true);
1199                 player->inventory.setModified(true);
1200                 // Updates are sent in ServerEnvironment::step()
1201         }
1202                 break;
1203         case InventoryLocation::NODEMETA:
1204         {
1205                 MapEditEvent event;
1206                 event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
1207                 event.p = loc.p;
1208                 m_env->getMap().dispatchEvent(event);
1209         }
1210                 break;
1211         case InventoryLocation::DETACHED:
1212         {
1213                 // Updates are sent in ServerEnvironment::step()
1214         }
1215                 break;
1216         default:
1217                 sanity_check(false); // abort
1218                 break;
1219         }
1220 }
1221
1222 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1223 {
1224         std::vector<session_t> clients = m_clients.getClientIDs();
1225         m_clients.lock();
1226         // Set the modified blocks unsent for all the clients
1227         for (const session_t client_id : clients) {
1228                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(client_id))
1229                                 client->SetBlocksNotSent(block);
1230         }
1231         m_clients.unlock();
1232 }
1233
1234 void Server::peerAdded(con::Peer *peer)
1235 {
1236         verbosestream<<"Server::peerAdded(): peer->id="
1237                         <<peer->id<<std::endl;
1238
1239         m_peer_change_queue.push(con::PeerChange(con::PEER_ADDED, peer->id, false));
1240 }
1241
1242 void Server::deletingPeer(con::Peer *peer, bool timeout)
1243 {
1244         verbosestream<<"Server::deletingPeer(): peer->id="
1245                         <<peer->id<<", timeout="<<timeout<<std::endl;
1246
1247         m_clients.event(peer->id, CSE_Disconnect);
1248         m_peer_change_queue.push(con::PeerChange(con::PEER_REMOVED, peer->id, timeout));
1249 }
1250
1251 bool Server::getClientConInfo(session_t peer_id, con::rtt_stat_type type, float* retval)
1252 {
1253         *retval = m_con->getPeerStat(peer_id,type);
1254         return *retval != -1;
1255 }
1256
1257 bool Server::getClientInfo(
1258                 session_t    peer_id,
1259                 ClientState* state,
1260                 u32*         uptime,
1261                 u8*          ser_vers,
1262                 u16*         prot_vers,
1263                 u8*          major,
1264                 u8*          minor,
1265                 u8*          patch,
1266                 std::string* vers_string
1267         )
1268 {
1269         *state = m_clients.getClientState(peer_id);
1270         m_clients.lock();
1271         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1272
1273         if (!client) {
1274                 m_clients.unlock();
1275                 return false;
1276         }
1277
1278         *uptime = client->uptime();
1279         *ser_vers = client->serialization_version;
1280         *prot_vers = client->net_proto_version;
1281
1282         *major = client->getMajor();
1283         *minor = client->getMinor();
1284         *patch = client->getPatch();
1285         *vers_string = client->getFull();
1286
1287         m_clients.unlock();
1288
1289         return true;
1290 }
1291
1292 void Server::handlePeerChanges()
1293 {
1294         while(!m_peer_change_queue.empty())
1295         {
1296                 con::PeerChange c = m_peer_change_queue.front();
1297                 m_peer_change_queue.pop();
1298
1299                 verbosestream<<"Server: Handling peer change: "
1300                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1301                                 <<std::endl;
1302
1303                 switch(c.type)
1304                 {
1305                 case con::PEER_ADDED:
1306                         m_clients.CreateClient(c.peer_id);
1307                         break;
1308
1309                 case con::PEER_REMOVED:
1310                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1311                         break;
1312
1313                 default:
1314                         FATAL_ERROR("Invalid peer change event received!");
1315                         break;
1316                 }
1317         }
1318 }
1319
1320 void Server::printToConsoleOnly(const std::string &text)
1321 {
1322         if (m_admin_chat) {
1323                 m_admin_chat->outgoing_queue.push_back(
1324                         new ChatEventChat("", utf8_to_wide(text)));
1325         } else {
1326                 std::cout << text << std::endl;
1327         }
1328 }
1329
1330 void Server::Send(NetworkPacket *pkt)
1331 {
1332         Send(pkt->getPeerId(), pkt);
1333 }
1334
1335 void Server::Send(session_t peer_id, NetworkPacket *pkt)
1336 {
1337         m_clients.send(peer_id,
1338                 clientCommandFactoryTable[pkt->getCommand()].channel,
1339                 pkt,
1340                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1341 }
1342
1343 void Server::SendMovement(session_t peer_id)
1344 {
1345         std::ostringstream os(std::ios_base::binary);
1346
1347         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1348
1349         pkt << g_settings->getFloat("movement_acceleration_default");
1350         pkt << g_settings->getFloat("movement_acceleration_air");
1351         pkt << g_settings->getFloat("movement_acceleration_fast");
1352         pkt << g_settings->getFloat("movement_speed_walk");
1353         pkt << g_settings->getFloat("movement_speed_crouch");
1354         pkt << g_settings->getFloat("movement_speed_fast");
1355         pkt << g_settings->getFloat("movement_speed_climb");
1356         pkt << g_settings->getFloat("movement_speed_jump");
1357         pkt << g_settings->getFloat("movement_liquid_fluidity");
1358         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1359         pkt << g_settings->getFloat("movement_liquid_sink");
1360         pkt << g_settings->getFloat("movement_gravity");
1361
1362         Send(&pkt);
1363 }
1364
1365 void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
1366 {
1367         if (playersao->isImmortal())
1368                 return;
1369
1370         session_t peer_id = playersao->getPeerID();
1371         bool is_alive = playersao->getHP() > 0;
1372
1373         if (is_alive)
1374                 SendPlayerHP(peer_id);
1375         else
1376                 DiePlayer(peer_id, reason);
1377 }
1378
1379 void Server::SendHP(session_t peer_id, u16 hp)
1380 {
1381         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1382         pkt << hp;
1383         Send(&pkt);
1384 }
1385
1386 void Server::SendBreath(session_t peer_id, u16 breath)
1387 {
1388         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1389         pkt << (u16) breath;
1390         Send(&pkt);
1391 }
1392
1393 void Server::SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
1394                 const std::string &custom_reason, bool reconnect)
1395 {
1396         assert(reason < SERVER_ACCESSDENIED_MAX);
1397
1398         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1399         pkt << (u8)reason;
1400         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1401                 pkt << custom_reason;
1402         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1403                         reason == SERVER_ACCESSDENIED_CRASH)
1404                 pkt << custom_reason << (u8)reconnect;
1405         Send(&pkt);
1406 }
1407
1408 void Server::SendAccessDenied_Legacy(session_t peer_id,const std::wstring &reason)
1409 {
1410         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1411         pkt << reason;
1412         Send(&pkt);
1413 }
1414
1415 void Server::SendDeathscreen(session_t peer_id, bool set_camera_point_target,
1416                 v3f camera_point_target)
1417 {
1418         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1419         pkt << set_camera_point_target << camera_point_target;
1420         Send(&pkt);
1421 }
1422
1423 void Server::SendItemDef(session_t peer_id,
1424                 IItemDefManager *itemdef, u16 protocol_version)
1425 {
1426         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1427
1428         /*
1429                 u16 command
1430                 u32 length of the next item
1431                 zlib-compressed serialized ItemDefManager
1432         */
1433         std::ostringstream tmp_os(std::ios::binary);
1434         itemdef->serialize(tmp_os, protocol_version);
1435         std::ostringstream tmp_os2(std::ios::binary);
1436         compressZlib(tmp_os.str(), tmp_os2);
1437         pkt.putLongString(tmp_os2.str());
1438
1439         // Make data buffer
1440         verbosestream << "Server: Sending item definitions to id(" << peer_id
1441                         << "): size=" << pkt.getSize() << std::endl;
1442
1443         Send(&pkt);
1444 }
1445
1446 void Server::SendNodeDef(session_t peer_id,
1447         const NodeDefManager *nodedef, u16 protocol_version)
1448 {
1449         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1450
1451         /*
1452                 u16 command
1453                 u32 length of the next item
1454                 zlib-compressed serialized NodeDefManager
1455         */
1456         std::ostringstream tmp_os(std::ios::binary);
1457         nodedef->serialize(tmp_os, protocol_version);
1458         std::ostringstream tmp_os2(std::ios::binary);
1459         compressZlib(tmp_os.str(), tmp_os2);
1460
1461         pkt.putLongString(tmp_os2.str());
1462
1463         // Make data buffer
1464         verbosestream << "Server: Sending node definitions to id(" << peer_id
1465                         << "): size=" << pkt.getSize() << std::endl;
1466
1467         Send(&pkt);
1468 }
1469
1470 /*
1471         Non-static send methods
1472 */
1473
1474 void Server::SendInventory(PlayerSAO *sao, bool incremental)
1475 {
1476         RemotePlayer *player = sao->getPlayer();
1477
1478         // Do not send new format to old clients
1479         incremental &= player->protocol_version >= 38;
1480
1481         UpdateCrafting(player);
1482
1483         /*
1484                 Serialize it
1485         */
1486
1487         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, sao->getPeerID());
1488
1489         std::ostringstream os(std::ios::binary);
1490         sao->getInventory()->serialize(os, incremental);
1491         sao->getInventory()->setModified(false);
1492         player->setModified(true);
1493
1494         const std::string &s = os.str();
1495         pkt.putRawString(s.c_str(), s.size());
1496         Send(&pkt);
1497 }
1498
1499 void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
1500 {
1501         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1502         u8 version = 1;
1503         u8 type = message.type;
1504         pkt << version << type << std::wstring(L"") << message.message << (u64)message.timestamp;
1505
1506         if (peer_id != PEER_ID_INEXISTENT) {
1507                 RemotePlayer *player = m_env->getPlayer(peer_id);
1508                 if (!player)
1509                         return;
1510
1511                 Send(&pkt);
1512         } else {
1513                 m_clients.sendToAll(&pkt);
1514         }
1515 }
1516
1517 void Server::SendShowFormspecMessage(session_t peer_id, const std::string &formspec,
1518         const std::string &formname)
1519 {
1520         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0, peer_id);
1521         if (formspec.empty()){
1522                 //the client should close the formspec
1523                 //but make sure there wasn't another one open in meantime
1524                 const auto it = m_formspec_state_data.find(peer_id);
1525                 if (it != m_formspec_state_data.end() && it->second == formname) {
1526                         m_formspec_state_data.erase(peer_id);
1527                 }
1528                 pkt.putLongString("");
1529         } else {
1530                 m_formspec_state_data[peer_id] = formname;
1531                 pkt.putLongString(formspec);
1532         }
1533         pkt << formname;
1534
1535         Send(&pkt);
1536 }
1537
1538 // Spawns a particle on peer with peer_id
1539 void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
1540                                 v3f pos, v3f velocity, v3f acceleration,
1541                                 float expirationtime, float size, bool collisiondetection,
1542                                 bool collision_removal, bool object_collision,
1543                                 bool vertical, const std::string &texture,
1544                                 const struct TileAnimationParams &animation, u8 glow)
1545 {
1546         static thread_local const float radius =
1547                         g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1548
1549         if (peer_id == PEER_ID_INEXISTENT) {
1550                 std::vector<session_t> clients = m_clients.getClientIDs();
1551
1552                 for (const session_t client_id : clients) {
1553                         RemotePlayer *player = m_env->getPlayer(client_id);
1554                         if (!player)
1555                                 continue;
1556
1557                         PlayerSAO *sao = player->getPlayerSAO();
1558                         if (!sao)
1559                                 continue;
1560
1561                         // Do not send to distant clients
1562                         if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
1563                                 continue;
1564
1565                         SendSpawnParticle(client_id, player->protocol_version,
1566                                         pos, velocity, acceleration,
1567                                         expirationtime, size, collisiondetection, collision_removal,
1568                                         object_collision, vertical, texture, animation, glow);
1569                 }
1570                 return;
1571         }
1572
1573         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1574
1575         pkt << pos << velocity << acceleration << expirationtime
1576                         << size << collisiondetection;
1577         pkt.putLongString(texture);
1578         pkt << vertical;
1579         pkt << collision_removal;
1580         // This is horrible but required (why are there two ways to serialize pkts?)
1581         std::ostringstream os(std::ios_base::binary);
1582         animation.serialize(os, protocol_version);
1583         pkt.putRawString(os.str());
1584         pkt << glow;
1585         pkt << object_collision;
1586
1587         Send(&pkt);
1588 }
1589
1590 // Adds a ParticleSpawner on peer with peer_id
1591 void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
1592         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1593         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1594         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1595         bool object_collision, u16 attached_id, bool vertical, const std::string &texture, u32 id,
1596         const struct TileAnimationParams &animation, u8 glow)
1597 {
1598         if (peer_id == PEER_ID_INEXISTENT) {
1599                 // This sucks and should be replaced:
1600                 std::vector<session_t> clients = m_clients.getClientIDs();
1601                 for (const session_t client_id : clients) {
1602                         RemotePlayer *player = m_env->getPlayer(client_id);
1603                         if (!player)
1604                                 continue;
1605                         SendAddParticleSpawner(client_id, player->protocol_version,
1606                                         amount, spawntime, minpos, maxpos,
1607                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1608                                         minsize, maxsize, collisiondetection, collision_removal,
1609                                         object_collision, attached_id, vertical, texture, id,
1610                                         animation, glow);
1611                 }
1612                 return;
1613         }
1614
1615         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1616
1617         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1618                         << minacc << maxacc << minexptime << maxexptime << minsize
1619                         << maxsize << collisiondetection;
1620
1621         pkt.putLongString(texture);
1622
1623         pkt << id << vertical;
1624         pkt << collision_removal;
1625         pkt << attached_id;
1626         // This is horrible but required
1627         std::ostringstream os(std::ios_base::binary);
1628         animation.serialize(os, protocol_version);
1629         pkt.putRawString(os.str());
1630         pkt << glow;
1631         pkt << object_collision;
1632
1633         Send(&pkt);
1634 }
1635
1636 void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
1637 {
1638         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER, 4, peer_id);
1639
1640         // Ugly error in this packet
1641         pkt << id;
1642
1643         if (peer_id != PEER_ID_INEXISTENT)
1644                 Send(&pkt);
1645         else
1646                 m_clients.sendToAll(&pkt);
1647
1648 }
1649
1650 void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
1651 {
1652         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1653
1654         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1655                         << form->text << form->number << form->item << form->dir
1656                         << form->align << form->offset << form->world_pos << form->size
1657                         << form->z_index;
1658
1659         Send(&pkt);
1660 }
1661
1662 void Server::SendHUDRemove(session_t peer_id, u32 id)
1663 {
1664         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1665         pkt << id;
1666         Send(&pkt);
1667 }
1668
1669 void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
1670 {
1671         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1672         pkt << id << (u8) stat;
1673
1674         switch (stat) {
1675                 case HUD_STAT_POS:
1676                 case HUD_STAT_SCALE:
1677                 case HUD_STAT_ALIGN:
1678                 case HUD_STAT_OFFSET:
1679                         pkt << *(v2f *) value;
1680                         break;
1681                 case HUD_STAT_NAME:
1682                 case HUD_STAT_TEXT:
1683                         pkt << *(std::string *) value;
1684                         break;
1685                 case HUD_STAT_WORLD_POS:
1686                         pkt << *(v3f *) value;
1687                         break;
1688                 case HUD_STAT_SIZE:
1689                         pkt << *(v2s32 *) value;
1690                         break;
1691                 case HUD_STAT_NUMBER:
1692                 case HUD_STAT_ITEM:
1693                 case HUD_STAT_DIR:
1694                 default:
1695                         pkt << *(u32 *) value;
1696                         break;
1697         }
1698
1699         Send(&pkt);
1700 }
1701
1702 void Server::SendHUDSetFlags(session_t peer_id, u32 flags, u32 mask)
1703 {
1704         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1705
1706         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1707
1708         pkt << flags << mask;
1709
1710         Send(&pkt);
1711 }
1712
1713 void Server::SendHUDSetParam(session_t peer_id, u16 param, const std::string &value)
1714 {
1715         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1716         pkt << param << value;
1717         Send(&pkt);
1718 }
1719
1720 void Server::SendSetSky(session_t peer_id, const SkyboxParams &params)
1721 {
1722         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1723
1724         // Handle prior clients here
1725         if (m_clients.getProtocolVersion(peer_id) < 39) {
1726                 pkt << params.bgcolor << params.type << (u16) params.textures.size();
1727
1728                 for (const std::string& texture : params.textures)
1729                         pkt << texture;
1730
1731                 pkt << params.clouds;
1732         } else { // Handle current clients and future clients
1733                 pkt << params.bgcolor << params.type
1734                 << params.clouds << params.sun_tint
1735                 << params.moon_tint << params.tint_type;
1736
1737                 if (params.type == "skybox") {
1738                         pkt << (u16) params.textures.size();
1739                         for (const std::string &texture : params.textures)
1740                                 pkt << texture;
1741                 } else if (params.type == "regular") {
1742                         pkt << params.sky_color.day_sky << params.sky_color.day_horizon
1743                                 << params.sky_color.dawn_sky << params.sky_color.dawn_horizon
1744                                 << params.sky_color.night_sky << params.sky_color.night_horizon
1745                                 << params.sky_color.indoors;
1746                 }
1747         }
1748
1749         Send(&pkt);
1750 }
1751
1752 void Server::SendSetSun(session_t peer_id, const SunParams &params)
1753 {
1754         NetworkPacket pkt(TOCLIENT_SET_SUN, 0, peer_id);
1755         pkt << params.visible << params.texture
1756                 << params.tonemap << params.sunrise
1757                 << params.sunrise_visible << params.scale;
1758
1759         Send(&pkt);
1760 }
1761 void Server::SendSetMoon(session_t peer_id, const MoonParams &params)
1762 {
1763         NetworkPacket pkt(TOCLIENT_SET_MOON, 0, peer_id);
1764
1765         pkt << params.visible << params.texture
1766                 << params.tonemap << params.scale;
1767
1768         Send(&pkt);
1769 }
1770 void Server::SendSetStars(session_t peer_id, const StarParams &params)
1771 {
1772         NetworkPacket pkt(TOCLIENT_SET_STARS, 0, peer_id);
1773
1774         pkt << params.visible << params.count
1775                 << params.starcolor << params.scale;
1776
1777         Send(&pkt);
1778 }
1779
1780 void Server::SendCloudParams(session_t peer_id, const CloudParams &params)
1781 {
1782         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1783         pkt << params.density << params.color_bright << params.color_ambient
1784                         << params.height << params.thickness << params.speed;
1785         Send(&pkt);
1786 }
1787
1788 void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
1789                 float ratio)
1790 {
1791         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1792                         1 + 2, peer_id);
1793
1794         pkt << do_override << (u16) (ratio * 65535);
1795
1796         Send(&pkt);
1797 }
1798
1799 void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
1800 {
1801         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1802         pkt << time << time_speed;
1803
1804         if (peer_id == PEER_ID_INEXISTENT) {
1805                 m_clients.sendToAll(&pkt);
1806         }
1807         else {
1808                 Send(&pkt);
1809         }
1810 }
1811
1812 void Server::SendPlayerHP(session_t peer_id)
1813 {
1814         PlayerSAO *playersao = getPlayerSAO(peer_id);
1815         assert(playersao);
1816
1817         SendHP(peer_id, playersao->getHP());
1818         m_script->player_event(playersao,"health_changed");
1819
1820         // Send to other clients
1821         std::string str = gob_cmd_punched(playersao->getHP());
1822         ActiveObjectMessage aom(playersao->getId(), true, str);
1823         playersao->m_messages_out.push(aom);
1824 }
1825
1826 void Server::SendPlayerBreath(PlayerSAO *sao)
1827 {
1828         assert(sao);
1829
1830         m_script->player_event(sao, "breath_changed");
1831         SendBreath(sao->getPeerID(), sao->getBreath());
1832 }
1833
1834 void Server::SendMovePlayer(session_t peer_id)
1835 {
1836         RemotePlayer *player = m_env->getPlayer(peer_id);
1837         assert(player);
1838         PlayerSAO *sao = player->getPlayerSAO();
1839         assert(sao);
1840
1841         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1842         pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
1843
1844         {
1845                 v3f pos = sao->getBasePosition();
1846                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1847                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1848                                 << " pitch=" << sao->getLookPitch()
1849                                 << " yaw=" << sao->getRotation().Y
1850                                 << std::endl;
1851         }
1852
1853         Send(&pkt);
1854 }
1855
1856 void Server::SendPlayerFov(session_t peer_id)
1857 {
1858         NetworkPacket pkt(TOCLIENT_FOV, 4 + 1, peer_id);
1859
1860         PlayerFovSpec fov_spec = m_env->getPlayer(peer_id)->getFov();
1861         pkt << fov_spec.fov << fov_spec.is_multiplier;
1862
1863         Send(&pkt);
1864 }
1865
1866 void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames[4],
1867                 f32 animation_speed)
1868 {
1869         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1870                 peer_id);
1871
1872         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1873                         << animation_frames[3] << animation_speed;
1874
1875         Send(&pkt);
1876 }
1877
1878 void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
1879 {
1880         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1881         pkt << first << third;
1882         Send(&pkt);
1883 }
1884
1885 void Server::SendPlayerPrivileges(session_t peer_id)
1886 {
1887         RemotePlayer *player = m_env->getPlayer(peer_id);
1888         assert(player);
1889         if(player->getPeerId() == PEER_ID_INEXISTENT)
1890                 return;
1891
1892         std::set<std::string> privs;
1893         m_script->getAuth(player->getName(), NULL, &privs);
1894
1895         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1896         pkt << (u16) privs.size();
1897
1898         for (const std::string &priv : privs) {
1899                 pkt << priv;
1900         }
1901
1902         Send(&pkt);
1903 }
1904
1905 void Server::SendPlayerInventoryFormspec(session_t peer_id)
1906 {
1907         RemotePlayer *player = m_env->getPlayer(peer_id);
1908         assert(player);
1909         if (player->getPeerId() == PEER_ID_INEXISTENT)
1910                 return;
1911
1912         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1913         pkt.putLongString(player->inventory_formspec);
1914
1915         Send(&pkt);
1916 }
1917
1918 void Server::SendPlayerFormspecPrepend(session_t peer_id)
1919 {
1920         RemotePlayer *player = m_env->getPlayer(peer_id);
1921         assert(player);
1922         if (player->getPeerId() == PEER_ID_INEXISTENT)
1923                 return;
1924
1925         NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
1926         pkt << player->formspec_prepend;
1927         Send(&pkt);
1928 }
1929
1930 void Server::SendActiveObjectRemoveAdd(RemoteClient *client, PlayerSAO *playersao)
1931 {
1932         // Radius inside which objects are active
1933         static thread_local const s16 radius =
1934                 g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
1935
1936         // Radius inside which players are active
1937         static thread_local const bool is_transfer_limited =
1938                 g_settings->exists("unlimited_player_transfer_distance") &&
1939                 !g_settings->getBool("unlimited_player_transfer_distance");
1940
1941         static thread_local const s16 player_transfer_dist =
1942                 g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
1943
1944         s16 player_radius = player_transfer_dist == 0 && is_transfer_limited ?
1945                 radius : player_transfer_dist;
1946
1947         s16 my_radius = MYMIN(radius, playersao->getWantedRange() * MAP_BLOCKSIZE);
1948         if (my_radius <= 0)
1949                 my_radius = radius;
1950
1951         std::queue<u16> removed_objects, added_objects;
1952         m_env->getRemovedActiveObjects(playersao, my_radius, player_radius,
1953                 client->m_known_objects, removed_objects);
1954         m_env->getAddedActiveObjects(playersao, my_radius, player_radius,
1955                 client->m_known_objects, added_objects);
1956
1957         int removed_count = removed_objects.size();
1958         int added_count   = added_objects.size();
1959
1960         if (removed_objects.empty() && added_objects.empty())
1961                 return;
1962
1963         char buf[4];
1964         std::string data;
1965
1966         // Handle removed objects
1967         writeU16((u8*)buf, removed_objects.size());
1968         data.append(buf, 2);
1969         while (!removed_objects.empty()) {
1970                 // Get object
1971                 u16 id = removed_objects.front();
1972                 ServerActiveObject* obj = m_env->getActiveObject(id);
1973
1974                 // Add to data buffer for sending
1975                 writeU16((u8*)buf, id);
1976                 data.append(buf, 2);
1977
1978                 // Remove from known objects
1979                 client->m_known_objects.erase(id);
1980
1981                 if (obj && obj->m_known_by_count > 0)
1982                         obj->m_known_by_count--;
1983
1984                 removed_objects.pop();
1985         }
1986
1987         // Handle added objects
1988         writeU16((u8*)buf, added_objects.size());
1989         data.append(buf, 2);
1990         while (!added_objects.empty()) {
1991                 // Get object
1992                 u16 id = added_objects.front();
1993                 ServerActiveObject *obj = m_env->getActiveObject(id);
1994                 added_objects.pop();
1995
1996                 if (!obj) {
1997                         warningstream << FUNCTION_NAME << ": NULL object id="
1998                                 << (int)id << std::endl;
1999                         continue;
2000                 }
2001
2002                 // Get object type
2003                 u8 type = obj->getSendType();
2004
2005                 // Add to data buffer for sending
2006                 writeU16((u8*)buf, id);
2007                 data.append(buf, 2);
2008                 writeU8((u8*)buf, type);
2009                 data.append(buf, 1);
2010
2011                 data.append(serializeLongString(
2012                         obj->getClientInitializationData(client->net_proto_version)));
2013
2014                 // Add to known objects
2015                 client->m_known_objects.insert(id);
2016
2017                 obj->m_known_by_count++;
2018         }
2019
2020         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, data.size(), client->peer_id);
2021         pkt.putRawString(data.c_str(), data.size());
2022         Send(&pkt);
2023
2024         verbosestream << "Server::SendActiveObjectRemoveAdd: "
2025                 << removed_count << " removed, " << added_count << " added, "
2026                 << "packet size is " << pkt.getSize() << std::endl;
2027 }
2028
2029 void Server::SendActiveObjectMessages(session_t peer_id, const std::string &datas,
2030                 bool reliable)
2031 {
2032         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
2033                         datas.size(), peer_id);
2034
2035         pkt.putRawString(datas.c_str(), datas.size());
2036
2037         m_clients.send(pkt.getPeerId(),
2038                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
2039                         &pkt, reliable);
2040 }
2041
2042 void Server::SendCSMRestrictionFlags(session_t peer_id)
2043 {
2044         NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
2045                 sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
2046         pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
2047         Send(&pkt);
2048 }
2049
2050 void Server::SendPlayerSpeed(session_t peer_id, const v3f &added_vel)
2051 {
2052         NetworkPacket pkt(TOCLIENT_PLAYER_SPEED, 0, peer_id);
2053         pkt << added_vel;
2054         Send(&pkt);
2055 }
2056
2057 inline s32 Server::nextSoundId()
2058 {
2059         s32 ret = m_next_sound_id;
2060         if (m_next_sound_id == INT32_MAX)
2061                 m_next_sound_id = 0; // signed overflow is undefined
2062         else
2063                 m_next_sound_id++;
2064         return ret;
2065 }
2066
2067 s32 Server::playSound(const SimpleSoundSpec &spec,
2068                 const ServerSoundParams &params, bool ephemeral)
2069 {
2070         // Find out initial position of sound
2071         bool pos_exists = false;
2072         v3f pos = params.getPos(m_env, &pos_exists);
2073         // If position is not found while it should be, cancel sound
2074         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
2075                 return -1;
2076
2077         // Filter destination clients
2078         std::vector<session_t> dst_clients;
2079         if (!params.to_player.empty()) {
2080                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
2081                 if(!player){
2082                         infostream<<"Server::playSound: Player \""<<params.to_player
2083                                         <<"\" not found"<<std::endl;
2084                         return -1;
2085                 }
2086                 if (player->getPeerId() == PEER_ID_INEXISTENT) {
2087                         infostream<<"Server::playSound: Player \""<<params.to_player
2088                                         <<"\" not connected"<<std::endl;
2089                         return -1;
2090                 }
2091                 dst_clients.push_back(player->getPeerId());
2092         } else {
2093                 std::vector<session_t> clients = m_clients.getClientIDs();
2094
2095                 for (const session_t client_id : clients) {
2096                         RemotePlayer *player = m_env->getPlayer(client_id);
2097                         if (!player)
2098                                 continue;
2099                         if (!params.exclude_player.empty() &&
2100                                         params.exclude_player == player->getName())
2101                                 continue;
2102
2103                         PlayerSAO *sao = player->getPlayerSAO();
2104                         if (!sao)
2105                                 continue;
2106
2107                         if (pos_exists) {
2108                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2109                                                 params.max_hear_distance)
2110                                         continue;
2111                         }
2112                         dst_clients.push_back(client_id);
2113                 }
2114         }
2115
2116         if(dst_clients.empty())
2117                 return -1;
2118
2119         // Create the sound
2120         s32 id;
2121         ServerPlayingSound *psound = nullptr;
2122         if (ephemeral) {
2123                 id = -1; // old clients will still use this, so pick a reserved ID
2124         } else {
2125                 id = nextSoundId();
2126                 // The sound will exist as a reference in m_playing_sounds
2127                 m_playing_sounds[id] = ServerPlayingSound();
2128                 psound = &m_playing_sounds[id];
2129                 psound->params = params;
2130                 psound->spec = spec;
2131         }
2132
2133         float gain = params.gain * spec.gain;
2134         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2135         pkt << id << spec.name << gain
2136                         << (u8) params.type << pos << params.object
2137                         << params.loop << params.fade << params.pitch
2138                         << ephemeral;
2139
2140         bool as_reliable = !ephemeral;
2141
2142         for (const u16 dst_client : dst_clients) {
2143                 if (psound)
2144                         psound->clients.insert(dst_client);
2145                 m_clients.send(dst_client, 0, &pkt, as_reliable);
2146         }
2147         return id;
2148 }
2149 void Server::stopSound(s32 handle)
2150 {
2151         // Get sound reference
2152         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2153                 m_playing_sounds.find(handle);
2154         if (i == m_playing_sounds.end())
2155                 return;
2156         ServerPlayingSound &psound = i->second;
2157
2158         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2159         pkt << handle;
2160
2161         for (std::unordered_set<session_t>::const_iterator si = psound.clients.begin();
2162                         si != psound.clients.end(); ++si) {
2163                 // Send as reliable
2164                 m_clients.send(*si, 0, &pkt, true);
2165         }
2166         // Remove sound reference
2167         m_playing_sounds.erase(i);
2168 }
2169
2170 void Server::fadeSound(s32 handle, float step, float gain)
2171 {
2172         // Get sound reference
2173         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2174                 m_playing_sounds.find(handle);
2175         if (i == m_playing_sounds.end())
2176                 return;
2177
2178         ServerPlayingSound &psound = i->second;
2179         psound.params.gain = gain;
2180
2181         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2182         pkt << handle << step << gain;
2183
2184         // Backwards compability
2185         bool play_sound = gain > 0;
2186         ServerPlayingSound compat_psound = psound;
2187         compat_psound.clients.clear();
2188
2189         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2190         compat_pkt << handle;
2191
2192         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2193                         it != psound.clients.end();) {
2194                 if (m_clients.getProtocolVersion(*it) >= 32) {
2195                         // Send as reliable
2196                         m_clients.send(*it, 0, &pkt, true);
2197                         ++it;
2198                 } else {
2199                         compat_psound.clients.insert(*it);
2200                         // Stop old sound
2201                         m_clients.send(*it, 0, &compat_pkt, true);
2202                         psound.clients.erase(it++);
2203                 }
2204         }
2205
2206         // Remove sound reference
2207         if (!play_sound || psound.clients.empty())
2208                 m_playing_sounds.erase(i);
2209
2210         if (play_sound && !compat_psound.clients.empty()) {
2211                 // Play new sound volume on older clients
2212                 playSound(compat_psound.spec, compat_psound.params);
2213         }
2214 }
2215
2216 void Server::sendRemoveNode(v3s16 p, std::unordered_set<u16> *far_players,
2217                 float far_d_nodes)
2218 {
2219         float maxd = far_d_nodes * BS;
2220         v3f p_f = intToFloat(p, BS);
2221         v3s16 block_pos = getNodeBlockPos(p);
2222
2223         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2224         pkt << p;
2225
2226         std::vector<session_t> clients = m_clients.getClientIDs();
2227         m_clients.lock();
2228
2229         for (session_t client_id : clients) {
2230                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2231                 if (!client)
2232                         continue;
2233
2234                 RemotePlayer *player = m_env->getPlayer(client_id);
2235                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2236
2237                 // If player is far away, only set modified blocks not sent
2238                 if (!client->isBlockSent(block_pos) || (sao &&
2239                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2240                         if (far_players)
2241                                 far_players->emplace(client_id);
2242                         else
2243                                 client->SetBlockNotSent(block_pos);
2244                         continue;
2245                 }
2246
2247                 // Send as reliable
2248                 m_clients.send(client_id, 0, &pkt, true);
2249         }
2250
2251         m_clients.unlock();
2252 }
2253
2254 void Server::sendAddNode(v3s16 p, MapNode n, std::unordered_set<u16> *far_players,
2255                 float far_d_nodes, bool remove_metadata)
2256 {
2257         float maxd = far_d_nodes * BS;
2258         v3f p_f = intToFloat(p, BS);
2259         v3s16 block_pos = getNodeBlockPos(p);
2260
2261         NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2262         pkt << p << n.param0 << n.param1 << n.param2
2263                         << (u8) (remove_metadata ? 0 : 1);
2264
2265         std::vector<session_t> clients = m_clients.getClientIDs();
2266         m_clients.lock();
2267
2268         for (session_t client_id : clients) {
2269                 RemoteClient *client = m_clients.lockedGetClientNoEx(client_id);
2270                 if (!client)
2271                         continue;
2272
2273                 RemotePlayer *player = m_env->getPlayer(client_id);
2274                 PlayerSAO *sao = player ? player->getPlayerSAO() : nullptr;
2275
2276                 // If player is far away, only set modified blocks not sent
2277                 if (!client->isBlockSent(block_pos) || (sao &&
2278                                 sao->getBasePosition().getDistanceFrom(p_f) > maxd)) {
2279                         if (far_players)
2280                                 far_players->emplace(client_id);
2281                         else
2282                                 client->SetBlockNotSent(block_pos);
2283                         continue;
2284                 }
2285
2286                 // Send as reliable
2287                 m_clients.send(client_id, 0, &pkt, true);
2288         }
2289
2290         m_clients.unlock();
2291 }
2292
2293 void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far_d_nodes)
2294 {
2295         float maxd = far_d_nodes * BS;
2296         NodeMetadataList meta_updates_list(false);
2297         std::vector<session_t> clients = m_clients.getClientIDs();
2298
2299         m_clients.lock();
2300
2301         for (session_t i : clients) {
2302                 RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2303                 if (!client)
2304                         continue;
2305
2306                 ServerActiveObject *player = m_env->getActiveObject(i);
2307                 v3f player_pos = player ? player->getBasePosition() : v3f();
2308
2309                 for (const v3s16 &pos : meta_updates) {
2310                         NodeMetadata *meta = m_env->getMap().getNodeMetadata(pos);
2311
2312                         if (!meta)
2313                                 continue;
2314
2315                         v3s16 block_pos = getNodeBlockPos(pos);
2316                         if (!client->isBlockSent(block_pos) || (player &&
2317                                         player_pos.getDistanceFrom(intToFloat(pos, BS)) > maxd)) {
2318                                 client->SetBlockNotSent(block_pos);
2319                                 continue;
2320                         }
2321
2322                         // Add the change to send list
2323                         meta_updates_list.set(pos, meta);
2324                 }
2325                 if (meta_updates_list.size() == 0)
2326                         continue;
2327
2328                 // Send the meta changes
2329                 std::ostringstream os(std::ios::binary);
2330                 meta_updates_list.serialize(os, client->net_proto_version, false, true);
2331                 std::ostringstream oss(std::ios::binary);
2332                 compressZlib(os.str(), oss);
2333
2334                 NetworkPacket pkt(TOCLIENT_NODEMETA_CHANGED, 0);
2335                 pkt.putLongString(oss.str());
2336                 m_clients.send(i, 0, &pkt, true);
2337
2338                 meta_updates_list.clear();
2339         }
2340
2341         m_clients.unlock();
2342 }
2343
2344 void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
2345                 u16 net_proto_version)
2346 {
2347         /*
2348                 Create a packet with the block in the right format
2349         */
2350
2351         std::ostringstream os(std::ios_base::binary);
2352         block->serialize(os, ver, false);
2353         block->serializeNetworkSpecific(os);
2354         std::string s = os.str();
2355
2356         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2357
2358         pkt << block->getPos();
2359         pkt.putRawString(s.c_str(), s.size());
2360         Send(&pkt);
2361 }
2362
2363 void Server::SendBlocks(float dtime)
2364 {
2365         MutexAutoLock envlock(m_env_mutex);
2366         //TODO check if one big lock could be faster then multiple small ones
2367
2368         std::vector<PrioritySortedBlockTransfer> queue;
2369
2370         u32 total_sending = 0;
2371
2372         {
2373                 ScopeProfiler sp2(g_profiler, "Server::SendBlocks(): Collect list");
2374
2375                 std::vector<session_t> clients = m_clients.getClientIDs();
2376
2377                 m_clients.lock();
2378                 for (const session_t client_id : clients) {
2379                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2380
2381                         if (!client)
2382                                 continue;
2383
2384                         total_sending += client->getSendingCount();
2385                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2386                 }
2387                 m_clients.unlock();
2388         }
2389
2390         // Sort.
2391         // Lowest priority number comes first.
2392         // Lowest is most important.
2393         std::sort(queue.begin(), queue.end());
2394
2395         m_clients.lock();
2396
2397         // Maximal total count calculation
2398         // The per-client block sends is halved with the maximal online users
2399         u32 max_blocks_to_send = (m_env->getPlayerCount() + g_settings->getU32("max_users")) *
2400                 g_settings->getU32("max_simultaneous_block_sends_per_client") / 4 + 1;
2401
2402         ScopeProfiler sp(g_profiler, "Server::SendBlocks(): Send to clients");
2403         Map &map = m_env->getMap();
2404
2405         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2406                 if (total_sending >= max_blocks_to_send)
2407                         break;
2408
2409                 MapBlock *block = map.getBlockNoCreateNoEx(block_to_send.pos);
2410                 if (!block)
2411                         continue;
2412
2413                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2414                                 CS_Active);
2415                 if (!client)
2416                         continue;
2417
2418                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2419                                 client->net_proto_version);
2420
2421                 client->SentBlock(block_to_send.pos);
2422                 total_sending++;
2423         }
2424         m_clients.unlock();
2425 }
2426
2427 bool Server::SendBlock(session_t peer_id, const v3s16 &blockpos)
2428 {
2429         MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2430         if (!block)
2431                 return false;
2432
2433         m_clients.lock();
2434         RemoteClient *client = m_clients.lockedGetClientNoEx(peer_id, CS_Active);
2435         if (!client || client->isBlockSent(blockpos)) {
2436                 m_clients.unlock();
2437                 return false;
2438         }
2439         SendBlockNoLock(peer_id, block, client->serialization_version,
2440                         client->net_proto_version);
2441         m_clients.unlock();
2442
2443         return true;
2444 }
2445
2446 void Server::fillMediaCache()
2447 {
2448         infostream<<"Server: Calculating media file checksums"<<std::endl;
2449
2450         // Collect all media file paths
2451         std::vector<std::string> paths;
2452         m_modmgr->getModsMediaPaths(paths);
2453         fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
2454         fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2455
2456         // Collect media file information from paths into cache
2457         for (const std::string &mediapath : paths) {
2458                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2459                 for (const fs::DirListNode &dln : dirlist) {
2460                         if (dln.dir) // Ignode dirs
2461                                 continue;
2462                         std::string filename = dln.name;
2463                         // If name contains illegal characters, ignore the file
2464                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2465                                 infostream<<"Server: ignoring illegal file name: \""
2466                                                 << filename << "\"" << std::endl;
2467                                 continue;
2468                         }
2469                         // If name is not in a supported format, ignore it
2470                         const char *supported_ext[] = {
2471                                 ".png", ".jpg", ".bmp", ".tga",
2472                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2473                                 ".ogg",
2474                                 ".x", ".b3d", ".md2", ".obj",
2475                                 // Custom translation file format
2476                                 ".tr",
2477                                 NULL
2478                         };
2479                         if (removeStringEnd(filename, supported_ext).empty()){
2480                                 infostream << "Server: ignoring unsupported file extension: \""
2481                                                 << filename << "\"" << std::endl;
2482                                 continue;
2483                         }
2484                         // Ok, attempt to load the file and add to cache
2485                         std::string filepath;
2486                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2487
2488                         // Read data
2489                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2490                         if (!fis.good()) {
2491                                 errorstream << "Server::fillMediaCache(): Could not open \""
2492                                                 << filename << "\" for reading" << std::endl;
2493                                 continue;
2494                         }
2495                         std::ostringstream tmp_os(std::ios_base::binary);
2496                         bool bad = false;
2497                         for(;;) {
2498                                 char buf[1024];
2499                                 fis.read(buf, 1024);
2500                                 std::streamsize len = fis.gcount();
2501                                 tmp_os.write(buf, len);
2502                                 if (fis.eof())
2503                                         break;
2504                                 if (!fis.good()) {
2505                                         bad = true;
2506                                         break;
2507                                 }
2508                         }
2509                         if(bad) {
2510                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2511                                                 << filename << "\"" << std::endl;
2512                                 continue;
2513                         }
2514                         if(tmp_os.str().length() == 0) {
2515                                 errorstream << "Server::fillMediaCache(): Empty file \""
2516                                                 << filepath << "\"" << std::endl;
2517                                 continue;
2518                         }
2519
2520                         SHA1 sha1;
2521                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2522
2523                         unsigned char *digest = sha1.getDigest();
2524                         std::string sha1_base64 = base64_encode(digest, 20);
2525                         std::string sha1_hex = hex_encode((char*)digest, 20);
2526                         free(digest);
2527
2528                         // Put in list
2529                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2530                         verbosestream << "Server: " << sha1_hex << " is " << filename
2531                                         << std::endl;
2532                 }
2533         }
2534 }
2535
2536 void Server::sendMediaAnnouncement(session_t peer_id, const std::string &lang_code)
2537 {
2538         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2539                 << std::endl;
2540
2541         // Make packet
2542         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2543
2544         u16 media_sent = 0;
2545         std::string lang_suffix;
2546         lang_suffix.append(".").append(lang_code).append(".tr");
2547         for (const auto &i : m_media) {
2548                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2549                         continue;
2550                 media_sent++;
2551         }
2552
2553         pkt << media_sent;
2554
2555         for (const auto &i : m_media) {
2556                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2557                         continue;
2558                 pkt << i.first << i.second.sha1_digest;
2559         }
2560
2561         pkt << g_settings->get("remote_media");
2562         Send(&pkt);
2563 }
2564
2565 struct SendableMedia
2566 {
2567         std::string name;
2568         std::string path;
2569         std::string data;
2570
2571         SendableMedia(const std::string &name_="", const std::string &path_="",
2572                       const std::string &data_=""):
2573                 name(name_),
2574                 path(path_),
2575                 data(data_)
2576         {}
2577 };
2578
2579 void Server::sendRequestedMedia(session_t peer_id,
2580                 const std::vector<std::string> &tosend)
2581 {
2582         verbosestream<<"Server::sendRequestedMedia(): "
2583                         <<"Sending files to client"<<std::endl;
2584
2585         /* Read files */
2586
2587         // Put 5kB in one bunch (this is not accurate)
2588         u32 bytes_per_bunch = 5000;
2589
2590         std::vector< std::vector<SendableMedia> > file_bunches;
2591         file_bunches.emplace_back();
2592
2593         u32 file_size_bunch_total = 0;
2594
2595         for (const std::string &name : tosend) {
2596                 if (m_media.find(name) == m_media.end()) {
2597                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2598                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2599                         continue;
2600                 }
2601
2602                 //TODO get path + name
2603                 std::string tpath = m_media[name].path;
2604
2605                 // Read data
2606                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2607                 if(!fis.good()){
2608                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2609                                         <<tpath<<"\" for reading"<<std::endl;
2610                         continue;
2611                 }
2612                 std::ostringstream tmp_os(std::ios_base::binary);
2613                 bool bad = false;
2614                 for(;;) {
2615                         char buf[1024];
2616                         fis.read(buf, 1024);
2617                         std::streamsize len = fis.gcount();
2618                         tmp_os.write(buf, len);
2619                         file_size_bunch_total += len;
2620                         if(fis.eof())
2621                                 break;
2622                         if(!fis.good()) {
2623                                 bad = true;
2624                                 break;
2625                         }
2626                 }
2627                 if (bad) {
2628                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2629                                         <<name<<"\""<<std::endl;
2630                         continue;
2631                 }
2632                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2633                                 <<tname<<"\""<<std::endl;*/
2634                 // Put in list
2635                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2636
2637                 // Start next bunch if got enough data
2638                 if(file_size_bunch_total >= bytes_per_bunch) {
2639                         file_bunches.emplace_back();
2640                         file_size_bunch_total = 0;
2641                 }
2642
2643         }
2644
2645         /* Create and send packets */
2646
2647         u16 num_bunches = file_bunches.size();
2648         for (u16 i = 0; i < num_bunches; i++) {
2649                 /*
2650                         u16 command
2651                         u16 total number of texture bunches
2652                         u16 index of this bunch
2653                         u32 number of files in this bunch
2654                         for each file {
2655                                 u16 length of name
2656                                 string name
2657                                 u32 length of data
2658                                 data
2659                         }
2660                 */
2661
2662                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2663                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2664
2665                 for (const SendableMedia &j : file_bunches[i]) {
2666                         pkt << j.name;
2667                         pkt.putLongString(j.data);
2668                 }
2669
2670                 verbosestream << "Server::sendRequestedMedia(): bunch "
2671                                 << i << "/" << num_bunches
2672                                 << " files=" << file_bunches[i].size()
2673                                 << " size="  << pkt.getSize() << std::endl;
2674                 Send(&pkt);
2675         }
2676 }
2677
2678 void Server::sendDetachedInventory(const std::string &name, session_t peer_id)
2679 {
2680         const auto &inv_it = m_detached_inventories.find(name);
2681         const auto &player_it = m_detached_inventories_player.find(name);
2682
2683         if (player_it == m_detached_inventories_player.end() ||
2684                         player_it->second.empty()) {
2685                 // OK. Send to everyone
2686         } else {
2687                 if (!m_env)
2688                         return; // Mods are not done loading
2689
2690                 RemotePlayer *p = m_env->getPlayer(player_it->second.c_str());
2691                 if (!p)
2692                         return; // Player is offline
2693
2694                 if (peer_id != PEER_ID_INEXISTENT && peer_id != p->getPeerId())
2695                         return; // Caller requested send to a different player, so don't send.
2696
2697                 peer_id = p->getPeerId();
2698         }
2699
2700         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2701         pkt << name;
2702
2703         if (inv_it == m_detached_inventories.end()) {
2704                 pkt << false; // Remove inventory
2705         } else {
2706                 pkt << true; // Update inventory
2707
2708                 // Serialization & NetworkPacket isn't a love story
2709                 std::ostringstream os(std::ios_base::binary);
2710                 inv_it->second->serialize(os);
2711                 inv_it->second->setModified(false);
2712
2713                 const std::string &os_str = os.str();
2714                 pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
2715                 pkt.putRawString(os_str);
2716         }
2717
2718         if (peer_id == PEER_ID_INEXISTENT)
2719                 m_clients.sendToAll(&pkt);
2720         else
2721                 Send(&pkt);
2722 }
2723
2724 void Server::sendDetachedInventories(session_t peer_id, bool incremental)
2725 {
2726         for (const auto &detached_inventory : m_detached_inventories) {
2727                 const std::string &name = detached_inventory.first;
2728                 if (incremental) {
2729                         Inventory *inv = detached_inventory.second;
2730                         if (!inv || !inv->checkModified())
2731                                 continue;
2732                 }
2733
2734                 sendDetachedInventory(name, peer_id);
2735         }
2736 }
2737
2738 /*
2739         Something random
2740 */
2741
2742 void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
2743 {
2744         PlayerSAO *playersao = getPlayerSAO(peer_id);
2745         assert(playersao);
2746
2747         infostream << "Server::DiePlayer(): Player "
2748                         << playersao->getPlayer()->getName()
2749                         << " dies" << std::endl;
2750
2751         playersao->setHP(0, reason);
2752         playersao->clearParentAttachment();
2753
2754         // Trigger scripted stuff
2755         m_script->on_dieplayer(playersao, reason);
2756
2757         SendPlayerHP(peer_id);
2758         SendDeathscreen(peer_id, false, v3f(0,0,0));
2759 }
2760
2761 void Server::RespawnPlayer(session_t peer_id)
2762 {
2763         PlayerSAO *playersao = getPlayerSAO(peer_id);
2764         assert(playersao);
2765
2766         infostream << "Server::RespawnPlayer(): Player "
2767                         << playersao->getPlayer()->getName()
2768                         << " respawns" << std::endl;
2769
2770         playersao->setHP(playersao->accessObjectProperties()->hp_max,
2771                         PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
2772         playersao->setBreath(playersao->accessObjectProperties()->breath_max);
2773
2774         bool repositioned = m_script->on_respawnplayer(playersao);
2775         if (!repositioned) {
2776                 // setPos will send the new position to client
2777                 playersao->setPos(findSpawnPos());
2778         }
2779
2780         SendPlayerHP(peer_id);
2781 }
2782
2783
2784 void Server::DenySudoAccess(session_t peer_id)
2785 {
2786         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2787         Send(&pkt);
2788 }
2789
2790
2791 void Server::DenyAccessVerCompliant(session_t peer_id, u16 proto_ver, AccessDeniedCode reason,
2792                 const std::string &str_reason, bool reconnect)
2793 {
2794         SendAccessDenied(peer_id, reason, str_reason, reconnect);
2795
2796         m_clients.event(peer_id, CSE_SetDenied);
2797         DisconnectPeer(peer_id);
2798 }
2799
2800
2801 void Server::DenyAccess(session_t peer_id, AccessDeniedCode reason,
2802                 const std::string &custom_reason)
2803 {
2804         SendAccessDenied(peer_id, reason, custom_reason);
2805         m_clients.event(peer_id, CSE_SetDenied);
2806         DisconnectPeer(peer_id);
2807 }
2808
2809 // 13/03/15: remove this function when protocol version 25 will become
2810 // the minimum version for MT users, maybe in 1 year
2811 void Server::DenyAccess_Legacy(session_t peer_id, const std::wstring &reason)
2812 {
2813         SendAccessDenied_Legacy(peer_id, reason);
2814         m_clients.event(peer_id, CSE_SetDenied);
2815         DisconnectPeer(peer_id);
2816 }
2817
2818 void Server::DisconnectPeer(session_t peer_id)
2819 {
2820         m_modchannel_mgr->leaveAllChannels(peer_id);
2821         m_con->DisconnectPeer(peer_id);
2822 }
2823
2824 void Server::acceptAuth(session_t peer_id, bool forSudoMode)
2825 {
2826         if (!forSudoMode) {
2827                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2828
2829                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2830
2831                 // Right now, the auth mechs don't change between login and sudo mode.
2832                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2833                 client->allowed_sudo_mechs = sudo_auth_mechs;
2834
2835                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2836                                 << g_settings->getFloat("dedicated_server_step")
2837                                 << sudo_auth_mechs;
2838
2839                 Send(&resp_pkt);
2840                 m_clients.event(peer_id, CSE_AuthAccept);
2841         } else {
2842                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2843
2844                 // We only support SRP right now
2845                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2846
2847                 resp_pkt << sudo_auth_mechs;
2848                 Send(&resp_pkt);
2849                 m_clients.event(peer_id, CSE_SudoSuccess);
2850         }
2851 }
2852
2853 void Server::DeleteClient(session_t peer_id, ClientDeletionReason reason)
2854 {
2855         std::wstring message;
2856         {
2857                 /*
2858                         Clear references to playing sounds
2859                 */
2860                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2861                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2862                         ServerPlayingSound &psound = i->second;
2863                         psound.clients.erase(peer_id);
2864                         if (psound.clients.empty())
2865                                 m_playing_sounds.erase(i++);
2866                         else
2867                                 ++i;
2868                 }
2869
2870                 // clear formspec info so the next client can't abuse the current state
2871                 m_formspec_state_data.erase(peer_id);
2872
2873                 RemotePlayer *player = m_env->getPlayer(peer_id);
2874
2875                 /* Run scripts and remove from environment */
2876                 if (player) {
2877                         PlayerSAO *playersao = player->getPlayerSAO();
2878                         assert(playersao);
2879
2880                         playersao->clearChildAttachments();
2881                         playersao->clearParentAttachment();
2882
2883                         // inform connected clients
2884                         const std::string &player_name = player->getName();
2885                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2886                         // (u16) 1 + std::string represents a vector serialization representation
2887                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << player_name;
2888                         m_clients.sendToAll(&notice);
2889                         // run scripts
2890                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2891
2892                         playersao->disconnected();
2893                 }
2894
2895                 /*
2896                         Print out action
2897                 */
2898                 {
2899                         if (player && reason != CDR_DENY) {
2900                                 std::ostringstream os(std::ios_base::binary);
2901                                 std::vector<session_t> clients = m_clients.getClientIDs();
2902
2903                                 for (const session_t client_id : clients) {
2904                                         // Get player
2905                                         RemotePlayer *player = m_env->getPlayer(client_id);
2906                                         if (!player)
2907                                                 continue;
2908
2909                                         // Get name of player
2910                                         os << player->getName() << " ";
2911                                 }
2912
2913                                 std::string name = player->getName();
2914                                 actionstream << name << " "
2915                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2916                                                 << " List of players: " << os.str() << std::endl;
2917                                 if (m_admin_chat)
2918                                         m_admin_chat->outgoing_queue.push_back(
2919                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2920                         }
2921                 }
2922                 {
2923                         MutexAutoLock env_lock(m_env_mutex);
2924                         m_clients.DeleteClient(peer_id);
2925                 }
2926         }
2927
2928         // Send leave chat message to all remaining clients
2929         if (!message.empty()) {
2930                 SendChatMessage(PEER_ID_INEXISTENT,
2931                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2932         }
2933 }
2934
2935 void Server::UpdateCrafting(RemotePlayer *player)
2936 {
2937         InventoryList *clist = player->inventory.getList("craft");
2938         if (!clist || clist->getSize() == 0)
2939                 return;
2940
2941         if (!clist->checkModified()) {
2942                 verbosestream << "Skip Server::UpdateCrafting(): list unmodified" << std::endl;
2943                 return;
2944         }
2945
2946         // Get a preview for crafting
2947         ItemStack preview;
2948         InventoryLocation loc;
2949         loc.setPlayer(player->getName());
2950         std::vector<ItemStack> output_replacements;
2951         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2952         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2953                         clist, loc);
2954
2955         InventoryList *plist = player->inventory.getList("craftpreview");
2956         if (plist && plist->getSize() >= 1) {
2957                 // Put the new preview in
2958                 plist->changeItem(0, preview);
2959         }
2960 }
2961
2962 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2963 {
2964         if (evt->type == CET_NICK_ADD) {
2965                 // The terminal informed us of its nick choice
2966                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2967                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2968                         errorstream << "You haven't set up an account." << std::endl
2969                                 << "Please log in using the client as '"
2970                                 << m_admin_nick << "' with a secure password." << std::endl
2971                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2972                                 << "and everybody can claim the user account instead of you," << std::endl
2973                                 << "giving them full control over this server." << std::endl;
2974                 }
2975         } else {
2976                 assert(evt->type == CET_CHAT);
2977                 handleAdminChat((ChatEventChat *)evt);
2978         }
2979 }
2980
2981 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2982         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2983 {
2984         // If something goes wrong, this player is to blame
2985         RollbackScopeActor rollback_scope(m_rollback,
2986                         std::string("player:") + name);
2987
2988         if (g_settings->getBool("strip_color_codes"))
2989                 wmessage = unescape_enriched(wmessage);
2990
2991         if (player) {
2992                 switch (player->canSendChatMessage()) {
2993                 case RPLAYER_CHATRESULT_FLOODING: {
2994                         std::wstringstream ws;
2995                         ws << L"You cannot send more messages. You are limited to "
2996                                         << g_settings->getFloat("chat_message_limit_per_10sec")
2997                                         << L" messages per 10 seconds.";
2998                         return ws.str();
2999                 }
3000                 case RPLAYER_CHATRESULT_KICK:
3001                         DenyAccess_Legacy(player->getPeerId(),
3002                                         L"You have been kicked due to message flooding.");
3003                         return L"";
3004                 case RPLAYER_CHATRESULT_OK:
3005                         break;
3006                 default:
3007                         FATAL_ERROR("Unhandled chat filtering result found.");
3008                 }
3009         }
3010
3011         if (m_max_chatmessage_length > 0
3012                         && wmessage.length() > m_max_chatmessage_length) {
3013                 return L"Your message exceed the maximum chat message limit set on the server. "
3014                                 L"It was refused. Send a shorter message";
3015         }
3016
3017         auto message = trim(wide_to_utf8(wmessage));
3018         if (message.find_first_of("\n\r") != std::wstring::npos) {
3019                 return L"New lines are not permitted in chat messages";
3020         }
3021
3022         // Run script hook, exit if script ate the chat message
3023         if (m_script->on_chat_message(name, message))
3024                 return L"";
3025
3026         // Line to send
3027         std::wstring line;
3028         // Whether to send line to the player that sent the message, or to all players
3029         bool broadcast_line = true;
3030
3031         if (check_shout_priv && !checkPriv(name, "shout")) {
3032                 line += L"-!- You don't have permission to shout.";
3033                 broadcast_line = false;
3034         } else {
3035                 line += narrow_to_wide(m_script->formatChatMessage(name,
3036                                 wide_to_narrow(wmessage)));
3037         }
3038
3039         /*
3040                 Tell calling method to send the message to sender
3041         */
3042         if (!broadcast_line)
3043                 return line;
3044
3045         /*
3046                 Send the message to others
3047         */
3048         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
3049
3050         std::vector<session_t> clients = m_clients.getClientIDs();
3051
3052         /*
3053                 Send the message back to the inital sender
3054                 if they are using protocol version >= 29
3055         */
3056
3057         session_t peer_id_to_avoid_sending =
3058                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
3059
3060         if (player && player->protocol_version >= 29)
3061                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
3062
3063         for (u16 cid : clients) {
3064                 if (cid != peer_id_to_avoid_sending)
3065                         SendChatMessage(cid, ChatMessage(line));
3066         }
3067         return L"";
3068 }
3069
3070 void Server::handleAdminChat(const ChatEventChat *evt)
3071 {
3072         std::string name = evt->nick;
3073         std::wstring wname = utf8_to_wide(name);
3074         std::wstring wmessage = evt->evt_msg;
3075
3076         std::wstring answer = handleChat(name, wname, wmessage);
3077
3078         // If asked to send answer to sender
3079         if (!answer.empty()) {
3080                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
3081         }
3082 }
3083
3084 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
3085 {
3086         RemoteClient *client = getClientNoEx(peer_id,state_min);
3087         if(!client)
3088                 throw ClientNotFoundException("Client not found");
3089
3090         return client;
3091 }
3092 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
3093 {
3094         return m_clients.getClientNoEx(peer_id, state_min);
3095 }
3096
3097 std::string Server::getPlayerName(session_t peer_id)
3098 {
3099         RemotePlayer *player = m_env->getPlayer(peer_id);
3100         if (!player)
3101                 return "[id="+itos(peer_id)+"]";
3102         return player->getName();
3103 }
3104
3105 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
3106 {
3107         RemotePlayer *player = m_env->getPlayer(peer_id);
3108         if (!player)
3109                 return NULL;
3110         return player->getPlayerSAO();
3111 }
3112
3113 std::wstring Server::getStatusString()
3114 {
3115         std::wostringstream os(std::ios_base::binary);
3116         os << L"# Server: ";
3117         // Version
3118         os << L"version=" << narrow_to_wide(g_version_string);
3119         // Uptime
3120         os << L", uptime=" << m_uptime.get();
3121         // Max lag estimate
3122         os << L", max_lag=" << (m_env ? m_env->getMaxLagEstimate() : 0);
3123
3124         // Information about clients
3125         bool first = true;
3126         os << L", clients={";
3127         if (m_env) {
3128                 std::vector<session_t> clients = m_clients.getClientIDs();
3129                 for (session_t client_id : clients) {
3130                         RemotePlayer *player = m_env->getPlayer(client_id);
3131
3132                         // Get name of player
3133                         std::wstring name = L"unknown";
3134                         if (player)
3135                                 name = narrow_to_wide(player->getName());
3136
3137                         // Add name to information string
3138                         if (!first)
3139                                 os << L", ";
3140                         else
3141                                 first = false;
3142
3143                         os << name;
3144                 }
3145         }
3146         os << L"}";
3147
3148         if (m_env && !((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
3149                 os << std::endl << L"# Server: " << " WARNING: Map saving is disabled.";
3150
3151         if (!g_settings->get("motd").empty())
3152                 os << std::endl << L"# Server: " << narrow_to_wide(g_settings->get("motd"));
3153
3154         return os.str();
3155 }
3156
3157 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3158 {
3159         std::set<std::string> privs;
3160         m_script->getAuth(name, NULL, &privs);
3161         return privs;
3162 }
3163
3164 bool Server::checkPriv(const std::string &name, const std::string &priv)
3165 {
3166         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3167         return (privs.count(priv) != 0);
3168 }
3169
3170 void Server::reportPrivsModified(const std::string &name)
3171 {
3172         if (name.empty()) {
3173                 std::vector<session_t> clients = m_clients.getClientIDs();
3174                 for (const session_t client_id : clients) {
3175                         RemotePlayer *player = m_env->getPlayer(client_id);
3176                         reportPrivsModified(player->getName());
3177                 }
3178         } else {
3179                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3180                 if (!player)
3181                         return;
3182                 SendPlayerPrivileges(player->getPeerId());
3183                 PlayerSAO *sao = player->getPlayerSAO();
3184                 if(!sao)
3185                         return;
3186                 sao->updatePrivileges(
3187                                 getPlayerEffectivePrivs(name),
3188                                 isSingleplayer());
3189         }
3190 }
3191
3192 void Server::reportInventoryFormspecModified(const std::string &name)
3193 {
3194         RemotePlayer *player = m_env->getPlayer(name.c_str());
3195         if (!player)
3196                 return;
3197         SendPlayerInventoryFormspec(player->getPeerId());
3198 }
3199
3200 void Server::reportFormspecPrependModified(const std::string &name)
3201 {
3202         RemotePlayer *player = m_env->getPlayer(name.c_str());
3203         if (!player)
3204                 return;
3205         SendPlayerFormspecPrepend(player->getPeerId());
3206 }
3207
3208 void Server::setIpBanned(const std::string &ip, const std::string &name)
3209 {
3210         m_banmanager->add(ip, name);
3211 }
3212
3213 void Server::unsetIpBanned(const std::string &ip_or_name)
3214 {
3215         m_banmanager->remove(ip_or_name);
3216 }
3217
3218 std::string Server::getBanDescription(const std::string &ip_or_name)
3219 {
3220         return m_banmanager->getBanDescription(ip_or_name);
3221 }
3222
3223 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3224 {
3225         // m_env will be NULL if the server is initializing
3226         if (!m_env)
3227                 return;
3228
3229         if (m_admin_nick == name && !m_admin_nick.empty()) {
3230                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3231         }
3232
3233         RemotePlayer *player = m_env->getPlayer(name);
3234         if (!player) {
3235                 return;
3236         }
3237
3238         if (player->getPeerId() == PEER_ID_INEXISTENT)
3239                 return;
3240
3241         SendChatMessage(player->getPeerId(), ChatMessage(msg));
3242 }
3243
3244 bool Server::showFormspec(const char *playername, const std::string &formspec,
3245         const std::string &formname)
3246 {
3247         // m_env will be NULL if the server is initializing
3248         if (!m_env)
3249                 return false;
3250
3251         RemotePlayer *player = m_env->getPlayer(playername);
3252         if (!player)
3253                 return false;
3254
3255         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
3256         return true;
3257 }
3258
3259 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3260 {
3261         if (!player)
3262                 return -1;
3263
3264         u32 id = player->addHud(form);
3265
3266         SendHUDAdd(player->getPeerId(), id, form);
3267
3268         return id;
3269 }
3270
3271 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3272         if (!player)
3273                 return false;
3274
3275         HudElement* todel = player->removeHud(id);
3276
3277         if (!todel)
3278                 return false;
3279
3280         delete todel;
3281
3282         SendHUDRemove(player->getPeerId(), id);
3283         return true;
3284 }
3285
3286 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3287 {
3288         if (!player)
3289                 return false;
3290
3291         SendHUDChange(player->getPeerId(), id, stat, data);
3292         return true;
3293 }
3294
3295 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3296 {
3297         if (!player)
3298                 return false;
3299
3300         SendHUDSetFlags(player->getPeerId(), flags, mask);
3301         player->hud_flags &= ~mask;
3302         player->hud_flags |= flags;
3303
3304         PlayerSAO* playersao = player->getPlayerSAO();
3305
3306         if (!playersao)
3307                 return false;
3308
3309         m_script->player_event(playersao, "hud_changed");
3310         return true;
3311 }
3312
3313 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3314 {
3315         if (!player)
3316                 return false;
3317
3318         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3319                 return false;
3320
3321         player->setHotbarItemcount(hotbar_itemcount);
3322         std::ostringstream os(std::ios::binary);
3323         writeS32(os, hotbar_itemcount);
3324         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3325         return true;
3326 }
3327
3328 void Server::hudSetHotbarImage(RemotePlayer *player, const std::string &name)
3329 {
3330         if (!player)
3331                 return;
3332
3333         player->setHotbarImage(name);
3334         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3335 }
3336
3337 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, const std::string &name)
3338 {
3339         if (!player)
3340                 return;
3341
3342         player->setHotbarSelectedImage(name);
3343         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3344 }
3345
3346 Address Server::getPeerAddress(session_t peer_id)
3347 {
3348         return m_con->GetPeerAddress(peer_id);
3349 }
3350
3351 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3352                 v2s32 animation_frames[4], f32 frame_speed)
3353 {
3354         sanity_check(player);
3355         player->setLocalAnimations(animation_frames, frame_speed);
3356         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3357 }
3358
3359 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3360 {
3361         sanity_check(player);
3362         player->eye_offset_first = first;
3363         player->eye_offset_third = third;
3364         SendEyeOffset(player->getPeerId(), first, third);
3365 }
3366
3367 void Server::setSky(RemotePlayer *player, const SkyboxParams &params)
3368 {
3369         sanity_check(player);
3370         player->setSky(params);
3371         SendSetSky(player->getPeerId(), params);
3372 }
3373
3374 void Server::setSun(RemotePlayer *player, const SunParams &params)
3375 {
3376         sanity_check(player);
3377         player->setSun(params);
3378         SendSetSun(player->getPeerId(), params);
3379 }
3380
3381 void Server::setMoon(RemotePlayer *player, const MoonParams &params)
3382 {
3383         sanity_check(player);
3384         player->setMoon(params);
3385         SendSetMoon(player->getPeerId(), params);
3386 }
3387
3388 void Server::setStars(RemotePlayer *player, const StarParams &params)
3389 {
3390         sanity_check(player);
3391         player->setStars(params);
3392         SendSetStars(player->getPeerId(), params);
3393 }
3394
3395 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3396 {
3397         sanity_check(player);
3398         player->setCloudParams(params);
3399         SendCloudParams(player->getPeerId(), params);
3400 }
3401
3402 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3403         float ratio)
3404 {
3405         if (!player)
3406                 return false;
3407
3408         player->overrideDayNightRatio(do_override, ratio);
3409         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3410         return true;
3411 }
3412
3413 void Server::notifyPlayers(const std::wstring &msg)
3414 {
3415         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3416 }
3417
3418 void Server::spawnParticle(const std::string &playername, v3f pos,
3419         v3f velocity, v3f acceleration,
3420         float expirationtime, float size, bool
3421         collisiondetection, bool collision_removal, bool object_collision,
3422         bool vertical, const std::string &texture,
3423         const struct TileAnimationParams &animation, u8 glow)
3424 {
3425         // m_env will be NULL if the server is initializing
3426         if (!m_env)
3427                 return;
3428
3429         session_t peer_id = PEER_ID_INEXISTENT;
3430         u16 proto_ver = 0;
3431         if (!playername.empty()) {
3432                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3433                 if (!player)
3434                         return;
3435                 peer_id = player->getPeerId();
3436                 proto_ver = player->protocol_version;
3437         }
3438
3439         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3440                         expirationtime, size, collisiondetection, collision_removal,
3441                         object_collision, vertical, texture, animation, glow);
3442 }
3443
3444 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3445         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3446         float minexptime, float maxexptime, float minsize, float maxsize,
3447         bool collisiondetection, bool collision_removal, bool object_collision,
3448         ServerActiveObject *attached, bool vertical, const std::string &texture,
3449         const std::string &playername, const struct TileAnimationParams &animation,
3450         u8 glow)
3451 {
3452         // m_env will be NULL if the server is initializing
3453         if (!m_env)
3454                 return -1;
3455
3456         session_t peer_id = PEER_ID_INEXISTENT;
3457         u16 proto_ver = 0;
3458         if (!playername.empty()) {
3459                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3460                 if (!player)
3461                         return -1;
3462                 peer_id = player->getPeerId();
3463                 proto_ver = player->protocol_version;
3464         }
3465
3466         u16 attached_id = attached ? attached->getId() : 0;
3467
3468         u32 id;
3469         if (attached_id == 0)
3470                 id = m_env->addParticleSpawner(spawntime);
3471         else
3472                 id = m_env->addParticleSpawner(spawntime, attached_id);
3473
3474         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3475                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3476                 minexptime, maxexptime, minsize, maxsize, collisiondetection,
3477                 collision_removal, object_collision, attached_id, vertical,
3478                 texture, id, animation, glow);
3479
3480         return id;
3481 }
3482
3483 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3484 {
3485         // m_env will be NULL if the server is initializing
3486         if (!m_env)
3487                 throw ServerError("Can't delete particle spawners during initialisation!");
3488
3489         session_t peer_id = PEER_ID_INEXISTENT;
3490         if (!playername.empty()) {
3491                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3492                 if (!player)
3493                         return;
3494                 peer_id = player->getPeerId();
3495         }
3496
3497         m_env->deleteParticleSpawner(id);
3498         SendDeleteParticleSpawner(peer_id, id);
3499 }
3500
3501 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3502 {
3503         if(m_detached_inventories.count(name) > 0){
3504                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3505                 delete m_detached_inventories[name];
3506         } else {
3507                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3508         }
3509         Inventory *inv = new Inventory(m_itemdef);
3510         sanity_check(inv);
3511         m_detached_inventories[name] = inv;
3512         if (!player.empty())
3513                 m_detached_inventories_player[name] = player;
3514
3515         //TODO find a better way to do this
3516         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3517         return inv;
3518 }
3519
3520 bool Server::removeDetachedInventory(const std::string &name)
3521 {
3522         const auto &inv_it = m_detached_inventories.find(name);
3523         if (inv_it == m_detached_inventories.end())
3524                 return false;
3525
3526         delete inv_it->second;
3527         m_detached_inventories.erase(inv_it);
3528
3529         if (!m_env) // Mods are not done loading
3530                 return true;
3531
3532         const auto &player_it = m_detached_inventories_player.find(name);
3533         if (player_it != m_detached_inventories_player.end()) {
3534                 RemotePlayer *player = m_env->getPlayer(player_it->second.c_str());
3535
3536                 if (player && player->getPeerId() != PEER_ID_INEXISTENT)
3537                         sendDetachedInventory(name, player->getPeerId());
3538
3539                 m_detached_inventories_player.erase(player_it);
3540         } else {
3541                 // Notify all players about the change
3542                 sendDetachedInventory(name, PEER_ID_INEXISTENT);
3543         }
3544         return true;
3545 }
3546
3547 // actions: time-reversed list
3548 // Return value: success/failure
3549 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3550                 std::list<std::string> *log)
3551 {
3552         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3553         ServerMap *map = (ServerMap*)(&m_env->getMap());
3554
3555         // Fail if no actions to handle
3556         if (actions.empty()) {
3557                 assert(log);
3558                 log->push_back("Nothing to do.");
3559                 return false;
3560         }
3561
3562         int num_tried = 0;
3563         int num_failed = 0;
3564
3565         for (const RollbackAction &action : actions) {
3566                 num_tried++;
3567                 bool success = action.applyRevert(map, this, this);
3568                 if(!success){
3569                         num_failed++;
3570                         std::ostringstream os;
3571                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3572                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3573                         if (log)
3574                                 log->push_back(os.str());
3575                 }else{
3576                         std::ostringstream os;
3577                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3578                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3579                         if (log)
3580                                 log->push_back(os.str());
3581                 }
3582         }
3583
3584         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3585                         <<" failed"<<std::endl;
3586
3587         // Call it done if less than half failed
3588         return num_failed <= num_tried/2;
3589 }
3590
3591 // IGameDef interface
3592 // Under envlock
3593 IItemDefManager *Server::getItemDefManager()
3594 {
3595         return m_itemdef;
3596 }
3597
3598 const NodeDefManager *Server::getNodeDefManager()
3599 {
3600         return m_nodedef;
3601 }
3602
3603 ICraftDefManager *Server::getCraftDefManager()
3604 {
3605         return m_craftdef;
3606 }
3607
3608 u16 Server::allocateUnknownNodeId(const std::string &name)
3609 {
3610         return m_nodedef->allocateDummy(name);
3611 }
3612
3613 IWritableItemDefManager *Server::getWritableItemDefManager()
3614 {
3615         return m_itemdef;
3616 }
3617
3618 NodeDefManager *Server::getWritableNodeDefManager()
3619 {
3620         return m_nodedef;
3621 }
3622
3623 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3624 {
3625         return m_craftdef;
3626 }
3627
3628 const std::vector<ModSpec> & Server::getMods() const
3629 {
3630         return m_modmgr->getMods();
3631 }
3632
3633 const ModSpec *Server::getModSpec(const std::string &modname) const
3634 {
3635         return m_modmgr->getModSpec(modname);
3636 }
3637
3638 void Server::getModNames(std::vector<std::string> &modlist)
3639 {
3640         m_modmgr->getModNames(modlist);
3641 }
3642
3643 std::string Server::getBuiltinLuaPath()
3644 {
3645         return porting::path_share + DIR_DELIM + "builtin";
3646 }
3647
3648 std::string Server::getModStoragePath() const
3649 {
3650         return m_path_world + DIR_DELIM + "mod_storage";
3651 }
3652
3653 v3f Server::findSpawnPos()
3654 {
3655         ServerMap &map = m_env->getServerMap();
3656         v3f nodeposf;
3657         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf))
3658                 return nodeposf * BS;
3659
3660         bool is_good = false;
3661         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3662         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3663
3664         // Try to find a good place a few times
3665         for (s32 i = 0; i < 4000 && !is_good; i++) {
3666                 s32 range = MYMIN(1 + i, range_max);
3667                 // We're going to try to throw the player to this position
3668                 v2s16 nodepos2d = v2s16(
3669                         -range + (myrand() % (range * 2)),
3670                         -range + (myrand() % (range * 2)));
3671                 // Get spawn level at point
3672                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3673                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by the mapgen to
3674                 // signify an unsuitable spawn position, or if outside limits.
3675                 if (spawn_level >= MAX_MAP_GENERATION_LIMIT ||
3676                                 spawn_level <= -MAX_MAP_GENERATION_LIMIT)
3677                         continue;
3678
3679                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3680                 // Consecutive empty nodes
3681                 s32 air_count = 0;
3682
3683                 // Search upwards from 'spawn level' for 2 consecutive empty nodes, to
3684                 // avoid obstructions in already-generated mapblocks.
3685                 // In ungenerated mapblocks consisting of 'ignore' nodes, there will be
3686                 // no obstructions, but mapgen decorations are generated after spawn so
3687                 // the player may end up inside one.
3688                 for (s32 i = 0; i < 8; i++) {
3689                         v3s16 blockpos = getNodeBlockPos(nodepos);
3690                         map.emergeBlock(blockpos, true);
3691                         content_t c = map.getNode(nodepos).getContent();
3692
3693                         // In generated mapblocks allow spawn in all 'airlike' drawtype nodes.
3694                         // In ungenerated mapblocks allow spawn in 'ignore' nodes.
3695                         if (m_nodedef->get(c).drawtype == NDT_AIRLIKE || c == CONTENT_IGNORE) {
3696                                 air_count++;
3697                                 if (air_count >= 2) {
3698                                         // Spawn in lower empty node
3699                                         nodepos.Y--;
3700                                         nodeposf = intToFloat(nodepos, BS);
3701                                         // Don't spawn the player outside map boundaries
3702                                         if (objectpos_over_limit(nodeposf))
3703                                                 // Exit this loop, positions above are probably over limit
3704                                                 break;
3705
3706                                         // Good position found, cause an exit from main loop
3707                                         is_good = true;
3708                                         break;
3709                                 }
3710                         } else {
3711                                 air_count = 0;
3712                         }
3713                         nodepos.Y++;
3714                 }
3715         }
3716
3717         if (is_good)
3718                 return nodeposf;
3719
3720         // No suitable spawn point found, return fallback 0,0,0
3721         return v3f(0.0f, 0.0f, 0.0f);
3722 }
3723
3724 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3725 {
3726         if (delay == 0.0f) {
3727         // No delay, shutdown immediately
3728                 m_shutdown_state.is_requested = true;
3729                 // only print to the infostream, a chat message saying
3730                 // "Server Shutting Down" is sent when the server destructs.
3731                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3732         } else if (delay < 0.0f && m_shutdown_state.isTimerRunning()) {
3733                 // Negative delay, cancel shutdown if requested
3734                 m_shutdown_state.reset();
3735                 std::wstringstream ws;
3736
3737                 ws << L"*** Server shutdown canceled.";
3738
3739                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3740                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3741                 // m_shutdown_* are already handled, skip.
3742                 return;
3743         } else if (delay > 0.0f) {
3744         // Positive delay, tell the clients when the server will shut down
3745                 std::wstringstream ws;
3746
3747                 ws << L"*** Server shutting down in "
3748                                 << duration_to_string(myround(delay)).c_str()
3749                                 << ".";
3750
3751                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3752                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3753         }
3754
3755         m_shutdown_state.trigger(delay, msg, reconnect);
3756 }
3757
3758 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3759 {
3760         /*
3761                 Try to get an existing player
3762         */
3763         RemotePlayer *player = m_env->getPlayer(name);
3764
3765         // If player is already connected, cancel
3766         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3767                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3768                 return NULL;
3769         }
3770
3771         /*
3772                 If player with the wanted peer_id already exists, cancel.
3773         */
3774         if (m_env->getPlayer(peer_id)) {
3775                 infostream<<"emergePlayer(): Player with wrong name but same"
3776                                 " peer_id already exists"<<std::endl;
3777                 return NULL;
3778         }
3779
3780         if (!player) {
3781                 player = new RemotePlayer(name, idef());
3782         }
3783
3784         bool newplayer = false;
3785
3786         // Load player
3787         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3788
3789         // Complete init with server parts
3790         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3791         player->protocol_version = proto_version;
3792
3793         /* Run scripts */
3794         if (newplayer) {
3795                 m_script->on_newplayer(playersao);
3796         }
3797
3798         return playersao;
3799 }
3800
3801 bool Server::registerModStorage(ModMetadata *storage)
3802 {
3803         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3804                 errorstream << "Unable to register same mod storage twice. Storage name: "
3805                                 << storage->getModName() << std::endl;
3806                 return false;
3807         }
3808
3809         m_mod_storages[storage->getModName()] = storage;
3810         return true;
3811 }
3812
3813 void Server::unregisterModStorage(const std::string &name)
3814 {
3815         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3816         if (it != m_mod_storages.end()) {
3817                 // Save unconditionaly on unregistration
3818                 it->second->save(getModStoragePath());
3819                 m_mod_storages.erase(name);
3820         }
3821 }
3822
3823 void dedicated_server_loop(Server &server, bool &kill)
3824 {
3825         verbosestream<<"dedicated_server_loop()"<<std::endl;
3826
3827         IntervalLimiter m_profiler_interval;
3828
3829         static thread_local const float steplen =
3830                         g_settings->getFloat("dedicated_server_step");
3831         static thread_local const float profiler_print_interval =
3832                         g_settings->getFloat("profiler_print_interval");
3833
3834         /*
3835          * The dedicated server loop only does time-keeping (in Server::step) and
3836          * provides a way to main.cpp to kill the server externally (bool &kill).
3837          */
3838
3839         for(;;) {
3840                 // This is kind of a hack but can be done like this
3841                 // because server.step() is very light
3842                 sleep_ms((int)(steplen*1000.0));
3843                 server.step(steplen);
3844
3845                 if (server.isShutdownRequested() || kill)
3846                         break;
3847
3848                 /*
3849                         Profiler
3850                 */
3851                 if (profiler_print_interval != 0) {
3852                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3853                         {
3854                                 infostream<<"Profiler:"<<std::endl;
3855                                 g_profiler->print(infostream);
3856                                 g_profiler->clear();
3857                         }
3858                 }
3859         }
3860
3861         infostream << "Dedicated server quitting" << std::endl;
3862 #if USE_CURL
3863         if (g_settings->getBool("server_announce"))
3864                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3865                         server.m_bind_addr.getPort());
3866 #endif
3867 }
3868
3869 /*
3870  * Mod channels
3871  */
3872
3873
3874 bool Server::joinModChannel(const std::string &channel)
3875 {
3876         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3877                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3878 }
3879
3880 bool Server::leaveModChannel(const std::string &channel)
3881 {
3882         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3883 }
3884
3885 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3886 {
3887         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3888                 return false;
3889
3890         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3891         return true;
3892 }
3893
3894 ModChannel* Server::getModChannel(const std::string &channel)
3895 {
3896         return m_modchannel_mgr->getModChannel(channel);
3897 }
3898
3899 void Server::broadcastModChannelMessage(const std::string &channel,
3900                 const std::string &message, session_t from_peer)
3901 {
3902         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3903         if (peers.empty())
3904                 return;
3905
3906         if (message.size() > STRING_MAX_LEN) {
3907                 warningstream << "ModChannel message too long, dropping before sending "
3908                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3909                                 << channel << ")" << std::endl;
3910                 return;
3911         }
3912
3913         std::string sender;
3914         if (from_peer != PEER_ID_SERVER) {
3915                 sender = getPlayerName(from_peer);
3916         }
3917
3918         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3919                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3920         resp_pkt << channel << sender << message;
3921         for (session_t peer_id : peers) {
3922                 // Ignore sender
3923                 if (peer_id == from_peer)
3924                         continue;
3925
3926                 Send(peer_id, &resp_pkt);
3927         }
3928
3929         if (from_peer != PEER_ID_SERVER) {
3930                 m_script->on_modchannel_message(channel, sender, message);
3931         }
3932 }