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