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