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