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