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