]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
7bae69d559b1af295fd28f20099fa30cd781b78b
[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 legacypkt(TOCLIENT_CHAT_MESSAGE_OLD, 0, peer_id);
1538         legacypkt << message.message;
1539
1540         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1541         u8 version = 1;
1542         u8 type = message.type;
1543         pkt << version << type << std::wstring(L"") << message.message << message.timestamp;
1544
1545         if (peer_id != PEER_ID_INEXISTENT) {
1546                 RemotePlayer *player = m_env->getPlayer(peer_id);
1547                 if (!player)
1548                         return;
1549
1550                 if (player->protocol_version < 35)
1551                         Send(&legacypkt);
1552                 else
1553                         Send(&pkt);
1554         } else {
1555                 m_clients.sendToAllCompat(&pkt, &legacypkt, 35);
1556         }
1557 }
1558
1559 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1560                                      const std::string &formname)
1561 {
1562         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1563         if (formspec.empty()){
1564                 //the client should close the formspec
1565                 pkt.putLongString("");
1566         } else {
1567                 pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1568         }
1569         pkt << formname;
1570
1571         Send(&pkt);
1572 }
1573
1574 // Spawns a particle on peer with peer_id
1575 void Server::SendSpawnParticle(u16 peer_id, u16 protocol_version,
1576                                 v3f pos, v3f velocity, v3f acceleration,
1577                                 float expirationtime, float size, bool collisiondetection,
1578                                 bool collision_removal,
1579                                 bool vertical, const std::string &texture,
1580                                 const struct TileAnimationParams &animation, u8 glow)
1581 {
1582         static thread_local const float radius =
1583                         g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1584
1585         if (peer_id == PEER_ID_INEXISTENT) {
1586                 std::vector<u16> clients = m_clients.getClientIDs();
1587
1588                 for (const u16 client_id : clients) {
1589                         RemotePlayer *player = m_env->getPlayer(client_id);
1590                         if (!player)
1591                                 continue;
1592
1593                         PlayerSAO *sao = player->getPlayerSAO();
1594                         if (!sao)
1595                                 continue;
1596
1597                         // Do not send to distant clients
1598                         if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
1599                                 continue;
1600
1601                         SendSpawnParticle(client_id, player->protocol_version,
1602                                         pos, velocity, acceleration,
1603                                         expirationtime, size, collisiondetection,
1604                                         collision_removal, vertical, texture, animation, glow);
1605                 }
1606                 return;
1607         }
1608
1609         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1610
1611         pkt << pos << velocity << acceleration << expirationtime
1612                         << size << collisiondetection;
1613         pkt.putLongString(texture);
1614         pkt << vertical;
1615         pkt << collision_removal;
1616         // This is horrible but required (why are there two ways to serialize pkts?)
1617         std::ostringstream os(std::ios_base::binary);
1618         animation.serialize(os, protocol_version);
1619         pkt.putRawString(os.str());
1620         pkt << glow;
1621
1622         Send(&pkt);
1623 }
1624
1625 // Adds a ParticleSpawner on peer with peer_id
1626 void Server::SendAddParticleSpawner(u16 peer_id, u16 protocol_version,
1627         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1628         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1629         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1630         u16 attached_id, bool vertical, const std::string &texture, u32 id,
1631         const struct TileAnimationParams &animation, u8 glow)
1632 {
1633         if (peer_id == PEER_ID_INEXISTENT) {
1634                 // This sucks and should be replaced:
1635                 std::vector<u16> clients = m_clients.getClientIDs();
1636                 for (const u16 client_id : clients) {
1637                         RemotePlayer *player = m_env->getPlayer(client_id);
1638                         if (!player)
1639                                 continue;
1640                         SendAddParticleSpawner(client_id, player->protocol_version,
1641                                         amount, spawntime, minpos, maxpos,
1642                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1643                                         minsize, maxsize, collisiondetection, collision_removal,
1644                                         attached_id, vertical, texture, id, animation, glow);
1645                 }
1646                 return;
1647         }
1648
1649         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1650
1651         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1652                         << minacc << maxacc << minexptime << maxexptime << minsize
1653                         << maxsize << collisiondetection;
1654
1655         pkt.putLongString(texture);
1656
1657         pkt << id << vertical;
1658         pkt << collision_removal;
1659         pkt << attached_id;
1660         // This is horrible but required
1661         std::ostringstream os(std::ios_base::binary);
1662         animation.serialize(os, protocol_version);
1663         pkt.putRawString(os.str());
1664         pkt << glow;
1665
1666         Send(&pkt);
1667 }
1668
1669 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1670 {
1671         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1672
1673         // Ugly error in this packet
1674         pkt << (u16) id;
1675
1676         if (peer_id != PEER_ID_INEXISTENT) {
1677                 Send(&pkt);
1678         }
1679         else {
1680                 m_clients.sendToAll(&pkt);
1681         }
1682
1683 }
1684
1685 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1686 {
1687         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1688
1689         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1690                         << form->text << form->number << form->item << form->dir
1691                         << form->align << form->offset << form->world_pos << form->size;
1692
1693         Send(&pkt);
1694 }
1695
1696 void Server::SendHUDRemove(u16 peer_id, u32 id)
1697 {
1698         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1699         pkt << id;
1700         Send(&pkt);
1701 }
1702
1703 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1704 {
1705         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1706         pkt << id << (u8) stat;
1707
1708         switch (stat) {
1709                 case HUD_STAT_POS:
1710                 case HUD_STAT_SCALE:
1711                 case HUD_STAT_ALIGN:
1712                 case HUD_STAT_OFFSET:
1713                         pkt << *(v2f *) value;
1714                         break;
1715                 case HUD_STAT_NAME:
1716                 case HUD_STAT_TEXT:
1717                         pkt << *(std::string *) value;
1718                         break;
1719                 case HUD_STAT_WORLD_POS:
1720                         pkt << *(v3f *) value;
1721                         break;
1722                 case HUD_STAT_SIZE:
1723                         pkt << *(v2s32 *) value;
1724                         break;
1725                 case HUD_STAT_NUMBER:
1726                 case HUD_STAT_ITEM:
1727                 case HUD_STAT_DIR:
1728                 default:
1729                         pkt << *(u32 *) value;
1730                         break;
1731         }
1732
1733         Send(&pkt);
1734 }
1735
1736 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1737 {
1738         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1739
1740         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1741
1742         pkt << flags << mask;
1743
1744         Send(&pkt);
1745 }
1746
1747 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1748 {
1749         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1750         pkt << param << value;
1751         Send(&pkt);
1752 }
1753
1754 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1755                 const std::string &type, const std::vector<std::string> &params,
1756                 bool &clouds)
1757 {
1758         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1759         pkt << bgcolor << type << (u16) params.size();
1760
1761         for (const std::string &param : params)
1762                 pkt << param;
1763
1764         pkt << clouds;
1765
1766         Send(&pkt);
1767 }
1768
1769 void Server::SendCloudParams(u16 peer_id, float density,
1770                 const video::SColor &color_bright,
1771                 const video::SColor &color_ambient,
1772                 float height,
1773                 float thickness,
1774                 const v2f &speed)
1775 {
1776         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1777         pkt << density << color_bright << color_ambient
1778                         << height << thickness << speed;
1779
1780         Send(&pkt);
1781 }
1782
1783 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1784                 float ratio)
1785 {
1786         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1787                         1 + 2, peer_id);
1788
1789         pkt << do_override << (u16) (ratio * 65535);
1790
1791         Send(&pkt);
1792 }
1793
1794 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1795 {
1796         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1797         pkt << time << time_speed;
1798
1799         if (peer_id == PEER_ID_INEXISTENT) {
1800                 m_clients.sendToAll(&pkt);
1801         }
1802         else {
1803                 Send(&pkt);
1804         }
1805 }
1806
1807 void Server::SendPlayerHP(u16 peer_id)
1808 {
1809         PlayerSAO *playersao = getPlayerSAO(peer_id);
1810         // In some rare case if the player is disconnected
1811         // while Lua call l_punch, for example, this can be NULL
1812         if (!playersao)
1813                 return;
1814
1815         SendHP(peer_id, playersao->getHP());
1816         m_script->player_event(playersao,"health_changed");
1817
1818         // Send to other clients
1819         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1820         ActiveObjectMessage aom(playersao->getId(), true, str);
1821         playersao->m_messages_out.push(aom);
1822 }
1823
1824 void Server::SendPlayerBreath(PlayerSAO *sao)
1825 {
1826         assert(sao);
1827
1828         m_script->player_event(sao, "breath_changed");
1829         SendBreath(sao->getPeerID(), sao->getBreath());
1830 }
1831
1832 void Server::SendMovePlayer(u16 peer_id)
1833 {
1834         RemotePlayer *player = m_env->getPlayer(peer_id);
1835         assert(player);
1836         PlayerSAO *sao = player->getPlayerSAO();
1837         assert(sao);
1838
1839         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1840         pkt << sao->getBasePosition() << sao->getPitch() << sao->getYaw();
1841
1842         {
1843                 v3f pos = sao->getBasePosition();
1844                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1845                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1846                                 << " pitch=" << sao->getPitch()
1847                                 << " yaw=" << sao->getYaw()
1848                                 << std::endl;
1849         }
1850
1851         Send(&pkt);
1852 }
1853
1854 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1855 {
1856         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1857                 peer_id);
1858
1859         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1860                         << animation_frames[3] << animation_speed;
1861
1862         Send(&pkt);
1863 }
1864
1865 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1866 {
1867         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1868         pkt << first << third;
1869         Send(&pkt);
1870 }
1871 void Server::SendPlayerPrivileges(u16 peer_id)
1872 {
1873         RemotePlayer *player = m_env->getPlayer(peer_id);
1874         assert(player);
1875         if(player->peer_id == PEER_ID_INEXISTENT)
1876                 return;
1877
1878         std::set<std::string> privs;
1879         m_script->getAuth(player->getName(), NULL, &privs);
1880
1881         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1882         pkt << (u16) privs.size();
1883
1884         for (const std::string &priv : privs) {
1885                 pkt << priv;
1886         }
1887
1888         Send(&pkt);
1889 }
1890
1891 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1892 {
1893         RemotePlayer *player = m_env->getPlayer(peer_id);
1894         assert(player);
1895         if(player->peer_id == PEER_ID_INEXISTENT)
1896                 return;
1897
1898         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1899         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1900         Send(&pkt);
1901 }
1902
1903 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
1904 {
1905         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1906         pkt.putRawString(datas.c_str(), datas.size());
1907         Send(&pkt);
1908         return pkt.getSize();
1909 }
1910
1911 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
1912 {
1913         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1914                         datas.size(), peer_id);
1915
1916         pkt.putRawString(datas.c_str(), datas.size());
1917
1918         m_clients.send(pkt.getPeerId(),
1919                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1920                         &pkt, reliable);
1921 }
1922
1923 void Server::SendCSMFlavourLimits(u16 peer_id)
1924 {
1925         NetworkPacket pkt(TOCLIENT_CSM_FLAVOUR_LIMITS,
1926                 sizeof(m_csm_flavour_limits) + sizeof(m_csm_noderange_limit), peer_id);
1927         pkt << m_csm_flavour_limits << m_csm_noderange_limit;
1928         Send(&pkt);
1929 }
1930
1931 s32 Server::playSound(const SimpleSoundSpec &spec,
1932                 const ServerSoundParams &params)
1933 {
1934         // Find out initial position of sound
1935         bool pos_exists = false;
1936         v3f pos = params.getPos(m_env, &pos_exists);
1937         // If position is not found while it should be, cancel sound
1938         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1939                 return -1;
1940
1941         // Filter destination clients
1942         std::vector<u16> dst_clients;
1943         if(!params.to_player.empty()) {
1944                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
1945                 if(!player){
1946                         infostream<<"Server::playSound: Player \""<<params.to_player
1947                                         <<"\" not found"<<std::endl;
1948                         return -1;
1949                 }
1950                 if(player->peer_id == PEER_ID_INEXISTENT){
1951                         infostream<<"Server::playSound: Player \""<<params.to_player
1952                                         <<"\" not connected"<<std::endl;
1953                         return -1;
1954                 }
1955                 dst_clients.push_back(player->peer_id);
1956         } else {
1957                 std::vector<u16> clients = m_clients.getClientIDs();
1958
1959                 for (const u16 client_id : clients) {
1960                         RemotePlayer *player = m_env->getPlayer(client_id);
1961                         if (!player)
1962                                 continue;
1963
1964                         PlayerSAO *sao = player->getPlayerSAO();
1965                         if (!sao)
1966                                 continue;
1967
1968                         if (pos_exists) {
1969                                 if(sao->getBasePosition().getDistanceFrom(pos) >
1970                                                 params.max_hear_distance)
1971                                         continue;
1972                         }
1973                         dst_clients.push_back(client_id);
1974                 }
1975         }
1976
1977         if(dst_clients.empty())
1978                 return -1;
1979
1980         // Create the sound
1981         s32 id = m_next_sound_id++;
1982         // The sound will exist as a reference in m_playing_sounds
1983         m_playing_sounds[id] = ServerPlayingSound();
1984         ServerPlayingSound &psound = m_playing_sounds[id];
1985         psound.params = params;
1986         psound.spec = spec;
1987
1988         float gain = params.gain * spec.gain;
1989         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
1990         pkt << id << spec.name << gain
1991                         << (u8) params.type << pos << params.object
1992                         << params.loop << params.fade << params.pitch;
1993
1994         // Backwards compability
1995         bool play_sound = gain > 0;
1996
1997         for (const u16 dst_client : dst_clients) {
1998                 if (play_sound || m_clients.getProtocolVersion(dst_client) >= 32) {
1999                         psound.clients.insert(dst_client);
2000                         m_clients.send(dst_client, 0, &pkt, true);
2001                 }
2002         }
2003         return id;
2004 }
2005 void Server::stopSound(s32 handle)
2006 {
2007         // Get sound reference
2008         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2009                 m_playing_sounds.find(handle);
2010         if (i == m_playing_sounds.end())
2011                 return;
2012         ServerPlayingSound &psound = i->second;
2013
2014         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2015         pkt << handle;
2016
2017         for (std::unordered_set<u16>::const_iterator si = psound.clients.begin();
2018                         si != psound.clients.end(); ++si) {
2019                 // Send as reliable
2020                 m_clients.send(*si, 0, &pkt, true);
2021         }
2022         // Remove sound reference
2023         m_playing_sounds.erase(i);
2024 }
2025
2026 void Server::fadeSound(s32 handle, float step, float gain)
2027 {
2028         // Get sound reference
2029         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2030                 m_playing_sounds.find(handle);
2031         if (i == m_playing_sounds.end())
2032                 return;
2033
2034         ServerPlayingSound &psound = i->second;
2035         psound.params.gain = gain;
2036
2037         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2038         pkt << handle << step << gain;
2039
2040         // Backwards compability
2041         bool play_sound = gain > 0;
2042         ServerPlayingSound compat_psound = psound;
2043         compat_psound.clients.clear();
2044
2045         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2046         compat_pkt << handle;
2047
2048         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2049                         it != psound.clients.end();) {
2050                 if (m_clients.getProtocolVersion(*it) >= 32) {
2051                         // Send as reliable
2052                         m_clients.send(*it, 0, &pkt, true);
2053                         ++it;
2054                 } else {
2055                         compat_psound.clients.insert(*it);
2056                         // Stop old sound
2057                         m_clients.send(*it, 0, &compat_pkt, true);
2058                         psound.clients.erase(it++);
2059                 }
2060         }
2061
2062         // Remove sound reference
2063         if (!play_sound || psound.clients.empty())
2064                 m_playing_sounds.erase(i);
2065
2066         if (play_sound && !compat_psound.clients.empty()) {
2067                 // Play new sound volume on older clients
2068                 playSound(compat_psound.spec, compat_psound.params);
2069         }
2070 }
2071
2072 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2073         std::vector<u16> *far_players, float far_d_nodes)
2074 {
2075         float maxd = far_d_nodes*BS;
2076         v3f p_f = intToFloat(p, BS);
2077
2078         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2079         pkt << p;
2080
2081         std::vector<u16> clients = m_clients.getClientIDs();
2082         for (u16 client_id : clients) {
2083                 if (far_players) {
2084                         // Get player
2085                         if (RemotePlayer *player = m_env->getPlayer(client_id)) {
2086                                 PlayerSAO *sao = player->getPlayerSAO();
2087                                 if (!sao)
2088                                         continue;
2089
2090                                 // If player is far away, only set modified blocks not sent
2091                                 v3f player_pos = sao->getBasePosition();
2092                                 if (player_pos.getDistanceFrom(p_f) > maxd) {
2093                                         far_players->push_back(client_id);
2094                                         continue;
2095                                 }
2096                         }
2097                 }
2098
2099                 // Send as reliable
2100                 m_clients.send(client_id, 0, &pkt, true);
2101         }
2102 }
2103
2104 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2105                 std::vector<u16> *far_players, float far_d_nodes,
2106                 bool remove_metadata)
2107 {
2108         float maxd = far_d_nodes*BS;
2109         v3f p_f = intToFloat(p, BS);
2110
2111         std::vector<u16> clients = m_clients.getClientIDs();
2112         for (const u16 client_id : clients) {
2113                 if (far_players) {
2114                         // Get player
2115                         if (RemotePlayer *player = m_env->getPlayer(client_id)) {
2116                                 PlayerSAO *sao = player->getPlayerSAO();
2117                                 if (!sao)
2118                                         continue;
2119
2120                                 // If player is far away, only set modified blocks not sent
2121                                 v3f player_pos = sao->getBasePosition();
2122                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2123                                         far_players->push_back(client_id);
2124                                         continue;
2125                                 }
2126                         }
2127                 }
2128
2129                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2130                 m_clients.lock();
2131                 RemoteClient* client = m_clients.lockedGetClientNoEx(client_id);
2132                 if (client) {
2133                         pkt << p << n.param0 << n.param1 << n.param2
2134                                         << (u8) (remove_metadata ? 0 : 1);
2135                 }
2136                 m_clients.unlock();
2137
2138                 // Send as reliable
2139                 if (pkt.getSize() > 0)
2140                         m_clients.send(client_id, 0, &pkt, true);
2141         }
2142 }
2143
2144 void Server::setBlockNotSent(v3s16 p)
2145 {
2146         std::vector<u16> clients = m_clients.getClientIDs();
2147         m_clients.lock();
2148         for (const u16 i : clients) {
2149                 RemoteClient *client = m_clients.lockedGetClientNoEx(i);
2150                 client->SetBlockNotSent(p);
2151         }
2152         m_clients.unlock();
2153 }
2154
2155 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2156 {
2157         v3s16 p = block->getPos();
2158
2159         /*
2160                 Create a packet with the block in the right format
2161         */
2162
2163         std::ostringstream os(std::ios_base::binary);
2164         block->serialize(os, ver, false);
2165         block->serializeNetworkSpecific(os);
2166         std::string s = os.str();
2167
2168         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2169
2170         pkt << p;
2171         pkt.putRawString(s.c_str(), s.size());
2172         Send(&pkt);
2173 }
2174
2175 void Server::SendBlocks(float dtime)
2176 {
2177         MutexAutoLock envlock(m_env_mutex);
2178         //TODO check if one big lock could be faster then multiple small ones
2179
2180         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2181
2182         std::vector<PrioritySortedBlockTransfer> queue;
2183
2184         s32 total_sending = 0;
2185
2186         {
2187                 ScopeProfiler sp2(g_profiler, "Server: selecting blocks for sending");
2188
2189                 std::vector<u16> clients = m_clients.getClientIDs();
2190
2191                 m_clients.lock();
2192                 for (const u16 client_id : clients) {
2193                         RemoteClient *client = m_clients.lockedGetClientNoEx(client_id, CS_Active);
2194
2195                         if (!client)
2196                                 continue;
2197
2198                         total_sending += client->SendingCount();
2199                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2200                 }
2201                 m_clients.unlock();
2202         }
2203
2204         // Sort.
2205         // Lowest priority number comes first.
2206         // Lowest is most important.
2207         std::sort(queue.begin(), queue.end());
2208
2209         m_clients.lock();
2210         s32 max_blocks_to_send =
2211                         g_settings->getS32("max_simultaneous_block_sends_server_total");
2212
2213         for (const PrioritySortedBlockTransfer &block_to_send : queue) {
2214                 //TODO: Calculate limit dynamically
2215                 if (total_sending >= max_blocks_to_send)
2216                         break;
2217
2218                 MapBlock *block = nullptr;
2219                 try {
2220                         block = m_env->getMap().getBlockNoCreate(block_to_send.pos);
2221                 } catch (const InvalidPositionException &e) {
2222                         continue;
2223                 }
2224
2225                 RemoteClient *client = m_clients.lockedGetClientNoEx(block_to_send.peer_id,
2226                                 CS_Active);
2227                 if (!client)
2228                         continue;
2229
2230                 SendBlockNoLock(block_to_send.peer_id, block, client->serialization_version,
2231                                 client->net_proto_version);
2232
2233                 client->SentBlock(block_to_send.pos);
2234                 total_sending++;
2235         }
2236         m_clients.unlock();
2237 }
2238
2239 void Server::fillMediaCache()
2240 {
2241         infostream<<"Server: Calculating media file checksums"<<std::endl;
2242
2243         // Collect all media file paths
2244         std::vector<std::string> paths;
2245         for (const ModSpec &mod : m_mods) {
2246                 paths.push_back(mod.path + DIR_DELIM + "textures");
2247                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2248                 paths.push_back(mod.path + DIR_DELIM + "media");
2249                 paths.push_back(mod.path + DIR_DELIM + "models");
2250                 paths.push_back(mod.path + DIR_DELIM + "locale");
2251         }
2252         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2253
2254         // Collect media file information from paths into cache
2255         for (const std::string &mediapath : paths) {
2256                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2257                 for (const fs::DirListNode &dln : dirlist) {
2258                         if (dln.dir) // Ignode dirs
2259                                 continue;
2260                         std::string filename = dln.name;
2261                         // If name contains illegal characters, ignore the file
2262                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2263                                 infostream<<"Server: ignoring illegal file name: \""
2264                                                 << filename << "\"" << std::endl;
2265                                 continue;
2266                         }
2267                         // If name is not in a supported format, ignore it
2268                         const char *supported_ext[] = {
2269                                 ".png", ".jpg", ".bmp", ".tga",
2270                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2271                                 ".ogg",
2272                                 ".x", ".b3d", ".md2", ".obj",
2273                                 // Custom translation file format
2274                                 ".tr",
2275                                 NULL
2276                         };
2277                         if (removeStringEnd(filename, supported_ext).empty()){
2278                                 infostream << "Server: ignoring unsupported file extension: \""
2279                                                 << filename << "\"" << std::endl;
2280                                 continue;
2281                         }
2282                         // Ok, attempt to load the file and add to cache
2283                         std::string filepath;
2284                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2285
2286                         // Read data
2287                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2288                         if (!fis.good()) {
2289                                 errorstream << "Server::fillMediaCache(): Could not open \""
2290                                                 << filename << "\" for reading" << std::endl;
2291                                 continue;
2292                         }
2293                         std::ostringstream tmp_os(std::ios_base::binary);
2294                         bool bad = false;
2295                         for(;;) {
2296                                 char buf[1024];
2297                                 fis.read(buf, 1024);
2298                                 std::streamsize len = fis.gcount();
2299                                 tmp_os.write(buf, len);
2300                                 if (fis.eof())
2301                                         break;
2302                                 if (!fis.good()) {
2303                                         bad = true;
2304                                         break;
2305                                 }
2306                         }
2307                         if(bad) {
2308                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2309                                                 << filename << "\"" << std::endl;
2310                                 continue;
2311                         }
2312                         if(tmp_os.str().length() == 0) {
2313                                 errorstream << "Server::fillMediaCache(): Empty file \""
2314                                                 << filepath << "\"" << std::endl;
2315                                 continue;
2316                         }
2317
2318                         SHA1 sha1;
2319                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2320
2321                         unsigned char *digest = sha1.getDigest();
2322                         std::string sha1_base64 = base64_encode(digest, 20);
2323                         std::string sha1_hex = hex_encode((char*)digest, 20);
2324                         free(digest);
2325
2326                         // Put in list
2327                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2328                         verbosestream << "Server: " << sha1_hex << " is " << filename
2329                                         << std::endl;
2330                 }
2331         }
2332 }
2333
2334 void Server::sendMediaAnnouncement(u16 peer_id, const std::string &lang_code)
2335 {
2336         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2337                 << std::endl;
2338
2339         // Make packet
2340         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2341
2342         u16 media_sent = 0;
2343         std::string lang_suffix;
2344         lang_suffix.append(".").append(lang_code).append(".tr");
2345         for (const auto &i : m_media) {
2346                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2347                         continue;
2348                 media_sent++;
2349         }
2350
2351         pkt << media_sent;
2352
2353         for (const auto &i : m_media) {
2354                 if (str_ends_with(i.first, ".tr") && !str_ends_with(i.first, lang_suffix))
2355                         continue;
2356                 pkt << i.first << i.second.sha1_digest;
2357         }
2358
2359         pkt << g_settings->get("remote_media");
2360         Send(&pkt);
2361 }
2362
2363 struct SendableMedia
2364 {
2365         std::string name;
2366         std::string path;
2367         std::string data;
2368
2369         SendableMedia(const std::string &name_="", const std::string &path_="",
2370                       const std::string &data_=""):
2371                 name(name_),
2372                 path(path_),
2373                 data(data_)
2374         {}
2375 };
2376
2377 void Server::sendRequestedMedia(u16 peer_id,
2378                 const std::vector<std::string> &tosend)
2379 {
2380         verbosestream<<"Server::sendRequestedMedia(): "
2381                         <<"Sending files to client"<<std::endl;
2382
2383         /* Read files */
2384
2385         // Put 5kB in one bunch (this is not accurate)
2386         u32 bytes_per_bunch = 5000;
2387
2388         std::vector< std::vector<SendableMedia> > file_bunches;
2389         file_bunches.emplace_back();
2390
2391         u32 file_size_bunch_total = 0;
2392
2393         for (const std::string &name : tosend) {
2394                 if (m_media.find(name) == m_media.end()) {
2395                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2396                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2397                         continue;
2398                 }
2399
2400                 //TODO get path + name
2401                 std::string tpath = m_media[name].path;
2402
2403                 // Read data
2404                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2405                 if(!fis.good()){
2406                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2407                                         <<tpath<<"\" for reading"<<std::endl;
2408                         continue;
2409                 }
2410                 std::ostringstream tmp_os(std::ios_base::binary);
2411                 bool bad = false;
2412                 for(;;) {
2413                         char buf[1024];
2414                         fis.read(buf, 1024);
2415                         std::streamsize len = fis.gcount();
2416                         tmp_os.write(buf, len);
2417                         file_size_bunch_total += len;
2418                         if(fis.eof())
2419                                 break;
2420                         if(!fis.good()) {
2421                                 bad = true;
2422                                 break;
2423                         }
2424                 }
2425                 if (bad) {
2426                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2427                                         <<name<<"\""<<std::endl;
2428                         continue;
2429                 }
2430                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2431                                 <<tname<<"\""<<std::endl;*/
2432                 // Put in list
2433                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2434
2435                 // Start next bunch if got enough data
2436                 if(file_size_bunch_total >= bytes_per_bunch) {
2437                         file_bunches.emplace_back();
2438                         file_size_bunch_total = 0;
2439                 }
2440
2441         }
2442
2443         /* Create and send packets */
2444
2445         u16 num_bunches = file_bunches.size();
2446         for (u16 i = 0; i < num_bunches; i++) {
2447                 /*
2448                         u16 command
2449                         u16 total number of texture bunches
2450                         u16 index of this bunch
2451                         u32 number of files in this bunch
2452                         for each file {
2453                                 u16 length of name
2454                                 string name
2455                                 u32 length of data
2456                                 data
2457                         }
2458                 */
2459
2460                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2461                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2462
2463                 for (const SendableMedia &j : file_bunches[i]) {
2464                         pkt << j.name;
2465                         pkt.putLongString(j.data);
2466                 }
2467
2468                 verbosestream << "Server::sendRequestedMedia(): bunch "
2469                                 << i << "/" << num_bunches
2470                                 << " files=" << file_bunches[i].size()
2471                                 << " size="  << pkt.getSize() << std::endl;
2472                 Send(&pkt);
2473         }
2474 }
2475
2476 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2477 {
2478         if(m_detached_inventories.count(name) == 0) {
2479                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2480                 return;
2481         }
2482         Inventory *inv = m_detached_inventories[name];
2483         std::ostringstream os(std::ios_base::binary);
2484
2485         os << serializeString(name);
2486         inv->serialize(os);
2487
2488         // Make data buffer
2489         std::string s = os.str();
2490
2491         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2492         pkt.putRawString(s.c_str(), s.size());
2493
2494         const std::string &check = m_detached_inventories_player[name];
2495         if (peer_id == PEER_ID_INEXISTENT) {
2496                 if (check.empty())
2497                         return m_clients.sendToAll(&pkt);
2498                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2499                 if (p)
2500                         m_clients.send(p->peer_id, 0, &pkt, true);
2501         } else {
2502                 if (check.empty() || getPlayerName(peer_id) == check)
2503                         Send(&pkt);
2504         }
2505 }
2506
2507 void Server::sendDetachedInventories(u16 peer_id)
2508 {
2509         for (const auto &detached_inventory : m_detached_inventories) {
2510                 const std::string &name = detached_inventory.first;
2511                 //Inventory *inv = i->second;
2512                 sendDetachedInventory(name, peer_id);
2513         }
2514 }
2515
2516 /*
2517         Something random
2518 */
2519
2520 void Server::DiePlayer(u16 peer_id)
2521 {
2522         PlayerSAO *playersao = getPlayerSAO(peer_id);
2523         // In some rare cases this can be NULL -- if the player is disconnected
2524         // when a Lua function modifies l_punch, for example
2525         if (!playersao)
2526                 return;
2527
2528         infostream << "Server::DiePlayer(): Player "
2529                         << playersao->getPlayer()->getName()
2530                         << " dies" << std::endl;
2531
2532         playersao->setHP(0);
2533
2534         // Trigger scripted stuff
2535         m_script->on_dieplayer(playersao);
2536
2537         SendPlayerHP(peer_id);
2538         SendDeathscreen(peer_id, false, v3f(0,0,0));
2539 }
2540
2541 void Server::RespawnPlayer(u16 peer_id)
2542 {
2543         PlayerSAO *playersao = getPlayerSAO(peer_id);
2544         assert(playersao);
2545
2546         infostream << "Server::RespawnPlayer(): Player "
2547                         << playersao->getPlayer()->getName()
2548                         << " respawns" << std::endl;
2549
2550         playersao->setHP(playersao->accessObjectProperties()->hp_max);
2551         playersao->setBreath(PLAYER_MAX_BREATH);
2552
2553         bool repositioned = m_script->on_respawnplayer(playersao);
2554         if (!repositioned) {
2555                 // setPos will send the new position to client
2556                 playersao->setPos(findSpawnPos());
2557         }
2558
2559         SendPlayerHP(peer_id);
2560 }
2561
2562
2563 void Server::DenySudoAccess(u16 peer_id)
2564 {
2565         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2566         Send(&pkt);
2567 }
2568
2569
2570 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2571                 const std::string &str_reason, bool reconnect)
2572 {
2573         if (proto_ver >= 25) {
2574                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2575         } else {
2576                 std::wstring wreason = utf8_to_wide(
2577                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2578                         accessDeniedStrings[(u8)reason]);
2579                 SendAccessDenied_Legacy(peer_id, wreason);
2580         }
2581
2582         m_clients.event(peer_id, CSE_SetDenied);
2583         m_con->DisconnectPeer(peer_id);
2584 }
2585
2586
2587 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2588 {
2589         SendAccessDenied(peer_id, reason, custom_reason);
2590         m_clients.event(peer_id, CSE_SetDenied);
2591         m_con->DisconnectPeer(peer_id);
2592 }
2593
2594 // 13/03/15: remove this function when protocol version 25 will become
2595 // the minimum version for MT users, maybe in 1 year
2596 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2597 {
2598         SendAccessDenied_Legacy(peer_id, reason);
2599         m_clients.event(peer_id, CSE_SetDenied);
2600         m_con->DisconnectPeer(peer_id);
2601 }
2602
2603 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2604 {
2605         if (!forSudoMode) {
2606                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2607
2608                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2609
2610                 // Right now, the auth mechs don't change between login and sudo mode.
2611                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2612                 client->allowed_sudo_mechs = sudo_auth_mechs;
2613
2614                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2615                                 << g_settings->getFloat("dedicated_server_step")
2616                                 << sudo_auth_mechs;
2617
2618                 Send(&resp_pkt);
2619                 m_clients.event(peer_id, CSE_AuthAccept);
2620         } else {
2621                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2622
2623                 // We only support SRP right now
2624                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2625
2626                 resp_pkt << sudo_auth_mechs;
2627                 Send(&resp_pkt);
2628                 m_clients.event(peer_id, CSE_SudoSuccess);
2629         }
2630 }
2631
2632 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2633 {
2634         std::wstring message;
2635         {
2636                 /*
2637                         Clear references to playing sounds
2638                 */
2639                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2640                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2641                         ServerPlayingSound &psound = i->second;
2642                         psound.clients.erase(peer_id);
2643                         if (psound.clients.empty())
2644                                 m_playing_sounds.erase(i++);
2645                         else
2646                                 ++i;
2647                 }
2648
2649                 RemotePlayer *player = m_env->getPlayer(peer_id);
2650
2651                 /* Run scripts and remove from environment */
2652                 if (player) {
2653                         PlayerSAO *playersao = player->getPlayerSAO();
2654                         assert(playersao);
2655
2656                         // inform connected clients
2657                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2658                         // (u16) 1 + std::string represents a vector serialization representation
2659                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
2660                         m_clients.sendToAll(&notice);
2661                         // run scripts
2662                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2663
2664                         playersao->disconnected();
2665                 }
2666
2667                 /*
2668                         Print out action
2669                 */
2670                 {
2671                         if (player && reason != CDR_DENY) {
2672                                 std::ostringstream os(std::ios_base::binary);
2673                                 std::vector<u16> clients = m_clients.getClientIDs();
2674
2675                                 for (const u16 client_id : clients) {
2676                                         // Get player
2677                                         RemotePlayer *player = m_env->getPlayer(client_id);
2678                                         if (!player)
2679                                                 continue;
2680
2681                                         // Get name of player
2682                                         os << player->getName() << " ";
2683                                 }
2684
2685                                 std::string name = player->getName();
2686                                 actionstream << name << " "
2687                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2688                                                 << " List of players: " << os.str() << std::endl;
2689                                 if (m_admin_chat)
2690                                         m_admin_chat->outgoing_queue.push_back(
2691                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2692                         }
2693                 }
2694                 {
2695                         MutexAutoLock env_lock(m_env_mutex);
2696                         m_clients.DeleteClient(peer_id);
2697                 }
2698         }
2699
2700         // Send leave chat message to all remaining clients
2701         if (!message.empty()) {
2702                 SendChatMessage(PEER_ID_INEXISTENT,
2703                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2704         }
2705 }
2706
2707 void Server::UpdateCrafting(RemotePlayer *player)
2708 {
2709         // Get a preview for crafting
2710         ItemStack preview;
2711         InventoryLocation loc;
2712         loc.setPlayer(player->getName());
2713         std::vector<ItemStack> output_replacements;
2714         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2715         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2716                         (&player->inventory)->getList("craft"), loc);
2717
2718         // Put the new preview in
2719         InventoryList *plist = player->inventory.getList("craftpreview");
2720         sanity_check(plist);
2721         sanity_check(plist->getSize() >= 1);
2722         plist->changeItem(0, preview);
2723 }
2724
2725 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2726 {
2727         if (evt->type == CET_NICK_ADD) {
2728                 // The terminal informed us of its nick choice
2729                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2730                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2731                         errorstream << "You haven't set up an account." << std::endl
2732                                 << "Please log in using the client as '"
2733                                 << m_admin_nick << "' with a secure password." << std::endl
2734                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2735                                 << "and everybody can claim the user account instead of you," << std::endl
2736                                 << "giving them full control over this server." << std::endl;
2737                 }
2738         } else {
2739                 assert(evt->type == CET_CHAT);
2740                 handleAdminChat((ChatEventChat *)evt);
2741         }
2742 }
2743
2744 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2745         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2746 {
2747         // If something goes wrong, this player is to blame
2748         RollbackScopeActor rollback_scope(m_rollback,
2749                 std::string("player:") + name);
2750
2751         if (g_settings->getBool("strip_color_codes"))
2752                 wmessage = unescape_enriched(wmessage);
2753
2754         if (player) {
2755                 switch (player->canSendChatMessage()) {
2756                         case RPLAYER_CHATRESULT_FLOODING: {
2757                                 std::wstringstream ws;
2758                                 ws << L"You cannot send more messages. You are limited to "
2759                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2760                                    << L" messages per 10 seconds.";
2761                                 return ws.str();
2762                         }
2763                         case RPLAYER_CHATRESULT_KICK:
2764                                 DenyAccess_Legacy(player->peer_id,
2765                                                 L"You have been kicked due to message flooding.");
2766                                 return L"";
2767                         case RPLAYER_CHATRESULT_OK:
2768                                 break;
2769                         default:
2770                                 FATAL_ERROR("Unhandled chat filtering result found.");
2771                 }
2772         }
2773
2774         if (m_max_chatmessage_length > 0
2775                         && wmessage.length() > m_max_chatmessage_length) {
2776                 return L"Your message exceed the maximum chat message limit set on the server. "
2777                                 L"It was refused. Send a shorter message";
2778         }
2779
2780         // Run script hook, exit if script ate the chat message
2781         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2782                 return L"";
2783
2784         // Line to send
2785         std::wstring line;
2786         // Whether to send line to the player that sent the message, or to all players
2787         bool broadcast_line = true;
2788
2789         if (check_shout_priv && !checkPriv(name, "shout")) {
2790                 line += L"-!- You don't have permission to shout.";
2791                 broadcast_line = false;
2792         } else {
2793                 line += L"<";
2794                 line += wname;
2795                 line += L"> ";
2796                 line += wmessage;
2797         }
2798
2799         /*
2800                 Tell calling method to send the message to sender
2801         */
2802         if (!broadcast_line)
2803                 return line;
2804
2805         /*
2806                 Send the message to others
2807         */
2808         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2809
2810         std::vector<u16> clients = m_clients.getClientIDs();
2811
2812         /*
2813                 Send the message back to the inital sender
2814                 if they are using protocol version >= 29
2815         */
2816
2817         u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2818         if (player && player->protocol_version >= 29)
2819                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2820
2821         for (u16 cid : clients) {
2822                 if (cid != peer_id_to_avoid_sending)
2823                         SendChatMessage(cid, ChatMessage(line));
2824         }
2825         return L"";
2826 }
2827
2828 void Server::handleAdminChat(const ChatEventChat *evt)
2829 {
2830         std::string name = evt->nick;
2831         std::wstring wname = utf8_to_wide(name);
2832         std::wstring wmessage = evt->evt_msg;
2833
2834         std::wstring answer = handleChat(name, wname, wmessage);
2835
2836         // If asked to send answer to sender
2837         if (!answer.empty()) {
2838                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2839         }
2840 }
2841
2842 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2843 {
2844         RemoteClient *client = getClientNoEx(peer_id,state_min);
2845         if(!client)
2846                 throw ClientNotFoundException("Client not found");
2847
2848         return client;
2849 }
2850 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2851 {
2852         return m_clients.getClientNoEx(peer_id, state_min);
2853 }
2854
2855 std::string Server::getPlayerName(u16 peer_id)
2856 {
2857         RemotePlayer *player = m_env->getPlayer(peer_id);
2858         if (!player)
2859                 return "[id="+itos(peer_id)+"]";
2860         return player->getName();
2861 }
2862
2863 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2864 {
2865         RemotePlayer *player = m_env->getPlayer(peer_id);
2866         if (!player)
2867                 return NULL;
2868         return player->getPlayerSAO();
2869 }
2870
2871 std::wstring Server::getStatusString()
2872 {
2873         std::wostringstream os(std::ios_base::binary);
2874         os<<L"# Server: ";
2875         // Version
2876         os<<L"version="<<narrow_to_wide(g_version_string);
2877         // Uptime
2878         os<<L", uptime="<<m_uptime.get();
2879         // Max lag estimate
2880         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2881         // Information about clients
2882         bool first = true;
2883         os<<L", clients={";
2884         std::vector<u16> clients = m_clients.getClientIDs();
2885         for (u16 client_id : clients) {
2886                 // Get player
2887                 RemotePlayer *player = m_env->getPlayer(client_id);
2888                 // Get name of player
2889                 std::wstring name = L"unknown";
2890                 if (player)
2891                         name = narrow_to_wide(player->getName());
2892                 // Add name to information string
2893                 if(!first)
2894                         os << L", ";
2895                 else
2896                         first = false;
2897                 os << name;
2898         }
2899         os << L"}";
2900
2901         if (!((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
2902                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2903
2904         if (!g_settings->get("motd").empty())
2905                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2906         return os.str();
2907 }
2908
2909 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2910 {
2911         std::set<std::string> privs;
2912         m_script->getAuth(name, NULL, &privs);
2913         return privs;
2914 }
2915
2916 bool Server::checkPriv(const std::string &name, const std::string &priv)
2917 {
2918         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2919         return (privs.count(priv) != 0);
2920 }
2921
2922 void Server::reportPrivsModified(const std::string &name)
2923 {
2924         if (name.empty()) {
2925                 std::vector<u16> clients = m_clients.getClientIDs();
2926                 for (const u16 client_id : clients) {
2927                         RemotePlayer *player = m_env->getPlayer(client_id);
2928                         reportPrivsModified(player->getName());
2929                 }
2930         } else {
2931                 RemotePlayer *player = m_env->getPlayer(name.c_str());
2932                 if (!player)
2933                         return;
2934                 SendPlayerPrivileges(player->peer_id);
2935                 PlayerSAO *sao = player->getPlayerSAO();
2936                 if(!sao)
2937                         return;
2938                 sao->updatePrivileges(
2939                                 getPlayerEffectivePrivs(name),
2940                                 isSingleplayer());
2941         }
2942 }
2943
2944 void Server::reportInventoryFormspecModified(const std::string &name)
2945 {
2946         RemotePlayer *player = m_env->getPlayer(name.c_str());
2947         if (!player)
2948                 return;
2949         SendPlayerInventoryFormspec(player->peer_id);
2950 }
2951
2952 void Server::setIpBanned(const std::string &ip, const std::string &name)
2953 {
2954         m_banmanager->add(ip, name);
2955 }
2956
2957 void Server::unsetIpBanned(const std::string &ip_or_name)
2958 {
2959         m_banmanager->remove(ip_or_name);
2960 }
2961
2962 std::string Server::getBanDescription(const std::string &ip_or_name)
2963 {
2964         return m_banmanager->getBanDescription(ip_or_name);
2965 }
2966
2967 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2968 {
2969         // m_env will be NULL if the server is initializing
2970         if (!m_env)
2971                 return;
2972
2973         if (m_admin_nick == name && !m_admin_nick.empty()) {
2974                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
2975         }
2976
2977         RemotePlayer *player = m_env->getPlayer(name);
2978         if (!player) {
2979                 return;
2980         }
2981
2982         if (player->peer_id == PEER_ID_INEXISTENT)
2983                 return;
2984
2985         SendChatMessage(player->peer_id, ChatMessage(msg));
2986 }
2987
2988 bool Server::showFormspec(const char *playername, const std::string &formspec,
2989         const std::string &formname)
2990 {
2991         // m_env will be NULL if the server is initializing
2992         if (!m_env)
2993                 return false;
2994
2995         RemotePlayer *player = m_env->getPlayer(playername);
2996         if (!player)
2997                 return false;
2998
2999         SendShowFormspecMessage(player->peer_id, formspec, formname);
3000         return true;
3001 }
3002
3003 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3004 {
3005         if (!player)
3006                 return -1;
3007
3008         u32 id = player->addHud(form);
3009
3010         SendHUDAdd(player->peer_id, id, form);
3011
3012         return id;
3013 }
3014
3015 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3016         if (!player)
3017                 return false;
3018
3019         HudElement* todel = player->removeHud(id);
3020
3021         if (!todel)
3022                 return false;
3023
3024         delete todel;
3025
3026         SendHUDRemove(player->peer_id, id);
3027         return true;
3028 }
3029
3030 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3031 {
3032         if (!player)
3033                 return false;
3034
3035         SendHUDChange(player->peer_id, id, stat, data);
3036         return true;
3037 }
3038
3039 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3040 {
3041         if (!player)
3042                 return false;
3043
3044         SendHUDSetFlags(player->peer_id, flags, mask);
3045         player->hud_flags &= ~mask;
3046         player->hud_flags |= flags;
3047
3048         PlayerSAO* playersao = player->getPlayerSAO();
3049
3050         if (!playersao)
3051                 return false;
3052
3053         m_script->player_event(playersao, "hud_changed");
3054         return true;
3055 }
3056
3057 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3058 {
3059         if (!player)
3060                 return false;
3061
3062         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3063                 return false;
3064
3065         player->setHotbarItemcount(hotbar_itemcount);
3066         std::ostringstream os(std::ios::binary);
3067         writeS32(os, hotbar_itemcount);
3068         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3069         return true;
3070 }
3071
3072 s32 Server::hudGetHotbarItemcount(RemotePlayer *player) const
3073 {
3074         return player->getHotbarItemcount();
3075 }
3076
3077 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3078 {
3079         if (!player)
3080                 return;
3081
3082         player->setHotbarImage(name);
3083         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3084 }
3085
3086 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3087 {
3088         if (!player)
3089                 return "";
3090         return player->getHotbarImage();
3091 }
3092
3093 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3094 {
3095         if (!player)
3096                 return;
3097
3098         player->setHotbarSelectedImage(name);
3099         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3100 }
3101
3102 const std::string& Server::hudGetHotbarSelectedImage(RemotePlayer *player) const
3103 {
3104         return player->getHotbarSelectedImage();
3105 }
3106
3107 Address Server::getPeerAddress(u16 peer_id)
3108 {
3109         return m_con->GetPeerAddress(peer_id);
3110 }
3111
3112 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3113                 v2s32 animation_frames[4], f32 frame_speed)
3114 {
3115         if (!player)
3116                 return false;
3117
3118         player->setLocalAnimations(animation_frames, frame_speed);
3119         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3120         return true;
3121 }
3122
3123 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3124 {
3125         if (!player)
3126                 return false;
3127
3128         player->eye_offset_first = first;
3129         player->eye_offset_third = third;
3130         SendEyeOffset(player->peer_id, first, third);
3131         return true;
3132 }
3133
3134 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3135         const std::string &type, const std::vector<std::string> &params,
3136         bool &clouds)
3137 {
3138         if (!player)
3139                 return false;
3140
3141         player->setSky(bgcolor, type, params, clouds);
3142         SendSetSky(player->peer_id, bgcolor, type, params, clouds);
3143         return true;
3144 }
3145
3146 bool Server::setClouds(RemotePlayer *player, float density,
3147         const video::SColor &color_bright,
3148         const video::SColor &color_ambient,
3149         float height,
3150         float thickness,
3151         const v2f &speed)
3152 {
3153         if (!player)
3154                 return false;
3155
3156         SendCloudParams(player->peer_id, density,
3157                         color_bright, color_ambient, height,
3158                         thickness, speed);
3159         return true;
3160 }
3161
3162 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3163         float ratio)
3164 {
3165         if (!player)
3166                 return false;
3167
3168         player->overrideDayNightRatio(do_override, ratio);
3169         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3170         return true;
3171 }
3172
3173 void Server::notifyPlayers(const std::wstring &msg)
3174 {
3175         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3176 }
3177
3178 void Server::spawnParticle(const std::string &playername, v3f pos,
3179         v3f velocity, v3f acceleration,
3180         float expirationtime, float size, bool
3181         collisiondetection, bool collision_removal,
3182         bool vertical, const std::string &texture,
3183         const struct TileAnimationParams &animation, u8 glow)
3184 {
3185         // m_env will be NULL if the server is initializing
3186         if (!m_env)
3187                 return;
3188
3189         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3190         if (!playername.empty()) {
3191                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3192                 if (!player)
3193                         return;
3194                 peer_id = player->peer_id;
3195                 proto_ver = player->protocol_version;
3196         }
3197
3198         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3199                         expirationtime, size, collisiondetection,
3200                         collision_removal, vertical, texture, animation, glow);
3201 }
3202
3203 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3204         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3205         float minexptime, float maxexptime, float minsize, float maxsize,
3206         bool collisiondetection, bool collision_removal,
3207         ServerActiveObject *attached, bool vertical, const std::string &texture,
3208         const std::string &playername, const struct TileAnimationParams &animation,
3209         u8 glow)
3210 {
3211         // m_env will be NULL if the server is initializing
3212         if (!m_env)
3213                 return -1;
3214
3215         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3216         if (!playername.empty()) {
3217                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3218                 if (!player)
3219                         return -1;
3220                 peer_id = player->peer_id;
3221                 proto_ver = player->protocol_version;
3222         }
3223
3224         u16 attached_id = attached ? attached->getId() : 0;
3225
3226         u32 id;
3227         if (attached_id == 0)
3228                 id = m_env->addParticleSpawner(spawntime);
3229         else
3230                 id = m_env->addParticleSpawner(spawntime, attached_id);
3231
3232         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3233                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3234                 minexptime, maxexptime, minsize, maxsize,
3235                 collisiondetection, collision_removal, attached_id, vertical,
3236                 texture, id, animation, glow);
3237
3238         return id;
3239 }
3240
3241 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3242 {
3243         // m_env will be NULL if the server is initializing
3244         if (!m_env)
3245                 throw ServerError("Can't delete particle spawners during initialisation!");
3246
3247         u16 peer_id = PEER_ID_INEXISTENT;
3248         if (!playername.empty()) {
3249                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3250                 if (!player)
3251                         return;
3252                 peer_id = player->peer_id;
3253         }
3254
3255         m_env->deleteParticleSpawner(id);
3256         SendDeleteParticleSpawner(peer_id, id);
3257 }
3258
3259 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3260 {
3261         if(m_detached_inventories.count(name) > 0){
3262                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3263                 delete m_detached_inventories[name];
3264         } else {
3265                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3266         }
3267         Inventory *inv = new Inventory(m_itemdef);
3268         sanity_check(inv);
3269         m_detached_inventories[name] = inv;
3270         m_detached_inventories_player[name] = player;
3271         //TODO find a better way to do this
3272         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3273         return inv;
3274 }
3275
3276 // actions: time-reversed list
3277 // Return value: success/failure
3278 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3279                 std::list<std::string> *log)
3280 {
3281         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3282         ServerMap *map = (ServerMap*)(&m_env->getMap());
3283
3284         // Fail if no actions to handle
3285         if(actions.empty()){
3286                 log->push_back("Nothing to do.");
3287                 return false;
3288         }
3289
3290         int num_tried = 0;
3291         int num_failed = 0;
3292
3293         for (const RollbackAction &action : actions) {
3294                 num_tried++;
3295                 bool success = action.applyRevert(map, this, this);
3296                 if(!success){
3297                         num_failed++;
3298                         std::ostringstream os;
3299                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3300                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3301                         if (log)
3302                                 log->push_back(os.str());
3303                 }else{
3304                         std::ostringstream os;
3305                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3306                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3307                         if (log)
3308                                 log->push_back(os.str());
3309                 }
3310         }
3311
3312         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3313                         <<" failed"<<std::endl;
3314
3315         // Call it done if less than half failed
3316         return num_failed <= num_tried/2;
3317 }
3318
3319 // IGameDef interface
3320 // Under envlock
3321 IItemDefManager *Server::getItemDefManager()
3322 {
3323         return m_itemdef;
3324 }
3325
3326 INodeDefManager *Server::getNodeDefManager()
3327 {
3328         return m_nodedef;
3329 }
3330
3331 ICraftDefManager *Server::getCraftDefManager()
3332 {
3333         return m_craftdef;
3334 }
3335
3336 u16 Server::allocateUnknownNodeId(const std::string &name)
3337 {
3338         return m_nodedef->allocateDummy(name);
3339 }
3340
3341 MtEventManager *Server::getEventManager()
3342 {
3343         return m_event;
3344 }
3345
3346 IWritableItemDefManager *Server::getWritableItemDefManager()
3347 {
3348         return m_itemdef;
3349 }
3350
3351 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3352 {
3353         return m_nodedef;
3354 }
3355
3356 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3357 {
3358         return m_craftdef;
3359 }
3360
3361 const ModSpec *Server::getModSpec(const std::string &modname) const
3362 {
3363         std::vector<ModSpec>::const_iterator it;
3364         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3365                 const ModSpec &mod = *it;
3366                 if (mod.name == modname)
3367                         return &mod;
3368         }
3369         return NULL;
3370 }
3371
3372 void Server::getModNames(std::vector<std::string> &modlist)
3373 {
3374         std::vector<ModSpec>::iterator it;
3375         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3376                 modlist.push_back(it->name);
3377 }
3378
3379 std::string Server::getBuiltinLuaPath()
3380 {
3381         return porting::path_share + DIR_DELIM + "builtin";
3382 }
3383
3384 std::string Server::getModStoragePath() const
3385 {
3386         return m_path_world + DIR_DELIM + "mod_storage";
3387 }
3388
3389 v3f Server::findSpawnPos()
3390 {
3391         ServerMap &map = m_env->getServerMap();
3392         v3f nodeposf;
3393         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3394                 return nodeposf * BS;
3395         }
3396
3397         bool is_good = false;
3398         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3399         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3400
3401         // Try to find a good place a few times
3402         for(s32 i = 0; i < 4000 && !is_good; i++) {
3403                 s32 range = MYMIN(1 + i, range_max);
3404                 // We're going to try to throw the player to this position
3405                 v2s16 nodepos2d = v2s16(
3406                         -range + (myrand() % (range * 2)),
3407                         -range + (myrand() % (range * 2)));
3408
3409                 // Get spawn level at point
3410                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3411                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3412                 // the mapgen to signify an unsuitable spawn position
3413                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3414                         continue;
3415
3416                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3417
3418                 s32 air_count = 0;
3419                 for (s32 i = 0; i < 10; i++) {
3420                         v3s16 blockpos = getNodeBlockPos(nodepos);
3421                         map.emergeBlock(blockpos, true);
3422                         content_t c = map.getNodeNoEx(nodepos).getContent();
3423                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3424                                 air_count++;
3425                                 if (air_count >= 2) {
3426                                         nodeposf = intToFloat(nodepos, BS);
3427                                         // Don't spawn the player outside map boundaries
3428                                         if (objectpos_over_limit(nodeposf))
3429                                                 continue;
3430                                         is_good = true;
3431                                         break;
3432                                 }
3433                         }
3434                         nodepos.Y++;
3435                 }
3436         }
3437
3438         return nodeposf;
3439 }
3440
3441 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3442 {
3443         m_shutdown_timer = delay;
3444         m_shutdown_msg = msg;
3445         m_shutdown_ask_reconnect = reconnect;
3446
3447         if (delay == 0.0f) {
3448         // No delay, shutdown immediately
3449                 m_shutdown_requested = true;
3450                 // only print to the infostream, a chat message saying
3451                 // "Server Shutting Down" is sent when the server destructs.
3452                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3453         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3454         // Negative delay, cancel shutdown if requested
3455                 m_shutdown_timer = 0.0f;
3456                 m_shutdown_msg = "";
3457                 m_shutdown_ask_reconnect = false;
3458                 m_shutdown_requested = false;
3459                 std::wstringstream ws;
3460
3461                 ws << L"*** Server shutdown canceled.";
3462
3463                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3464                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3465         } else if (delay > 0.0f) {
3466         // Positive delay, tell the clients when the server will shut down
3467                 std::wstringstream ws;
3468
3469                 ws << L"*** Server shutting down in "
3470                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3471                                 << ".";
3472
3473                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3474                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3475         }
3476 }
3477
3478 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3479 {
3480         /*
3481                 Try to get an existing player
3482         */
3483         RemotePlayer *player = m_env->getPlayer(name);
3484
3485         // If player is already connected, cancel
3486         if (player && player->peer_id != 0) {
3487                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3488                 return NULL;
3489         }
3490
3491         /*
3492                 If player with the wanted peer_id already exists, cancel.
3493         */
3494         if (m_env->getPlayer(peer_id)) {
3495                 infostream<<"emergePlayer(): Player with wrong name but same"
3496                                 " peer_id already exists"<<std::endl;
3497                 return NULL;
3498         }
3499
3500         if (!player) {
3501                 player = new RemotePlayer(name, idef());
3502         }
3503
3504         bool newplayer = false;
3505
3506         // Load player
3507         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3508
3509         // Complete init with server parts
3510         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3511         player->protocol_version = proto_version;
3512
3513         /* Run scripts */
3514         if (newplayer) {
3515                 m_script->on_newplayer(playersao);
3516         }
3517
3518         return playersao;
3519 }
3520
3521 bool Server::registerModStorage(ModMetadata *storage)
3522 {
3523         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3524                 errorstream << "Unable to register same mod storage twice. Storage name: "
3525                                 << storage->getModName() << std::endl;
3526                 return false;
3527         }
3528
3529         m_mod_storages[storage->getModName()] = storage;
3530         return true;
3531 }
3532
3533 void Server::unregisterModStorage(const std::string &name)
3534 {
3535         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3536         if (it != m_mod_storages.end()) {
3537                 // Save unconditionaly on unregistration
3538                 it->second->save(getModStoragePath());
3539                 m_mod_storages.erase(name);
3540         }
3541 }
3542
3543 void dedicated_server_loop(Server &server, bool &kill)
3544 {
3545         verbosestream<<"dedicated_server_loop()"<<std::endl;
3546
3547         IntervalLimiter m_profiler_interval;
3548
3549         static thread_local const float steplen =
3550                         g_settings->getFloat("dedicated_server_step");
3551         static thread_local const float profiler_print_interval =
3552                         g_settings->getFloat("profiler_print_interval");
3553
3554         for(;;) {
3555                 // This is kind of a hack but can be done like this
3556                 // because server.step() is very light
3557                 {
3558                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3559                         sleep_ms((int)(steplen*1000.0));
3560                 }
3561                 server.step(steplen);
3562
3563                 if (server.getShutdownRequested() || kill)
3564                         break;
3565
3566                 /*
3567                         Profiler
3568                 */
3569                 if (profiler_print_interval != 0) {
3570                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3571                         {
3572                                 infostream<<"Profiler:"<<std::endl;
3573                                 g_profiler->print(infostream);
3574                                 g_profiler->clear();
3575                         }
3576                 }
3577         }
3578
3579         infostream << "Dedicated server quitting" << std::endl;
3580 #if USE_CURL
3581         if (g_settings->getBool("server_announce"))
3582                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3583                         server.m_bind_addr.getPort());
3584 #endif
3585 }