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