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