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