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