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