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