Fix builtin inventory list crash when size = 0 (#7297)
[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         InventoryList *clist = player->inventory.getList("craft");
2689         if (!clist || clist->getSize() == 0)
2690                 return;
2691
2692         // Get a preview for crafting
2693         ItemStack preview;
2694         InventoryLocation loc;
2695         loc.setPlayer(player->getName());
2696         std::vector<ItemStack> output_replacements;
2697         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2698         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2699                         clist, loc);
2700
2701         InventoryList *plist = player->inventory.getList("craftpreview");
2702         if (plist && plist->getSize() >= 1) {
2703                 // Put the new preview in
2704                 plist->changeItem(0, preview);
2705         }
2706 }
2707
2708 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2709 {
2710         if (evt->type == CET_NICK_ADD) {
2711                 // The terminal informed us of its nick choice
2712                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2713                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2714                         errorstream << "You haven't set up an account." << std::endl
2715                                 << "Please log in using the client as '"
2716                                 << m_admin_nick << "' with a secure password." << std::endl
2717                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2718                                 << "and everybody can claim the user account instead of you," << std::endl
2719                                 << "giving them full control over this server." << std::endl;
2720                 }
2721         } else {
2722                 assert(evt->type == CET_CHAT);
2723                 handleAdminChat((ChatEventChat *)evt);
2724         }
2725 }
2726
2727 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2728         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2729 {
2730         // If something goes wrong, this player is to blame
2731         RollbackScopeActor rollback_scope(m_rollback,
2732                 std::string("player:") + name);
2733
2734         if (g_settings->getBool("strip_color_codes"))
2735                 wmessage = unescape_enriched(wmessage);
2736
2737         if (player) {
2738                 switch (player->canSendChatMessage()) {
2739                         case RPLAYER_CHATRESULT_FLOODING: {
2740                                 std::wstringstream ws;
2741                                 ws << L"You cannot send more messages. You are limited to "
2742                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2743                                    << L" messages per 10 seconds.";
2744                                 return ws.str();
2745                         }
2746                         case RPLAYER_CHATRESULT_KICK:
2747                                 DenyAccess_Legacy(player->getPeerId(),
2748                                                 L"You have been kicked due to message flooding.");
2749                                 return L"";
2750                         case RPLAYER_CHATRESULT_OK:
2751                                 break;
2752                         default:
2753                                 FATAL_ERROR("Unhandled chat filtering result found.");
2754                 }
2755         }
2756
2757         if (m_max_chatmessage_length > 0
2758                         && wmessage.length() > m_max_chatmessage_length) {
2759                 return L"Your message exceed the maximum chat message limit set on the server. "
2760                                 L"It was refused. Send a shorter message";
2761         }
2762
2763         // Run script hook, exit if script ate the chat message
2764         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2765                 return L"";
2766
2767         // Line to send
2768         std::wstring line;
2769         // Whether to send line to the player that sent the message, or to all players
2770         bool broadcast_line = true;
2771
2772         if (check_shout_priv && !checkPriv(name, "shout")) {
2773                 line += L"-!- You don't have permission to shout.";
2774                 broadcast_line = false;
2775         } else {
2776                 line += L"<";
2777                 line += wname;
2778                 line += L"> ";
2779                 line += wmessage;
2780         }
2781
2782         /*
2783                 Tell calling method to send the message to sender
2784         */
2785         if (!broadcast_line)
2786                 return line;
2787
2788         /*
2789                 Send the message to others
2790         */
2791         actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2792
2793         std::vector<session_t> clients = m_clients.getClientIDs();
2794
2795         /*
2796                 Send the message back to the inital sender
2797                 if they are using protocol version >= 29
2798         */
2799
2800         session_t peer_id_to_avoid_sending =
2801                 (player ? player->getPeerId() : PEER_ID_INEXISTENT);
2802
2803         if (player && player->protocol_version >= 29)
2804                 peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2805
2806         for (u16 cid : clients) {
2807                 if (cid != peer_id_to_avoid_sending)
2808                         SendChatMessage(cid, ChatMessage(line));
2809         }
2810         return L"";
2811 }
2812
2813 void Server::handleAdminChat(const ChatEventChat *evt)
2814 {
2815         std::string name = evt->nick;
2816         std::wstring wname = utf8_to_wide(name);
2817         std::wstring wmessage = evt->evt_msg;
2818
2819         std::wstring answer = handleChat(name, wname, wmessage);
2820
2821         // If asked to send answer to sender
2822         if (!answer.empty()) {
2823                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2824         }
2825 }
2826
2827 RemoteClient *Server::getClient(session_t peer_id, ClientState state_min)
2828 {
2829         RemoteClient *client = getClientNoEx(peer_id,state_min);
2830         if(!client)
2831                 throw ClientNotFoundException("Client not found");
2832
2833         return client;
2834 }
2835 RemoteClient *Server::getClientNoEx(session_t peer_id, ClientState state_min)
2836 {
2837         return m_clients.getClientNoEx(peer_id, state_min);
2838 }
2839
2840 std::string Server::getPlayerName(session_t peer_id)
2841 {
2842         RemotePlayer *player = m_env->getPlayer(peer_id);
2843         if (!player)
2844                 return "[id="+itos(peer_id)+"]";
2845         return player->getName();
2846 }
2847
2848 PlayerSAO *Server::getPlayerSAO(session_t peer_id)
2849 {
2850         RemotePlayer *player = m_env->getPlayer(peer_id);
2851         if (!player)
2852                 return NULL;
2853         return player->getPlayerSAO();
2854 }
2855
2856 std::wstring Server::getStatusString()
2857 {
2858         std::wostringstream os(std::ios_base::binary);
2859         os<<L"# Server: ";
2860         // Version
2861         os<<L"version="<<narrow_to_wide(g_version_string);
2862         // Uptime
2863         os<<L", uptime="<<m_uptime.get();
2864         // Max lag estimate
2865         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2866         // Information about clients
2867         bool first = true;
2868         os<<L", clients={";
2869         std::vector<session_t> clients = m_clients.getClientIDs();
2870         for (session_t client_id : clients) {
2871                 // Get player
2872                 RemotePlayer *player = m_env->getPlayer(client_id);
2873                 // Get name of player
2874                 std::wstring name = L"unknown";
2875                 if (player)
2876                         name = narrow_to_wide(player->getName());
2877                 // Add name to information string
2878                 if(!first)
2879                         os << L", ";
2880                 else
2881                         first = false;
2882                 os << name;
2883         }
2884         os << L"}";
2885
2886         if (!((ServerMap*)(&m_env->getMap()))->isSavingEnabled())
2887                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2888
2889         if (!g_settings->get("motd").empty())
2890                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2891         return os.str();
2892 }
2893
2894 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2895 {
2896         std::set<std::string> privs;
2897         m_script->getAuth(name, NULL, &privs);
2898         return privs;
2899 }
2900
2901 bool Server::checkPriv(const std::string &name, const std::string &priv)
2902 {
2903         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2904         return (privs.count(priv) != 0);
2905 }
2906
2907 void Server::reportPrivsModified(const std::string &name)
2908 {
2909         if (name.empty()) {
2910                 std::vector<session_t> clients = m_clients.getClientIDs();
2911                 for (const session_t client_id : clients) {
2912                         RemotePlayer *player = m_env->getPlayer(client_id);
2913                         reportPrivsModified(player->getName());
2914                 }
2915         } else {
2916                 RemotePlayer *player = m_env->getPlayer(name.c_str());
2917                 if (!player)
2918                         return;
2919                 SendPlayerPrivileges(player->getPeerId());
2920                 PlayerSAO *sao = player->getPlayerSAO();
2921                 if(!sao)
2922                         return;
2923                 sao->updatePrivileges(
2924                                 getPlayerEffectivePrivs(name),
2925                                 isSingleplayer());
2926         }
2927 }
2928
2929 void Server::reportInventoryFormspecModified(const std::string &name)
2930 {
2931         RemotePlayer *player = m_env->getPlayer(name.c_str());
2932         if (!player)
2933                 return;
2934         SendPlayerInventoryFormspec(player->getPeerId());
2935 }
2936
2937 void Server::reportFormspecPrependModified(const std::string &name)
2938 {
2939         RemotePlayer *player = m_env->getPlayer(name.c_str());
2940         if (!player)
2941                 return;
2942         SendPlayerFormspecPrepend(player->getPeerId());
2943 }
2944
2945 void Server::setIpBanned(const std::string &ip, const std::string &name)
2946 {
2947         m_banmanager->add(ip, name);
2948 }
2949
2950 void Server::unsetIpBanned(const std::string &ip_or_name)
2951 {
2952         m_banmanager->remove(ip_or_name);
2953 }
2954
2955 std::string Server::getBanDescription(const std::string &ip_or_name)
2956 {
2957         return m_banmanager->getBanDescription(ip_or_name);
2958 }
2959
2960 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2961 {
2962         // m_env will be NULL if the server is initializing
2963         if (!m_env)
2964                 return;
2965
2966         if (m_admin_nick == name && !m_admin_nick.empty()) {
2967                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
2968         }
2969
2970         RemotePlayer *player = m_env->getPlayer(name);
2971         if (!player) {
2972                 return;
2973         }
2974
2975         if (player->getPeerId() == PEER_ID_INEXISTENT)
2976                 return;
2977
2978         SendChatMessage(player->getPeerId(), ChatMessage(msg));
2979 }
2980
2981 bool Server::showFormspec(const char *playername, const std::string &formspec,
2982         const std::string &formname)
2983 {
2984         // m_env will be NULL if the server is initializing
2985         if (!m_env)
2986                 return false;
2987
2988         RemotePlayer *player = m_env->getPlayer(playername);
2989         if (!player)
2990                 return false;
2991
2992         SendShowFormspecMessage(player->getPeerId(), formspec, formname);
2993         return true;
2994 }
2995
2996 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
2997 {
2998         if (!player)
2999                 return -1;
3000
3001         u32 id = player->addHud(form);
3002
3003         SendHUDAdd(player->getPeerId(), id, form);
3004
3005         return id;
3006 }
3007
3008 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3009         if (!player)
3010                 return false;
3011
3012         HudElement* todel = player->removeHud(id);
3013
3014         if (!todel)
3015                 return false;
3016
3017         delete todel;
3018
3019         SendHUDRemove(player->getPeerId(), id);
3020         return true;
3021 }
3022
3023 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3024 {
3025         if (!player)
3026                 return false;
3027
3028         SendHUDChange(player->getPeerId(), id, stat, data);
3029         return true;
3030 }
3031
3032 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3033 {
3034         if (!player)
3035                 return false;
3036
3037         SendHUDSetFlags(player->getPeerId(), flags, mask);
3038         player->hud_flags &= ~mask;
3039         player->hud_flags |= flags;
3040
3041         PlayerSAO* playersao = player->getPlayerSAO();
3042
3043         if (!playersao)
3044                 return false;
3045
3046         m_script->player_event(playersao, "hud_changed");
3047         return true;
3048 }
3049
3050 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3051 {
3052         if (!player)
3053                 return false;
3054
3055         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3056                 return false;
3057
3058         player->setHotbarItemcount(hotbar_itemcount);
3059         std::ostringstream os(std::ios::binary);
3060         writeS32(os, hotbar_itemcount);
3061         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3062         return true;
3063 }
3064
3065 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3066 {
3067         if (!player)
3068                 return;
3069
3070         player->setHotbarImage(name);
3071         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_IMAGE, name);
3072 }
3073
3074 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3075 {
3076         if (!player)
3077                 return;
3078
3079         player->setHotbarSelectedImage(name);
3080         SendHUDSetParam(player->getPeerId(), HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3081 }
3082
3083 Address Server::getPeerAddress(session_t peer_id)
3084 {
3085         return m_con->GetPeerAddress(peer_id);
3086 }
3087
3088 void Server::setLocalPlayerAnimations(RemotePlayer *player,
3089                 v2s32 animation_frames[4], f32 frame_speed)
3090 {
3091         sanity_check(player);
3092         player->setLocalAnimations(animation_frames, frame_speed);
3093         SendLocalPlayerAnimations(player->getPeerId(), animation_frames, frame_speed);
3094 }
3095
3096 void Server::setPlayerEyeOffset(RemotePlayer *player, const v3f &first, const v3f &third)
3097 {
3098         sanity_check(player);
3099         player->eye_offset_first = first;
3100         player->eye_offset_third = third;
3101         SendEyeOffset(player->getPeerId(), first, third);
3102 }
3103
3104 void Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3105         const std::string &type, const std::vector<std::string> &params,
3106         bool &clouds)
3107 {
3108         sanity_check(player);
3109         player->setSky(bgcolor, type, params, clouds);
3110         SendSetSky(player->getPeerId(), bgcolor, type, params, clouds);
3111 }
3112
3113 void Server::setClouds(RemotePlayer *player, const CloudParams &params)
3114 {
3115         sanity_check(player);
3116         player->setCloudParams(params);
3117         SendCloudParams(player->getPeerId(), params);
3118 }
3119
3120 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3121         float ratio)
3122 {
3123         if (!player)
3124                 return false;
3125
3126         player->overrideDayNightRatio(do_override, ratio);
3127         SendOverrideDayNightRatio(player->getPeerId(), do_override, ratio);
3128         return true;
3129 }
3130
3131 void Server::notifyPlayers(const std::wstring &msg)
3132 {
3133         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3134 }
3135
3136 void Server::spawnParticle(const std::string &playername, v3f pos,
3137         v3f velocity, v3f acceleration,
3138         float expirationtime, float size, bool
3139         collisiondetection, bool collision_removal,
3140         bool vertical, const std::string &texture,
3141         const struct TileAnimationParams &animation, u8 glow)
3142 {
3143         // m_env will be NULL if the server is initializing
3144         if (!m_env)
3145                 return;
3146
3147         session_t peer_id = PEER_ID_INEXISTENT;
3148         u16 proto_ver = 0;
3149         if (!playername.empty()) {
3150                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3151                 if (!player)
3152                         return;
3153                 peer_id = player->getPeerId();
3154                 proto_ver = player->protocol_version;
3155         }
3156
3157         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3158                         expirationtime, size, collisiondetection,
3159                         collision_removal, vertical, texture, animation, glow);
3160 }
3161
3162 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3163         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3164         float minexptime, float maxexptime, float minsize, float maxsize,
3165         bool collisiondetection, bool collision_removal,
3166         ServerActiveObject *attached, bool vertical, const std::string &texture,
3167         const std::string &playername, const struct TileAnimationParams &animation,
3168         u8 glow)
3169 {
3170         // m_env will be NULL if the server is initializing
3171         if (!m_env)
3172                 return -1;
3173
3174         session_t peer_id = PEER_ID_INEXISTENT;
3175         u16 proto_ver = 0;
3176         if (!playername.empty()) {
3177                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3178                 if (!player)
3179                         return -1;
3180                 peer_id = player->getPeerId();
3181                 proto_ver = player->protocol_version;
3182         }
3183
3184         u16 attached_id = attached ? attached->getId() : 0;
3185
3186         u32 id;
3187         if (attached_id == 0)
3188                 id = m_env->addParticleSpawner(spawntime);
3189         else
3190                 id = m_env->addParticleSpawner(spawntime, attached_id);
3191
3192         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3193                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3194                 minexptime, maxexptime, minsize, maxsize,
3195                 collisiondetection, collision_removal, attached_id, vertical,
3196                 texture, id, animation, glow);
3197
3198         return id;
3199 }
3200
3201 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3202 {
3203         // m_env will be NULL if the server is initializing
3204         if (!m_env)
3205                 throw ServerError("Can't delete particle spawners during initialisation!");
3206
3207         session_t peer_id = PEER_ID_INEXISTENT;
3208         if (!playername.empty()) {
3209                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3210                 if (!player)
3211                         return;
3212                 peer_id = player->getPeerId();
3213         }
3214
3215         m_env->deleteParticleSpawner(id);
3216         SendDeleteParticleSpawner(peer_id, id);
3217 }
3218
3219 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3220 {
3221         if(m_detached_inventories.count(name) > 0){
3222                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3223                 delete m_detached_inventories[name];
3224         } else {
3225                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3226         }
3227         Inventory *inv = new Inventory(m_itemdef);
3228         sanity_check(inv);
3229         m_detached_inventories[name] = inv;
3230         m_detached_inventories_player[name] = player;
3231         //TODO find a better way to do this
3232         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3233         return inv;
3234 }
3235
3236 // actions: time-reversed list
3237 // Return value: success/failure
3238 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3239                 std::list<std::string> *log)
3240 {
3241         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3242         ServerMap *map = (ServerMap*)(&m_env->getMap());
3243
3244         // Fail if no actions to handle
3245         if (actions.empty()) {
3246                 assert(log);
3247                 log->push_back("Nothing to do.");
3248                 return false;
3249         }
3250
3251         int num_tried = 0;
3252         int num_failed = 0;
3253
3254         for (const RollbackAction &action : actions) {
3255                 num_tried++;
3256                 bool success = action.applyRevert(map, this, this);
3257                 if(!success){
3258                         num_failed++;
3259                         std::ostringstream os;
3260                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3261                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3262                         if (log)
3263                                 log->push_back(os.str());
3264                 }else{
3265                         std::ostringstream os;
3266                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3267                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3268                         if (log)
3269                                 log->push_back(os.str());
3270                 }
3271         }
3272
3273         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3274                         <<" failed"<<std::endl;
3275
3276         // Call it done if less than half failed
3277         return num_failed <= num_tried/2;
3278 }
3279
3280 // IGameDef interface
3281 // Under envlock
3282 IItemDefManager *Server::getItemDefManager()
3283 {
3284         return m_itemdef;
3285 }
3286
3287 const NodeDefManager *Server::getNodeDefManager()
3288 {
3289         return m_nodedef;
3290 }
3291
3292 ICraftDefManager *Server::getCraftDefManager()
3293 {
3294         return m_craftdef;
3295 }
3296
3297 u16 Server::allocateUnknownNodeId(const std::string &name)
3298 {
3299         return m_nodedef->allocateDummy(name);
3300 }
3301
3302 IWritableItemDefManager *Server::getWritableItemDefManager()
3303 {
3304         return m_itemdef;
3305 }
3306
3307 NodeDefManager *Server::getWritableNodeDefManager()
3308 {
3309         return m_nodedef;
3310 }
3311
3312 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3313 {
3314         return m_craftdef;
3315 }
3316
3317 const std::vector<ModSpec> & Server::getMods() const
3318 {
3319         return m_modmgr->getMods();
3320 }
3321
3322 const ModSpec *Server::getModSpec(const std::string &modname) const
3323 {
3324         return m_modmgr->getModSpec(modname);
3325 }
3326
3327 void Server::getModNames(std::vector<std::string> &modlist)
3328 {
3329         m_modmgr->getModNames(modlist);
3330 }
3331
3332 std::string Server::getBuiltinLuaPath()
3333 {
3334         return porting::path_share + DIR_DELIM + "builtin";
3335 }
3336
3337 std::string Server::getModStoragePath() const
3338 {
3339         return m_path_world + DIR_DELIM + "mod_storage";
3340 }
3341
3342 v3f Server::findSpawnPos()
3343 {
3344         ServerMap &map = m_env->getServerMap();
3345         v3f nodeposf;
3346         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3347                 return nodeposf * BS;
3348         }
3349
3350         bool is_good = false;
3351         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3352         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3353
3354         // Try to find a good place a few times
3355         for(s32 i = 0; i < 4000 && !is_good; i++) {
3356                 s32 range = MYMIN(1 + i, range_max);
3357                 // We're going to try to throw the player to this position
3358                 v2s16 nodepos2d = v2s16(
3359                         -range + (myrand() % (range * 2)),
3360                         -range + (myrand() % (range * 2)));
3361
3362                 // Get spawn level at point
3363                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3364                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3365                 // the mapgen to signify an unsuitable spawn position
3366                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3367                         continue;
3368
3369                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3370
3371                 s32 air_count = 0;
3372                 for (s32 i = 0; i < 10; i++) {
3373                         v3s16 blockpos = getNodeBlockPos(nodepos);
3374                         map.emergeBlock(blockpos, true);
3375                         content_t c = map.getNodeNoEx(nodepos).getContent();
3376                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3377                                 air_count++;
3378                                 if (air_count >= 2) {
3379                                         nodeposf = intToFloat(nodepos, BS);
3380                                         // Don't spawn the player outside map boundaries
3381                                         if (objectpos_over_limit(nodeposf))
3382                                                 continue;
3383                                         is_good = true;
3384                                         break;
3385                                 }
3386                         }
3387                         nodepos.Y++;
3388                 }
3389         }
3390
3391         return nodeposf;
3392 }
3393
3394 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3395 {
3396         m_shutdown_timer = delay;
3397         m_shutdown_msg = msg;
3398         m_shutdown_ask_reconnect = reconnect;
3399
3400         if (delay == 0.0f) {
3401         // No delay, shutdown immediately
3402                 m_shutdown_requested = true;
3403                 // only print to the infostream, a chat message saying
3404                 // "Server Shutting Down" is sent when the server destructs.
3405                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3406         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3407         // Negative delay, cancel shutdown if requested
3408                 m_shutdown_timer = 0.0f;
3409                 m_shutdown_msg = "";
3410                 m_shutdown_ask_reconnect = false;
3411                 m_shutdown_requested = false;
3412                 std::wstringstream ws;
3413
3414                 ws << L"*** Server shutdown canceled.";
3415
3416                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3417                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3418         } else if (delay > 0.0f) {
3419         // Positive delay, tell the clients when the server will shut down
3420                 std::wstringstream ws;
3421
3422                 ws << L"*** Server shutting down in "
3423                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3424                                 << ".";
3425
3426                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3427                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3428         }
3429 }
3430
3431 PlayerSAO* Server::emergePlayer(const char *name, session_t peer_id, u16 proto_version)
3432 {
3433         /*
3434                 Try to get an existing player
3435         */
3436         RemotePlayer *player = m_env->getPlayer(name);
3437
3438         // If player is already connected, cancel
3439         if (player && player->getPeerId() != PEER_ID_INEXISTENT) {
3440                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3441                 return NULL;
3442         }
3443
3444         /*
3445                 If player with the wanted peer_id already exists, cancel.
3446         */
3447         if (m_env->getPlayer(peer_id)) {
3448                 infostream<<"emergePlayer(): Player with wrong name but same"
3449                                 " peer_id already exists"<<std::endl;
3450                 return NULL;
3451         }
3452
3453         if (!player) {
3454                 player = new RemotePlayer(name, idef());
3455         }
3456
3457         bool newplayer = false;
3458
3459         // Load player
3460         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3461
3462         // Complete init with server parts
3463         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3464         player->protocol_version = proto_version;
3465
3466         /* Run scripts */
3467         if (newplayer) {
3468                 m_script->on_newplayer(playersao);
3469         }
3470
3471         return playersao;
3472 }
3473
3474 bool Server::registerModStorage(ModMetadata *storage)
3475 {
3476         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3477                 errorstream << "Unable to register same mod storage twice. Storage name: "
3478                                 << storage->getModName() << std::endl;
3479                 return false;
3480         }
3481
3482         m_mod_storages[storage->getModName()] = storage;
3483         return true;
3484 }
3485
3486 void Server::unregisterModStorage(const std::string &name)
3487 {
3488         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3489         if (it != m_mod_storages.end()) {
3490                 // Save unconditionaly on unregistration
3491                 it->second->save(getModStoragePath());
3492                 m_mod_storages.erase(name);
3493         }
3494 }
3495
3496 void dedicated_server_loop(Server &server, bool &kill)
3497 {
3498         verbosestream<<"dedicated_server_loop()"<<std::endl;
3499
3500         IntervalLimiter m_profiler_interval;
3501
3502         static thread_local const float steplen =
3503                         g_settings->getFloat("dedicated_server_step");
3504         static thread_local const float profiler_print_interval =
3505                         g_settings->getFloat("profiler_print_interval");
3506
3507         for(;;) {
3508                 // This is kind of a hack but can be done like this
3509                 // because server.step() is very light
3510                 {
3511                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3512                         sleep_ms((int)(steplen*1000.0));
3513                 }
3514                 server.step(steplen);
3515
3516                 if (server.getShutdownRequested() || kill)
3517                         break;
3518
3519                 /*
3520                         Profiler
3521                 */
3522                 if (profiler_print_interval != 0) {
3523                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3524                         {
3525                                 infostream<<"Profiler:"<<std::endl;
3526                                 g_profiler->print(infostream);
3527                                 g_profiler->clear();
3528                         }
3529                 }
3530         }
3531
3532         infostream << "Dedicated server quitting" << std::endl;
3533 #if USE_CURL
3534         if (g_settings->getBool("server_announce"))
3535                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3536                         server.m_bind_addr.getPort());
3537 #endif
3538 }
3539
3540 /*
3541  * Mod channels
3542  */
3543
3544
3545 bool Server::joinModChannel(const std::string &channel)
3546 {
3547         return m_modchannel_mgr->joinChannel(channel, PEER_ID_SERVER) &&
3548                         m_modchannel_mgr->setChannelState(channel, MODCHANNEL_STATE_READ_WRITE);
3549 }
3550
3551 bool Server::leaveModChannel(const std::string &channel)
3552 {
3553         return m_modchannel_mgr->leaveChannel(channel, PEER_ID_SERVER);
3554 }
3555
3556 bool Server::sendModChannelMessage(const std::string &channel, const std::string &message)
3557 {
3558         if (!m_modchannel_mgr->canWriteOnChannel(channel))
3559                 return false;
3560
3561         broadcastModChannelMessage(channel, message, PEER_ID_SERVER);
3562         return true;
3563 }
3564
3565 ModChannel* Server::getModChannel(const std::string &channel)
3566 {
3567         return m_modchannel_mgr->getModChannel(channel);
3568 }
3569
3570 void Server::broadcastModChannelMessage(const std::string &channel,
3571                 const std::string &message, session_t from_peer)
3572 {
3573         const std::vector<u16> &peers = m_modchannel_mgr->getChannelPeers(channel);
3574         if (peers.empty())
3575                 return;
3576
3577         if (message.size() > STRING_MAX_LEN) {
3578                 warningstream << "ModChannel message too long, dropping before sending "
3579                                 << " (" << message.size() << " > " << STRING_MAX_LEN << ", channel: "
3580                                 << channel << ")" << std::endl;
3581                 return;
3582         }
3583
3584         std::string sender;
3585         if (from_peer != PEER_ID_SERVER) {
3586                 sender = getPlayerName(from_peer);
3587         }
3588
3589         NetworkPacket resp_pkt(TOCLIENT_MODCHANNEL_MSG,
3590                         2 + channel.size() + 2 + sender.size() + 2 + message.size());
3591         resp_pkt << channel << sender << message;
3592         for (session_t peer_id : peers) {
3593                 // Ignore sender
3594                 if (peer_id == from_peer)
3595                         continue;
3596
3597                 Send(peer_id, &resp_pkt);
3598         }
3599
3600         if (from_peer != PEER_ID_SERVER) {
3601                 m_script->on_modchannel_message(channel, sender, message);
3602         }
3603 }