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