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