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