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