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