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