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