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