]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Network cleanup (#6302)
[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         }
2297         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2298
2299         // Collect media file information from paths into cache
2300         for (const std::string &mediapath : paths) {
2301                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2302                 for (const fs::DirListNode &dln : dirlist) {
2303                         if (dln.dir) // Ignode dirs
2304                                 continue;
2305                         std::string filename = dln.name;
2306                         // If name contains illegal characters, ignore the file
2307                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2308                                 infostream<<"Server: ignoring illegal file name: \""
2309                                                 << filename << "\"" << std::endl;
2310                                 continue;
2311                         }
2312                         // If name is not in a supported format, ignore it
2313                         const char *supported_ext[] = {
2314                                 ".png", ".jpg", ".bmp", ".tga",
2315                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2316                                 ".ogg",
2317                                 ".x", ".b3d", ".md2", ".obj",
2318                                 NULL
2319                         };
2320                         if (removeStringEnd(filename, supported_ext).empty()){
2321                                 infostream << "Server: ignoring unsupported file extension: \""
2322                                                 << filename << "\"" << std::endl;
2323                                 continue;
2324                         }
2325                         // Ok, attempt to load the file and add to cache
2326                         std::string filepath;
2327                         filepath.append(mediapath).append(DIR_DELIM).append(filename);
2328
2329                         // Read data
2330                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2331                         if (!fis.good()) {
2332                                 errorstream << "Server::fillMediaCache(): Could not open \""
2333                                                 << filename << "\" for reading" << std::endl;
2334                                 continue;
2335                         }
2336                         std::ostringstream tmp_os(std::ios_base::binary);
2337                         bool bad = false;
2338                         for(;;) {
2339                                 char buf[1024];
2340                                 fis.read(buf, 1024);
2341                                 std::streamsize len = fis.gcount();
2342                                 tmp_os.write(buf, len);
2343                                 if (fis.eof())
2344                                         break;
2345                                 if (!fis.good()) {
2346                                         bad = true;
2347                                         break;
2348                                 }
2349                         }
2350                         if(bad) {
2351                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2352                                                 << filename << "\"" << std::endl;
2353                                 continue;
2354                         }
2355                         if(tmp_os.str().length() == 0) {
2356                                 errorstream << "Server::fillMediaCache(): Empty file \""
2357                                                 << filepath << "\"" << std::endl;
2358                                 continue;
2359                         }
2360
2361                         SHA1 sha1;
2362                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2363
2364                         unsigned char *digest = sha1.getDigest();
2365                         std::string sha1_base64 = base64_encode(digest, 20);
2366                         std::string sha1_hex = hex_encode((char*)digest, 20);
2367                         free(digest);
2368
2369                         // Put in list
2370                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2371                         verbosestream << "Server: " << sha1_hex << " is " << filename
2372                                         << std::endl;
2373                 }
2374         }
2375 }
2376
2377 void Server::sendMediaAnnouncement(u16 peer_id)
2378 {
2379         DSTACK(FUNCTION_NAME);
2380
2381         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2382                 << std::endl;
2383
2384         // Make packet
2385         std::ostringstream os(std::ios_base::binary);
2386
2387         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2388         pkt << (u16) m_media.size();
2389
2390         for (const auto &i : m_media) {
2391                 pkt << i.first << i.second.sha1_digest;
2392         }
2393
2394         pkt << g_settings->get("remote_media");
2395         Send(&pkt);
2396 }
2397
2398 struct SendableMedia
2399 {
2400         std::string name;
2401         std::string path;
2402         std::string data;
2403
2404         SendableMedia(const std::string &name_="", const std::string &path_="",
2405                       const std::string &data_=""):
2406                 name(name_),
2407                 path(path_),
2408                 data(data_)
2409         {}
2410 };
2411
2412 void Server::sendRequestedMedia(u16 peer_id,
2413                 const std::vector<std::string> &tosend)
2414 {
2415         DSTACK(FUNCTION_NAME);
2416
2417         verbosestream<<"Server::sendRequestedMedia(): "
2418                         <<"Sending files to client"<<std::endl;
2419
2420         /* Read files */
2421
2422         // Put 5kB in one bunch (this is not accurate)
2423         u32 bytes_per_bunch = 5000;
2424
2425         std::vector< std::vector<SendableMedia> > file_bunches;
2426         file_bunches.emplace_back();
2427
2428         u32 file_size_bunch_total = 0;
2429
2430         for (const std::string &name : tosend) {
2431                 if (m_media.find(name) == m_media.end()) {
2432                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2433                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2434                         continue;
2435                 }
2436
2437                 //TODO get path + name
2438                 std::string tpath = m_media[name].path;
2439
2440                 // Read data
2441                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2442                 if(!fis.good()){
2443                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2444                                         <<tpath<<"\" for reading"<<std::endl;
2445                         continue;
2446                 }
2447                 std::ostringstream tmp_os(std::ios_base::binary);
2448                 bool bad = false;
2449                 for(;;) {
2450                         char buf[1024];
2451                         fis.read(buf, 1024);
2452                         std::streamsize len = fis.gcount();
2453                         tmp_os.write(buf, len);
2454                         file_size_bunch_total += len;
2455                         if(fis.eof())
2456                                 break;
2457                         if(!fis.good()) {
2458                                 bad = true;
2459                                 break;
2460                         }
2461                 }
2462                 if (bad) {
2463                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2464                                         <<name<<"\""<<std::endl;
2465                         continue;
2466                 }
2467                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2468                                 <<tname<<"\""<<std::endl;*/
2469                 // Put in list
2470                 file_bunches[file_bunches.size()-1].emplace_back(name, tpath, tmp_os.str());
2471
2472                 // Start next bunch if got enough data
2473                 if(file_size_bunch_total >= bytes_per_bunch) {
2474                         file_bunches.emplace_back();
2475                         file_size_bunch_total = 0;
2476                 }
2477
2478         }
2479
2480         /* Create and send packets */
2481
2482         u16 num_bunches = file_bunches.size();
2483         for (u16 i = 0; i < num_bunches; i++) {
2484                 /*
2485                         u16 command
2486                         u16 total number of texture bunches
2487                         u16 index of this bunch
2488                         u32 number of files in this bunch
2489                         for each file {
2490                                 u16 length of name
2491                                 string name
2492                                 u32 length of data
2493                                 data
2494                         }
2495                 */
2496
2497                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2498                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2499
2500                 for (const SendableMedia &j : file_bunches[i]) {
2501                         pkt << j.name;
2502                         pkt.putLongString(j.data);
2503                 }
2504
2505                 verbosestream << "Server::sendRequestedMedia(): bunch "
2506                                 << i << "/" << num_bunches
2507                                 << " files=" << file_bunches[i].size()
2508                                 << " size="  << pkt.getSize() << std::endl;
2509                 Send(&pkt);
2510         }
2511 }
2512
2513 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2514 {
2515         if(m_detached_inventories.count(name) == 0) {
2516                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2517                 return;
2518         }
2519         Inventory *inv = m_detached_inventories[name];
2520         std::ostringstream os(std::ios_base::binary);
2521
2522         os << serializeString(name);
2523         inv->serialize(os);
2524
2525         // Make data buffer
2526         std::string s = os.str();
2527
2528         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2529         pkt.putRawString(s.c_str(), s.size());
2530
2531         const std::string &check = m_detached_inventories_player[name];
2532         if (peer_id == PEER_ID_INEXISTENT) {
2533                 if (check.empty())
2534                         return m_clients.sendToAll(&pkt);
2535                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2536                 if (p)
2537                         m_clients.send(p->peer_id, 0, &pkt, true);
2538         } else {
2539                 if (check.empty() || getPlayerName(peer_id) == check)
2540                         Send(&pkt);
2541         }
2542 }
2543
2544 void Server::sendDetachedInventories(u16 peer_id)
2545 {
2546         DSTACK(FUNCTION_NAME);
2547
2548         for (const auto &detached_inventory : m_detached_inventories) {
2549                 const std::string &name = detached_inventory.first;
2550                 //Inventory *inv = i->second;
2551                 sendDetachedInventory(name, peer_id);
2552         }
2553 }
2554
2555 /*
2556         Something random
2557 */
2558
2559 void Server::DiePlayer(u16 peer_id)
2560 {
2561         DSTACK(FUNCTION_NAME);
2562         PlayerSAO *playersao = getPlayerSAO(peer_id);
2563         // In some rare cases this can be NULL -- if the player is disconnected
2564         // when a Lua function modifies l_punch, for example
2565         if (!playersao)
2566                 return;
2567
2568         infostream << "Server::DiePlayer(): Player "
2569                         << playersao->getPlayer()->getName()
2570                         << " dies" << std::endl;
2571
2572         playersao->setHP(0);
2573
2574         // Trigger scripted stuff
2575         m_script->on_dieplayer(playersao);
2576
2577         SendPlayerHP(peer_id);
2578         SendDeathscreen(peer_id, false, v3f(0,0,0));
2579 }
2580
2581 void Server::RespawnPlayer(u16 peer_id)
2582 {
2583         DSTACK(FUNCTION_NAME);
2584
2585         PlayerSAO *playersao = getPlayerSAO(peer_id);
2586         assert(playersao);
2587
2588         infostream << "Server::RespawnPlayer(): Player "
2589                         << playersao->getPlayer()->getName()
2590                         << " respawns" << std::endl;
2591
2592         playersao->setHP(playersao->accessObjectProperties()->hp_max);
2593         playersao->setBreath(PLAYER_MAX_BREATH);
2594
2595         bool repositioned = m_script->on_respawnplayer(playersao);
2596         if (!repositioned) {
2597                 // setPos will send the new position to client
2598                 playersao->setPos(findSpawnPos());
2599         }
2600
2601         SendPlayerHP(peer_id);
2602 }
2603
2604
2605 void Server::DenySudoAccess(u16 peer_id)
2606 {
2607         DSTACK(FUNCTION_NAME);
2608
2609         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2610         Send(&pkt);
2611 }
2612
2613
2614 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2615                 const std::string &str_reason, bool reconnect)
2616 {
2617         if (proto_ver >= 25) {
2618                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2619         } else {
2620                 std::wstring wreason = utf8_to_wide(
2621                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2622                         accessDeniedStrings[(u8)reason]);
2623                 SendAccessDenied_Legacy(peer_id, wreason);
2624         }
2625
2626         m_clients.event(peer_id, CSE_SetDenied);
2627         m_con->DisconnectPeer(peer_id);
2628 }
2629
2630
2631 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2632 {
2633         DSTACK(FUNCTION_NAME);
2634
2635         SendAccessDenied(peer_id, reason, custom_reason);
2636         m_clients.event(peer_id, CSE_SetDenied);
2637         m_con->DisconnectPeer(peer_id);
2638 }
2639
2640 // 13/03/15: remove this function when protocol version 25 will become
2641 // the minimum version for MT users, maybe in 1 year
2642 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2643 {
2644         DSTACK(FUNCTION_NAME);
2645
2646         SendAccessDenied_Legacy(peer_id, reason);
2647         m_clients.event(peer_id, CSE_SetDenied);
2648         m_con->DisconnectPeer(peer_id);
2649 }
2650
2651 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2652 {
2653         DSTACK(FUNCTION_NAME);
2654
2655         if (!forSudoMode) {
2656                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2657
2658                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2659
2660                 // Right now, the auth mechs don't change between login and sudo mode.
2661                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2662                 client->allowed_sudo_mechs = sudo_auth_mechs;
2663
2664                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2665                                 << g_settings->getFloat("dedicated_server_step")
2666                                 << sudo_auth_mechs;
2667
2668                 Send(&resp_pkt);
2669                 m_clients.event(peer_id, CSE_AuthAccept);
2670         } else {
2671                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2672
2673                 // We only support SRP right now
2674                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2675
2676                 resp_pkt << sudo_auth_mechs;
2677                 Send(&resp_pkt);
2678                 m_clients.event(peer_id, CSE_SudoSuccess);
2679         }
2680 }
2681
2682 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2683 {
2684         DSTACK(FUNCTION_NAME);
2685         std::wstring message;
2686         {
2687                 /*
2688                         Clear references to playing sounds
2689                 */
2690                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2691                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2692                         ServerPlayingSound &psound = i->second;
2693                         psound.clients.erase(peer_id);
2694                         if (psound.clients.empty())
2695                                 m_playing_sounds.erase(i++);
2696                         else
2697                                 ++i;
2698                 }
2699
2700                 RemotePlayer *player = m_env->getPlayer(peer_id);
2701
2702                 /* Run scripts and remove from environment */
2703                 if (player) {
2704                         PlayerSAO *playersao = player->getPlayerSAO();
2705                         assert(playersao);
2706
2707                         // inform connected clients
2708                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2709                         // (u16) 1 + std::string represents a vector serialization representation
2710                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
2711                         m_clients.sendToAll(&notice);
2712                         // run scripts
2713                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2714
2715                         playersao->disconnected();
2716                 }
2717
2718                 /*
2719                         Print out action
2720                 */
2721                 {
2722                         if (player && reason != CDR_DENY) {
2723                                 std::ostringstream os(std::ios_base::binary);
2724                                 std::vector<u16> clients = m_clients.getClientIDs();
2725
2726                                 for (const u16 client_id : clients) {
2727                                         // Get player
2728                                         RemotePlayer *player = m_env->getPlayer(client_id);
2729                                         if (!player)
2730                                                 continue;
2731
2732                                         // Get name of player
2733                                         os << player->getName() << " ";
2734                                 }
2735
2736                                 std::string name = player->getName();
2737                                 actionstream << name << " "
2738                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2739                                                 << " List of players: " << os.str() << std::endl;
2740                                 if (m_admin_chat)
2741                                         m_admin_chat->outgoing_queue.push_back(
2742                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2743                         }
2744                 }
2745                 {
2746                         MutexAutoLock env_lock(m_env_mutex);
2747                         m_clients.DeleteClient(peer_id);
2748                 }
2749         }
2750
2751         // Send leave chat message to all remaining clients
2752         if (!message.empty()) {
2753                 SendChatMessage(PEER_ID_INEXISTENT,
2754                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2755         }
2756 }
2757
2758 void Server::UpdateCrafting(RemotePlayer *player)
2759 {
2760         DSTACK(FUNCTION_NAME);
2761
2762         // Get a preview for crafting
2763         ItemStack preview;
2764         InventoryLocation loc;
2765         loc.setPlayer(player->getName());
2766         std::vector<ItemStack> output_replacements;
2767         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2768         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2769                         (&player->inventory)->getList("craft"), loc);
2770
2771         // Put the new preview in
2772         InventoryList *plist = player->inventory.getList("craftpreview");
2773         sanity_check(plist);
2774         sanity_check(plist->getSize() >= 1);
2775         plist->changeItem(0, preview);
2776 }
2777
2778 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2779 {
2780         if (evt->type == CET_NICK_ADD) {
2781                 // The terminal informed us of its nick choice
2782                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2783                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2784                         errorstream << "You haven't set up an account." << std::endl
2785                                 << "Please log in using the client as '"
2786                                 << m_admin_nick << "' with a secure password." << std::endl
2787                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2788                                 << "and everybody can claim the user account instead of you," << std::endl
2789                                 << "giving them full control over this server." << std::endl;
2790                 }
2791         } else {
2792                 assert(evt->type == CET_CHAT);
2793                 handleAdminChat((ChatEventChat *)evt);
2794         }
2795 }
2796
2797 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2798         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2799 {
2800         // If something goes wrong, this player is to blame
2801         RollbackScopeActor rollback_scope(m_rollback,
2802                 std::string("player:") + name);
2803
2804         if (g_settings->getBool("strip_color_codes"))
2805                 wmessage = unescape_enriched(wmessage);
2806
2807         if (player) {
2808                 switch (player->canSendChatMessage()) {
2809                         case RPLAYER_CHATRESULT_FLOODING: {
2810                                 std::wstringstream ws;
2811                                 ws << L"You cannot send more messages. You are limited to "
2812                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2813                                    << L" messages per 10 seconds.";
2814                                 return ws.str();
2815                         }
2816                         case RPLAYER_CHATRESULT_KICK:
2817                                 DenyAccess_Legacy(player->peer_id,
2818                                                 L"You have been kicked due to message flooding.");
2819                                 return L"";
2820                         case RPLAYER_CHATRESULT_OK:
2821                                 break;
2822                         default:
2823                                 FATAL_ERROR("Unhandled chat filtering result found.");
2824                 }
2825         }
2826
2827         if (m_max_chatmessage_length > 0
2828                         && wmessage.length() > m_max_chatmessage_length) {
2829                 return L"Your message exceed the maximum chat message limit set on the server. "
2830                                 L"It was refused. Send a shorter message";
2831         }
2832
2833         // Run script hook, exit if script ate the chat message
2834         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2835                 return L"";
2836
2837         // Line to send
2838         std::wstring line;
2839         // Whether to send line to the player that sent the message, or to all players
2840         bool broadcast_line = true;
2841
2842         if (check_shout_priv && !checkPriv(name, "shout")) {
2843                 line += L"-!- You don't have permission to shout.";
2844                 broadcast_line = false;
2845         } else {
2846                 line += L"<";
2847                 line += wname;
2848                 line += L"> ";
2849                 line += wmessage;
2850         }
2851
2852         /*
2853                 Tell calling method to send the message to sender
2854         */
2855         if (!broadcast_line)
2856                 return line;
2857
2858         /*
2859                 Send the message to others
2860         */
2861         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2862
2863         std::vector<u16> clients = m_clients.getClientIDs();
2864
2865         /*
2866                 Send the message back to the inital sender
2867                 if they are using protocol version >= 29
2868         */
2869
2870         u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2871         if (player && player->protocol_version >= 29)
2872                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2873
2874         for (u16 cid : clients) {
2875                 if (cid != peer_id_to_avoid_sending)
2876                         SendChatMessage(cid, ChatMessage(line));
2877         }
2878         return L"";
2879 }
2880
2881 void Server::handleAdminChat(const ChatEventChat *evt)
2882 {
2883         std::string name = evt->nick;
2884         std::wstring wname = utf8_to_wide(name);
2885         std::wstring wmessage = evt->evt_msg;
2886
2887         std::wstring answer = handleChat(name, wname, wmessage);
2888
2889         // If asked to send answer to sender
2890         if (!answer.empty()) {
2891                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2892         }
2893 }
2894
2895 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2896 {
2897         RemoteClient *client = getClientNoEx(peer_id,state_min);
2898         if(!client)
2899                 throw ClientNotFoundException("Client not found");
2900
2901         return client;
2902 }
2903 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2904 {
2905         return m_clients.getClientNoEx(peer_id, state_min);
2906 }
2907
2908 std::string Server::getPlayerName(u16 peer_id)
2909 {
2910         RemotePlayer *player = m_env->getPlayer(peer_id);
2911         if (!player)
2912                 return "[id="+itos(peer_id)+"]";
2913         return player->getName();
2914 }
2915
2916 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2917 {
2918         RemotePlayer *player = m_env->getPlayer(peer_id);
2919         if (!player)
2920                 return NULL;
2921         return player->getPlayerSAO();
2922 }
2923
2924 std::wstring Server::getStatusString()
2925 {
2926         std::wostringstream os(std::ios_base::binary);
2927         os<<L"# Server: ";
2928         // Version
2929         os<<L"version="<<narrow_to_wide(g_version_string);
2930         // Uptime
2931         os<<L", uptime="<<m_uptime.get();
2932         // Max lag estimate
2933         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2934         // Information about clients
2935         bool first = true;
2936         os<<L", clients={";
2937         std::vector<u16> clients = m_clients.getClientIDs();
2938         for (u16 client_id : clients) {
2939                 // Get player
2940                 RemotePlayer *player = m_env->getPlayer(client_id);
2941                 // Get name of player
2942                 std::wstring name = L"unknown";
2943                 if (player)
2944                         name = narrow_to_wide(player->getName());
2945                 // Add name to information string
2946                 if(!first)
2947                         os << L", ";
2948                 else
2949                         first = false;
2950                 os << name;
2951         }
2952         os << L"}";
2953
2954         if (!((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
2955                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2956
2957         if (!g_settings->get("motd").empty())
2958                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2959         return os.str();
2960 }
2961
2962 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2963 {
2964         std::set<std::string> privs;
2965         m_script->getAuth(name, NULL, &privs);
2966         return privs;
2967 }
2968
2969 bool Server::checkPriv(const std::string &name, const std::string &priv)
2970 {
2971         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2972         return (privs.count(priv) != 0);
2973 }
2974
2975 void Server::reportPrivsModified(const std::string &name)
2976 {
2977         if (name.empty()) {
2978                 std::vector<u16> clients = m_clients.getClientIDs();
2979                 for (const u16 client_id : clients) {
2980                         RemotePlayer *player = m_env->getPlayer(client_id);
2981                         reportPrivsModified(player->getName());
2982                 }
2983         } else {
2984                 RemotePlayer *player = m_env->getPlayer(name.c_str());
2985                 if (!player)
2986                         return;
2987                 SendPlayerPrivileges(player->peer_id);
2988                 PlayerSAO *sao = player->getPlayerSAO();
2989                 if(!sao)
2990                         return;
2991                 sao->updatePrivileges(
2992                                 getPlayerEffectivePrivs(name),
2993                                 isSingleplayer());
2994         }
2995 }
2996
2997 void Server::reportInventoryFormspecModified(const std::string &name)
2998 {
2999         RemotePlayer *player = m_env->getPlayer(name.c_str());
3000         if (!player)
3001                 return;
3002         SendPlayerInventoryFormspec(player->peer_id);
3003 }
3004
3005 void Server::setIpBanned(const std::string &ip, const std::string &name)
3006 {
3007         m_banmanager->add(ip, name);
3008 }
3009
3010 void Server::unsetIpBanned(const std::string &ip_or_name)
3011 {
3012         m_banmanager->remove(ip_or_name);
3013 }
3014
3015 std::string Server::getBanDescription(const std::string &ip_or_name)
3016 {
3017         return m_banmanager->getBanDescription(ip_or_name);
3018 }
3019
3020 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3021 {
3022         // m_env will be NULL if the server is initializing
3023         if (!m_env)
3024                 return;
3025
3026         if (m_admin_nick == name && !m_admin_nick.empty()) {
3027                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3028         }
3029
3030         RemotePlayer *player = m_env->getPlayer(name);
3031         if (!player) {
3032                 return;
3033         }
3034
3035         if (player->peer_id == PEER_ID_INEXISTENT)
3036                 return;
3037
3038         SendChatMessage(player->peer_id, ChatMessage(msg));
3039 }
3040
3041 bool Server::showFormspec(const char *playername, const std::string &formspec,
3042         const std::string &formname)
3043 {
3044         // m_env will be NULL if the server is initializing
3045         if (!m_env)
3046                 return false;
3047
3048         RemotePlayer *player = m_env->getPlayer(playername);
3049         if (!player)
3050                 return false;
3051
3052         SendShowFormspecMessage(player->peer_id, formspec, formname);
3053         return true;
3054 }
3055
3056 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3057 {
3058         if (!player)
3059                 return -1;
3060
3061         u32 id = player->addHud(form);
3062
3063         SendHUDAdd(player->peer_id, id, form);
3064
3065         return id;
3066 }
3067
3068 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3069         if (!player)
3070                 return false;
3071
3072         HudElement* todel = player->removeHud(id);
3073
3074         if (!todel)
3075                 return false;
3076
3077         delete todel;
3078
3079         SendHUDRemove(player->peer_id, id);
3080         return true;
3081 }
3082
3083 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3084 {
3085         if (!player)
3086                 return false;
3087
3088         SendHUDChange(player->peer_id, id, stat, data);
3089         return true;
3090 }
3091
3092 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3093 {
3094         if (!player)
3095                 return false;
3096
3097         SendHUDSetFlags(player->peer_id, flags, mask);
3098         player->hud_flags &= ~mask;
3099         player->hud_flags |= flags;
3100
3101         PlayerSAO* playersao = player->getPlayerSAO();
3102
3103         if (!playersao)
3104                 return false;
3105
3106         m_script->player_event(playersao, "hud_changed");
3107         return true;
3108 }
3109
3110 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3111 {
3112         if (!player)
3113                 return false;
3114
3115         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3116                 return false;
3117
3118         player->setHotbarItemcount(hotbar_itemcount);
3119         std::ostringstream os(std::ios::binary);
3120         writeS32(os, hotbar_itemcount);
3121         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3122         return true;
3123 }
3124
3125 s32 Server::hudGetHotbarItemcount(RemotePlayer *player) const
3126 {
3127         return player->getHotbarItemcount();
3128 }
3129
3130 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3131 {
3132         if (!player)
3133                 return;
3134
3135         player->setHotbarImage(name);
3136         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3137 }
3138
3139 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3140 {
3141         if (!player)
3142                 return "";
3143         return player->getHotbarImage();
3144 }
3145
3146 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3147 {
3148         if (!player)
3149                 return;
3150
3151         player->setHotbarSelectedImage(name);
3152         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3153 }
3154
3155 const std::string& Server::hudGetHotbarSelectedImage(RemotePlayer *player) const
3156 {
3157         return player->getHotbarSelectedImage();
3158 }
3159
3160 Address Server::getPeerAddress(u16 peer_id)
3161 {
3162         return m_con->GetPeerAddress(peer_id);
3163 }
3164
3165 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3166                 v2s32 animation_frames[4], f32 frame_speed)
3167 {
3168         if (!player)
3169                 return false;
3170
3171         player->setLocalAnimations(animation_frames, frame_speed);
3172         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3173         return true;
3174 }
3175
3176 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3177 {
3178         if (!player)
3179                 return false;
3180
3181         player->eye_offset_first = first;
3182         player->eye_offset_third = third;
3183         SendEyeOffset(player->peer_id, first, third);
3184         return true;
3185 }
3186
3187 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3188         const std::string &type, const std::vector<std::string> &params,
3189         bool &clouds)
3190 {
3191         if (!player)
3192                 return false;
3193
3194         player->setSky(bgcolor, type, params, clouds);
3195         SendSetSky(player->peer_id, bgcolor, type, params, clouds);
3196         return true;
3197 }
3198
3199 bool Server::setClouds(RemotePlayer *player, float density,
3200         const video::SColor &color_bright,
3201         const video::SColor &color_ambient,
3202         float height,
3203         float thickness,
3204         const v2f &speed)
3205 {
3206         if (!player)
3207                 return false;
3208
3209         SendCloudParams(player->peer_id, density,
3210                         color_bright, color_ambient, height,
3211                         thickness, speed);
3212         return true;
3213 }
3214
3215 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3216         float ratio)
3217 {
3218         if (!player)
3219                 return false;
3220
3221         player->overrideDayNightRatio(do_override, ratio);
3222         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3223         return true;
3224 }
3225
3226 void Server::notifyPlayers(const std::wstring &msg)
3227 {
3228         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3229 }
3230
3231 void Server::spawnParticle(const std::string &playername, v3f pos,
3232         v3f velocity, v3f acceleration,
3233         float expirationtime, float size, bool
3234         collisiondetection, bool collision_removal,
3235         bool vertical, const std::string &texture,
3236         const struct TileAnimationParams &animation, u8 glow)
3237 {
3238         // m_env will be NULL if the server is initializing
3239         if (!m_env)
3240                 return;
3241
3242         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3243         if (!playername.empty()) {
3244                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3245                 if (!player)
3246                         return;
3247                 peer_id = player->peer_id;
3248                 proto_ver = player->protocol_version;
3249         }
3250
3251         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3252                         expirationtime, size, collisiondetection,
3253                         collision_removal, vertical, texture, animation, glow);
3254 }
3255
3256 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3257         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3258         float minexptime, float maxexptime, float minsize, float maxsize,
3259         bool collisiondetection, bool collision_removal,
3260         ServerActiveObject *attached, bool vertical, const std::string &texture,
3261         const std::string &playername, const struct TileAnimationParams &animation,
3262         u8 glow)
3263 {
3264         // m_env will be NULL if the server is initializing
3265         if (!m_env)
3266                 return -1;
3267
3268         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3269         if (!playername.empty()) {
3270                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3271                 if (!player)
3272                         return -1;
3273                 peer_id = player->peer_id;
3274                 proto_ver = player->protocol_version;
3275         }
3276
3277         u16 attached_id = attached ? attached->getId() : 0;
3278
3279         u32 id;
3280         if (attached_id == 0)
3281                 id = m_env->addParticleSpawner(spawntime);
3282         else
3283                 id = m_env->addParticleSpawner(spawntime, attached_id);
3284
3285         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3286                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3287                 minexptime, maxexptime, minsize, maxsize,
3288                 collisiondetection, collision_removal, attached_id, vertical,
3289                 texture, id, animation, glow);
3290
3291         return id;
3292 }
3293
3294 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3295 {
3296         // m_env will be NULL if the server is initializing
3297         if (!m_env)
3298                 throw ServerError("Can't delete particle spawners during initialisation!");
3299
3300         u16 peer_id = PEER_ID_INEXISTENT;
3301         if (!playername.empty()) {
3302                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3303                 if (!player)
3304                         return;
3305                 peer_id = player->peer_id;
3306         }
3307
3308         m_env->deleteParticleSpawner(id);
3309         SendDeleteParticleSpawner(peer_id, id);
3310 }
3311
3312 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3313 {
3314         if(m_detached_inventories.count(name) > 0){
3315                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3316                 delete m_detached_inventories[name];
3317         } else {
3318                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3319         }
3320         Inventory *inv = new Inventory(m_itemdef);
3321         sanity_check(inv);
3322         m_detached_inventories[name] = inv;
3323         m_detached_inventories_player[name] = player;
3324         //TODO find a better way to do this
3325         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3326         return inv;
3327 }
3328
3329 // actions: time-reversed list
3330 // Return value: success/failure
3331 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3332                 std::list<std::string> *log)
3333 {
3334         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3335         ServerMap *map = (ServerMap*)(&m_env->getMap());
3336
3337         // Fail if no actions to handle
3338         if(actions.empty()){
3339                 log->push_back("Nothing to do.");
3340                 return false;
3341         }
3342
3343         int num_tried = 0;
3344         int num_failed = 0;
3345
3346         for (const RollbackAction &action : actions) {
3347                 num_tried++;
3348                 bool success = action.applyRevert(map, this, this);
3349                 if(!success){
3350                         num_failed++;
3351                         std::ostringstream os;
3352                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3353                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3354                         if (log)
3355                                 log->push_back(os.str());
3356                 }else{
3357                         std::ostringstream os;
3358                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3359                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3360                         if (log)
3361                                 log->push_back(os.str());
3362                 }
3363         }
3364
3365         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3366                         <<" failed"<<std::endl;
3367
3368         // Call it done if less than half failed
3369         return num_failed <= num_tried/2;
3370 }
3371
3372 // IGameDef interface
3373 // Under envlock
3374 IItemDefManager *Server::getItemDefManager()
3375 {
3376         return m_itemdef;
3377 }
3378
3379 INodeDefManager *Server::getNodeDefManager()
3380 {
3381         return m_nodedef;
3382 }
3383
3384 ICraftDefManager *Server::getCraftDefManager()
3385 {
3386         return m_craftdef;
3387 }
3388
3389 u16 Server::allocateUnknownNodeId(const std::string &name)
3390 {
3391         return m_nodedef->allocateDummy(name);
3392 }
3393
3394 MtEventManager *Server::getEventManager()
3395 {
3396         return m_event;
3397 }
3398
3399 IWritableItemDefManager *Server::getWritableItemDefManager()
3400 {
3401         return m_itemdef;
3402 }
3403
3404 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3405 {
3406         return m_nodedef;
3407 }
3408
3409 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3410 {
3411         return m_craftdef;
3412 }
3413
3414 const ModSpec *Server::getModSpec(const std::string &modname) const
3415 {
3416         std::vector<ModSpec>::const_iterator it;
3417         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3418                 const ModSpec &mod = *it;
3419                 if (mod.name == modname)
3420                         return &mod;
3421         }
3422         return NULL;
3423 }
3424
3425 void Server::getModNames(std::vector<std::string> &modlist)
3426 {
3427         std::vector<ModSpec>::iterator it;
3428         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3429                 modlist.push_back(it->name);
3430 }
3431
3432 std::string Server::getBuiltinLuaPath()
3433 {
3434         return porting::path_share + DIR_DELIM + "builtin";
3435 }
3436
3437 std::string Server::getModStoragePath() const
3438 {
3439         return m_path_world + DIR_DELIM + "mod_storage";
3440 }
3441
3442 v3f Server::findSpawnPos()
3443 {
3444         ServerMap &map = m_env->getServerMap();
3445         v3f nodeposf;
3446         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3447                 return nodeposf * BS;
3448         }
3449
3450         bool is_good = false;
3451         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3452         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3453
3454         // Try to find a good place a few times
3455         for(s32 i = 0; i < 4000 && !is_good; i++) {
3456                 s32 range = MYMIN(1 + i, range_max);
3457                 // We're going to try to throw the player to this position
3458                 v2s16 nodepos2d = v2s16(
3459                         -range + (myrand() % (range * 2)),
3460                         -range + (myrand() % (range * 2)));
3461
3462                 // Get spawn level at point
3463                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3464                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3465                 // the mapgen to signify an unsuitable spawn position
3466                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3467                         continue;
3468
3469                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3470
3471                 s32 air_count = 0;
3472                 for (s32 i = 0; i < 10; i++) {
3473                         v3s16 blockpos = getNodeBlockPos(nodepos);
3474                         map.emergeBlock(blockpos, true);
3475                         content_t c = map.getNodeNoEx(nodepos).getContent();
3476                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3477                                 air_count++;
3478                                 if (air_count >= 2) {
3479                                         nodeposf = intToFloat(nodepos, BS);
3480                                         // Don't spawn the player outside map boundaries
3481                                         if (objectpos_over_limit(nodeposf))
3482                                                 continue;
3483                                         is_good = true;
3484                                         break;
3485                                 }
3486                         }
3487                         nodepos.Y++;
3488                 }
3489         }
3490
3491         return nodeposf;
3492 }
3493
3494 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3495 {
3496         m_shutdown_timer = delay;
3497         m_shutdown_msg = msg;
3498         m_shutdown_ask_reconnect = reconnect;
3499
3500         if (delay == 0.0f) {
3501         // No delay, shutdown immediately
3502                 m_shutdown_requested = true;
3503                 // only print to the infostream, a chat message saying
3504                 // "Server Shutting Down" is sent when the server destructs.
3505                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3506         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3507         // Negative delay, cancel shutdown if requested
3508                 m_shutdown_timer = 0.0f;
3509                 m_shutdown_msg = "";
3510                 m_shutdown_ask_reconnect = false;
3511                 m_shutdown_requested = false;
3512                 std::wstringstream ws;
3513
3514                 ws << L"*** Server shutdown canceled.";
3515
3516                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3517                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3518         } else if (delay > 0.0f) {
3519         // Positive delay, tell the clients when the server will shut down
3520                 std::wstringstream ws;
3521
3522                 ws << L"*** Server shutting down in "
3523                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3524                                 << ".";
3525
3526                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3527                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3528         }
3529 }
3530
3531 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3532 {
3533         /*
3534                 Try to get an existing player
3535         */
3536         RemotePlayer *player = m_env->getPlayer(name);
3537
3538         // If player is already connected, cancel
3539         if (player && player->peer_id != 0) {
3540                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3541                 return NULL;
3542         }
3543
3544         /*
3545                 If player with the wanted peer_id already exists, cancel.
3546         */
3547         if (m_env->getPlayer(peer_id)) {
3548                 infostream<<"emergePlayer(): Player with wrong name but same"
3549                                 " peer_id already exists"<<std::endl;
3550                 return NULL;
3551         }
3552
3553         if (!player) {
3554                 player = new RemotePlayer(name, idef());
3555         }
3556
3557         bool newplayer = false;
3558
3559         // Load player
3560         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3561
3562         // Complete init with server parts
3563         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3564         player->protocol_version = proto_version;
3565
3566         /* Run scripts */
3567         if (newplayer) {
3568                 m_script->on_newplayer(playersao);
3569         }
3570
3571         return playersao;
3572 }
3573
3574 bool Server::registerModStorage(ModMetadata *storage)
3575 {
3576         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3577                 errorstream << "Unable to register same mod storage twice. Storage name: "
3578                                 << storage->getModName() << std::endl;
3579                 return false;
3580         }
3581
3582         m_mod_storages[storage->getModName()] = storage;
3583         return true;
3584 }
3585
3586 void Server::unregisterModStorage(const std::string &name)
3587 {
3588         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3589         if (it != m_mod_storages.end()) {
3590                 // Save unconditionaly on unregistration
3591                 it->second->save(getModStoragePath());
3592                 m_mod_storages.erase(name);
3593         }
3594 }
3595
3596 void dedicated_server_loop(Server &server, bool &kill)
3597 {
3598         DSTACK(FUNCTION_NAME);
3599
3600         verbosestream<<"dedicated_server_loop()"<<std::endl;
3601
3602         IntervalLimiter m_profiler_interval;
3603
3604         static thread_local const float steplen =
3605                         g_settings->getFloat("dedicated_server_step");
3606         static thread_local const float profiler_print_interval =
3607                         g_settings->getFloat("profiler_print_interval");
3608
3609         for(;;) {
3610                 // This is kind of a hack but can be done like this
3611                 // because server.step() is very light
3612                 {
3613                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3614                         sleep_ms((int)(steplen*1000.0));
3615                 }
3616                 server.step(steplen);
3617
3618                 if (server.getShutdownRequested() || kill)
3619                         break;
3620
3621                 /*
3622                         Profiler
3623                 */
3624                 if (profiler_print_interval != 0) {
3625                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3626                         {
3627                                 infostream<<"Profiler:"<<std::endl;
3628                                 g_profiler->print(infostream);
3629                                 g_profiler->clear();
3630                         }
3631                 }
3632         }
3633
3634         infostream << "Dedicated server quitting" << std::endl;
3635 #if USE_CURL
3636         if (g_settings->getBool("server_announce"))
3637                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3638                         server.m_bind_addr.getPort());
3639 #endif
3640 }