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