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