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