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