Add Lua errors to error dialog
[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                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
244                         it != unsatisfied_mods.end(); ++it) {
245                         ModSpec mod = *it;
246                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
247                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
248                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
249                                 errorstream << " \"" << *dep_it << "\"";
250                         errorstream << std::endl;
251                 }
252         }
253
254         Settings worldmt_settings;
255         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
256         worldmt_settings.readConfigFile(worldmt.c_str());
257         std::vector<std::string> names = worldmt_settings.getNames();
258         std::set<std::string> load_mod_names;
259         for(std::vector<std::string>::iterator it = names.begin();
260                 it != names.end(); ++it) {
261                 std::string name = *it;
262                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
263                         load_mod_names.insert(name.substr(9));
264         }
265         // complain about mods declared to be loaded, but not found
266         for(std::vector<ModSpec>::iterator it = m_mods.begin();
267                         it != m_mods.end(); ++it)
268                 load_mod_names.erase((*it).name);
269         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
270                         it != unsatisfied_mods.end(); ++it)
271                 load_mod_names.erase((*it).name);
272         if(!load_mod_names.empty()) {
273                 errorstream << "The following mods could not be found:";
274                 for(std::set<std::string>::iterator it = load_mod_names.begin();
275                         it != load_mod_names.end(); ++it)
276                         errorstream << " \"" << (*it) << "\"";
277                 errorstream << std::endl;
278         }
279
280         // Lock environment
281         JMutexAutoLock envlock(m_env_mutex);
282
283         // Load mapgen params from Settings
284         m_emerge->loadMapgenParams();
285
286         // Create the Map (loads map_meta.txt, overriding configured mapgen params)
287         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
288
289         // Initialize scripting
290         infostream<<"Server: Initializing Lua"<<std::endl;
291
292         m_script = new GameScripting(this);
293
294         std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";
295         std::string error_msg;
296
297         if (!m_script->loadMod(script_path, BUILTIN_MOD_NAME, &error_msg))
298                 throw ModError("Failed to load and run " + script_path
299                                 + "\nError from Lua:\n" + error_msg);
300
301         // Print mods
302         infostream << "Server: Loading mods: ";
303         for(std::vector<ModSpec>::iterator i = m_mods.begin();
304                         i != m_mods.end(); i++) {
305                 const ModSpec &mod = *i;
306                 infostream << mod.name << " ";
307         }
308         infostream << std::endl;
309         // Load and run "mod" scripts
310         for (std::vector<ModSpec>::iterator i = m_mods.begin();
311                         i != m_mods.end(); i++) {
312                 const ModSpec &mod = *i;
313                 if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
314                         std::ostringstream err;
315                         err << "Error loading mod \"" << mod.name
316                                         << "\": mod_name does not follow naming conventions: "
317                                         << "Only chararacters [a-z0-9_] are allowed." << std::endl;
318                         errorstream << err.str().c_str();
319                         throw ModError(err.str());
320                 }
321                 std::string script_path = mod.path + DIR_DELIM "init.lua";
322                 infostream << "  [" << padStringRight(mod.name, 12) << "] [\""
323                                 << script_path << "\"]" << std::endl;
324                 if (!m_script->loadMod(script_path, mod.name, &error_msg)) {
325                         errorstream << "Server: Failed to load and run "
326                                         << script_path << std::endl;
327                         throw ModError("Failed to load and run " + script_path
328                                         + "\nError from Lua:\n" + error_msg);
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                         return;
1210                 }
1211
1212                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1213                         handleCommand(pkt);
1214                         return;
1215                 }
1216
1217                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1218
1219                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1220                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1221                                         " serialization format invalid or not initialized."
1222                                         " Skipping incoming command=" << command << std::endl;
1223                         return;
1224                 }
1225
1226                 /* Handle commands related to client startup */
1227                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1228                         handleCommand(pkt);
1229                         return;
1230                 }
1231
1232                 if (m_clients.getClientState(peer_id) < CS_Active) {
1233                         if (command == TOSERVER_PLAYERPOS) return;
1234
1235                         errorstream << "Got packet command: " << command << " for peer id "
1236                                         << peer_id << " but client isn't active yet. Dropping packet "
1237                                         << std::endl;
1238                         return;
1239                 }
1240
1241                 handleCommand(pkt);
1242         } catch (SendFailedException &e) {
1243                 errorstream << "Server::ProcessData(): SendFailedException: "
1244                                 << "what=" << e.what()
1245                                 << std::endl;
1246         } catch (PacketError &e) {
1247                 actionstream << "Server::ProcessData(): PacketError: "
1248                                 << "what=" << e.what()
1249                                 << std::endl;
1250         }
1251 }
1252
1253 void Server::setTimeOfDay(u32 time)
1254 {
1255         m_env->setTimeOfDay(time);
1256         m_time_of_day_send_timer = 0;
1257 }
1258
1259 void Server::onMapEditEvent(MapEditEvent *event)
1260 {
1261         if(m_ignore_map_edit_events)
1262                 return;
1263         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1264                 return;
1265         MapEditEvent *e = event->clone();
1266         m_unsent_map_edit_queue.push(e);
1267 }
1268
1269 Inventory* Server::getInventory(const InventoryLocation &loc)
1270 {
1271         switch (loc.type) {
1272         case InventoryLocation::UNDEFINED:
1273         case InventoryLocation::CURRENT_PLAYER:
1274                 break;
1275         case InventoryLocation::PLAYER:
1276         {
1277                 Player *player = m_env->getPlayer(loc.name.c_str());
1278                 if(!player)
1279                         return NULL;
1280                 PlayerSAO *playersao = player->getPlayerSAO();
1281                 if(!playersao)
1282                         return NULL;
1283                 return playersao->getInventory();
1284         }
1285                 break;
1286         case InventoryLocation::NODEMETA:
1287         {
1288                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1289                 if(!meta)
1290                         return NULL;
1291                 return meta->getInventory();
1292         }
1293                 break;
1294         case InventoryLocation::DETACHED:
1295         {
1296                 if(m_detached_inventories.count(loc.name) == 0)
1297                         return NULL;
1298                 return m_detached_inventories[loc.name];
1299         }
1300                 break;
1301         default:
1302                 sanity_check(false); // abort
1303                 break;
1304         }
1305         return NULL;
1306 }
1307 void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
1308 {
1309         switch(loc.type){
1310         case InventoryLocation::UNDEFINED:
1311                 break;
1312         case InventoryLocation::PLAYER:
1313         {
1314                 if (!playerSend)
1315                         return;
1316
1317                 Player *player = m_env->getPlayer(loc.name.c_str());
1318                 if(!player)
1319                         return;
1320                 PlayerSAO *playersao = player->getPlayerSAO();
1321                 if(!playersao)
1322                         return;
1323
1324                 SendInventory(playersao);
1325         }
1326                 break;
1327         case InventoryLocation::NODEMETA:
1328         {
1329                 v3s16 blockpos = getNodeBlockPos(loc.p);
1330
1331                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1332                 if(block)
1333                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1334
1335                 setBlockNotSent(blockpos);
1336         }
1337                 break;
1338         case InventoryLocation::DETACHED:
1339         {
1340                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1341         }
1342                 break;
1343         default:
1344                 sanity_check(false); // abort
1345                 break;
1346         }
1347 }
1348
1349 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1350 {
1351         std::vector<u16> clients = m_clients.getClientIDs();
1352         m_clients.Lock();
1353         // Set the modified blocks unsent for all the clients
1354         for (std::vector<u16>::iterator i = clients.begin();
1355                  i != clients.end(); ++i) {
1356                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1357                                 client->SetBlocksNotSent(block);
1358         }
1359         m_clients.Unlock();
1360 }
1361
1362 void Server::peerAdded(con::Peer *peer)
1363 {
1364         DSTACK(__FUNCTION_NAME);
1365         verbosestream<<"Server::peerAdded(): peer->id="
1366                         <<peer->id<<std::endl;
1367
1368         con::PeerChange c;
1369         c.type = con::PEER_ADDED;
1370         c.peer_id = peer->id;
1371         c.timeout = false;
1372         m_peer_change_queue.push(c);
1373 }
1374
1375 void Server::deletingPeer(con::Peer *peer, bool timeout)
1376 {
1377         DSTACK(__FUNCTION_NAME);
1378         verbosestream<<"Server::deletingPeer(): peer->id="
1379                         <<peer->id<<", timeout="<<timeout<<std::endl;
1380
1381         m_clients.event(peer->id, CSE_Disconnect);
1382         con::PeerChange c;
1383         c.type = con::PEER_REMOVED;
1384         c.peer_id = peer->id;
1385         c.timeout = timeout;
1386         m_peer_change_queue.push(c);
1387 }
1388
1389 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1390 {
1391         *retval = m_con.getPeerStat(peer_id,type);
1392         if (*retval == -1) return false;
1393         return true;
1394 }
1395
1396 bool Server::getClientInfo(
1397                 u16          peer_id,
1398                 ClientState* state,
1399                 u32*         uptime,
1400                 u8*          ser_vers,
1401                 u16*         prot_vers,
1402                 u8*          major,
1403                 u8*          minor,
1404                 u8*          patch,
1405                 std::string* vers_string
1406         )
1407 {
1408         *state = m_clients.getClientState(peer_id);
1409         m_clients.Lock();
1410         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1411
1412         if (client == NULL) {
1413                 m_clients.Unlock();
1414                 return false;
1415         }
1416
1417         *uptime = client->uptime();
1418         *ser_vers = client->serialization_version;
1419         *prot_vers = client->net_proto_version;
1420
1421         *major = client->getMajor();
1422         *minor = client->getMinor();
1423         *patch = client->getPatch();
1424         *vers_string = client->getPatch();
1425
1426         m_clients.Unlock();
1427
1428         return true;
1429 }
1430
1431 void Server::handlePeerChanges()
1432 {
1433         while(m_peer_change_queue.size() > 0)
1434         {
1435                 con::PeerChange c = m_peer_change_queue.front();
1436                 m_peer_change_queue.pop();
1437
1438                 verbosestream<<"Server: Handling peer change: "
1439                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1440                                 <<std::endl;
1441
1442                 switch(c.type)
1443                 {
1444                 case con::PEER_ADDED:
1445                         m_clients.CreateClient(c.peer_id);
1446                         break;
1447
1448                 case con::PEER_REMOVED:
1449                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1450                         break;
1451
1452                 default:
1453                         FATAL_ERROR("Invalid peer change event received!");
1454                         break;
1455                 }
1456         }
1457 }
1458
1459 void Server::Send(NetworkPacket* pkt)
1460 {
1461         m_clients.send(pkt->getPeerId(),
1462                 clientCommandFactoryTable[pkt->getCommand()].channel,
1463                 pkt,
1464                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1465 }
1466
1467 void Server::SendMovement(u16 peer_id)
1468 {
1469         DSTACK(__FUNCTION_NAME);
1470         std::ostringstream os(std::ios_base::binary);
1471
1472         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1473
1474         pkt << g_settings->getFloat("movement_acceleration_default");
1475         pkt << g_settings->getFloat("movement_acceleration_air");
1476         pkt << g_settings->getFloat("movement_acceleration_fast");
1477         pkt << g_settings->getFloat("movement_speed_walk");
1478         pkt << g_settings->getFloat("movement_speed_crouch");
1479         pkt << g_settings->getFloat("movement_speed_fast");
1480         pkt << g_settings->getFloat("movement_speed_climb");
1481         pkt << g_settings->getFloat("movement_speed_jump");
1482         pkt << g_settings->getFloat("movement_liquid_fluidity");
1483         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1484         pkt << g_settings->getFloat("movement_liquid_sink");
1485         pkt << g_settings->getFloat("movement_gravity");
1486
1487         Send(&pkt);
1488 }
1489
1490 void Server::SendHP(u16 peer_id, u8 hp)
1491 {
1492         DSTACK(__FUNCTION_NAME);
1493
1494         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1495         pkt << hp;
1496         Send(&pkt);
1497 }
1498
1499 void Server::SendBreath(u16 peer_id, u16 breath)
1500 {
1501         DSTACK(__FUNCTION_NAME);
1502
1503         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1504         pkt << (u16) breath;
1505         Send(&pkt);
1506 }
1507
1508 void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
1509 {
1510         DSTACK(__FUNCTION_NAME);
1511
1512         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1513         pkt << (u8) reason;
1514
1515         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING) {
1516                 pkt << custom_reason;
1517         }
1518         Send(&pkt);
1519 }
1520
1521 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1522 {
1523         DSTACK(__FUNCTION_NAME);
1524
1525         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1526         pkt << reason;
1527         Send(&pkt);
1528 }
1529
1530 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1531                 v3f camera_point_target)
1532 {
1533         DSTACK(__FUNCTION_NAME);
1534
1535         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1536         pkt << set_camera_point_target << camera_point_target;
1537         Send(&pkt);
1538 }
1539
1540 void Server::SendItemDef(u16 peer_id,
1541                 IItemDefManager *itemdef, u16 protocol_version)
1542 {
1543         DSTACK(__FUNCTION_NAME);
1544
1545         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1546
1547         /*
1548                 u16 command
1549                 u32 length of the next item
1550                 zlib-compressed serialized ItemDefManager
1551         */
1552         std::ostringstream tmp_os(std::ios::binary);
1553         itemdef->serialize(tmp_os, protocol_version);
1554         std::ostringstream tmp_os2(std::ios::binary);
1555         compressZlib(tmp_os.str(), tmp_os2);
1556         pkt.putLongString(tmp_os2.str());
1557
1558         // Make data buffer
1559         verbosestream << "Server: Sending item definitions to id(" << peer_id
1560                         << "): size=" << pkt.getSize() << std::endl;
1561
1562         Send(&pkt);
1563 }
1564
1565 void Server::SendNodeDef(u16 peer_id,
1566                 INodeDefManager *nodedef, u16 protocol_version)
1567 {
1568         DSTACK(__FUNCTION_NAME);
1569
1570         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1571
1572         /*
1573                 u16 command
1574                 u32 length of the next item
1575                 zlib-compressed serialized NodeDefManager
1576         */
1577         std::ostringstream tmp_os(std::ios::binary);
1578         nodedef->serialize(tmp_os, protocol_version);
1579         std::ostringstream tmp_os2(std::ios::binary);
1580         compressZlib(tmp_os.str(), tmp_os2);
1581
1582         pkt.putLongString(tmp_os2.str());
1583
1584         // Make data buffer
1585         verbosestream << "Server: Sending node definitions to id(" << peer_id
1586                         << "): size=" << pkt.getSize() << std::endl;
1587
1588         Send(&pkt);
1589 }
1590
1591 /*
1592         Non-static send methods
1593 */
1594
1595 void Server::SendInventory(PlayerSAO* playerSAO)
1596 {
1597         DSTACK(__FUNCTION_NAME);
1598
1599         UpdateCrafting(playerSAO->getPlayer());
1600
1601         /*
1602                 Serialize it
1603         */
1604
1605         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1606
1607         std::ostringstream os;
1608         playerSAO->getInventory()->serialize(os);
1609
1610         std::string s = os.str();
1611
1612         pkt.putRawString(s.c_str(), s.size());
1613         Send(&pkt);
1614 }
1615
1616 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
1617 {
1618         DSTACK(__FUNCTION_NAME);
1619
1620         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1621         pkt << message;
1622
1623         if (peer_id != PEER_ID_INEXISTENT) {
1624                 Send(&pkt);
1625         }
1626         else {
1627                 m_clients.sendToAll(0, &pkt, true);
1628         }
1629 }
1630
1631 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1632                                      const std::string &formname)
1633 {
1634         DSTACK(__FUNCTION_NAME);
1635
1636         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1637
1638         pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1639         pkt << formname;
1640
1641         Send(&pkt);
1642 }
1643
1644 // Spawns a particle on peer with peer_id
1645 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
1646                                 float expirationtime, float size, bool collisiondetection,
1647                                 bool vertical, std::string texture)
1648 {
1649         DSTACK(__FUNCTION_NAME);
1650
1651         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1652
1653         pkt << pos << velocity << acceleration << expirationtime
1654                         << size << collisiondetection;
1655         pkt.putLongString(texture);
1656         pkt << vertical;
1657
1658         if (peer_id != PEER_ID_INEXISTENT) {
1659                 Send(&pkt);
1660         }
1661         else {
1662                 m_clients.sendToAll(0, &pkt, true);
1663         }
1664 }
1665
1666 // Adds a ParticleSpawner on peer with peer_id
1667 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
1668         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1669         float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
1670 {
1671         DSTACK(__FUNCTION_NAME);
1672
1673         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1674
1675         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1676                         << minacc << maxacc << minexptime << maxexptime << minsize
1677                         << maxsize << collisiondetection;
1678
1679         pkt.putLongString(texture);
1680
1681         pkt << id << vertical;
1682
1683         if (peer_id != PEER_ID_INEXISTENT) {
1684                 Send(&pkt);
1685         }
1686         else {
1687                 m_clients.sendToAll(0, &pkt, true);
1688         }
1689 }
1690
1691 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1692 {
1693         DSTACK(__FUNCTION_NAME);
1694
1695         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1696
1697         // Ugly error in this packet
1698         pkt << (u16) id;
1699
1700         if (peer_id != PEER_ID_INEXISTENT) {
1701                 Send(&pkt);
1702         }
1703         else {
1704                 m_clients.sendToAll(0, &pkt, true);
1705         }
1706
1707 }
1708
1709 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1710 {
1711         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1712
1713         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1714                         << form->text << form->number << form->item << form->dir
1715                         << form->align << form->offset << form->world_pos << form->size;
1716
1717         Send(&pkt);
1718 }
1719
1720 void Server::SendHUDRemove(u16 peer_id, u32 id)
1721 {
1722         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1723         pkt << id;
1724         Send(&pkt);
1725 }
1726
1727 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1728 {
1729         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1730         pkt << id << (u8) stat;
1731
1732         switch (stat) {
1733                 case HUD_STAT_POS:
1734                 case HUD_STAT_SCALE:
1735                 case HUD_STAT_ALIGN:
1736                 case HUD_STAT_OFFSET:
1737                         pkt << *(v2f *) value;
1738                         break;
1739                 case HUD_STAT_NAME:
1740                 case HUD_STAT_TEXT:
1741                         pkt << *(std::string *) value;
1742                         break;
1743                 case HUD_STAT_WORLD_POS:
1744                         pkt << *(v3f *) value;
1745                         break;
1746                 case HUD_STAT_SIZE:
1747                         pkt << *(v2s32 *) value;
1748                         break;
1749                 case HUD_STAT_NUMBER:
1750                 case HUD_STAT_ITEM:
1751                 case HUD_STAT_DIR:
1752                 default:
1753                         pkt << *(u32 *) value;
1754                         break;
1755         }
1756
1757         Send(&pkt);
1758 }
1759
1760 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1761 {
1762         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1763
1764         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1765
1766         pkt << flags << mask;
1767
1768         Send(&pkt);
1769 }
1770
1771 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1772 {
1773         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1774         pkt << param << value;
1775         Send(&pkt);
1776 }
1777
1778 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1779                 const std::string &type, const std::vector<std::string> &params)
1780 {
1781         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1782         pkt << bgcolor << type << (u16) params.size();
1783
1784         for(size_t i=0; i<params.size(); i++)
1785                 pkt << params[i];
1786
1787         Send(&pkt);
1788 }
1789
1790 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1791                 float ratio)
1792 {
1793         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1794                         1 + 2, peer_id);
1795
1796         pkt << do_override << (u16) (ratio * 65535);
1797
1798         Send(&pkt);
1799 }
1800
1801 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1802 {
1803         DSTACK(__FUNCTION_NAME);
1804
1805         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1806         pkt << time << time_speed;
1807
1808         if (peer_id == PEER_ID_INEXISTENT) {
1809                 m_clients.sendToAll(0, &pkt, true);
1810         }
1811         else {
1812                 Send(&pkt);
1813         }
1814 }
1815
1816 void Server::SendPlayerHP(u16 peer_id)
1817 {
1818         DSTACK(__FUNCTION_NAME);
1819         PlayerSAO *playersao = getPlayerSAO(peer_id);
1820         // In some rare case, if the player is disconnected
1821         // while Lua call l_punch, for example, this can be NULL
1822         if (!playersao)
1823                 return;
1824
1825         SendHP(peer_id, playersao->getHP());
1826         m_script->player_event(playersao,"health_changed");
1827
1828         // Send to other clients
1829         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1830         ActiveObjectMessage aom(playersao->getId(), true, str);
1831         playersao->m_messages_out.push(aom);
1832 }
1833
1834 void Server::SendPlayerBreath(u16 peer_id)
1835 {
1836         DSTACK(__FUNCTION_NAME);
1837         PlayerSAO *playersao = getPlayerSAO(peer_id);
1838         assert(playersao);
1839
1840         m_script->player_event(playersao, "breath_changed");
1841         SendBreath(peer_id, playersao->getBreath());
1842 }
1843
1844 void Server::SendMovePlayer(u16 peer_id)
1845 {
1846         DSTACK(__FUNCTION_NAME);
1847         Player *player = m_env->getPlayer(peer_id);
1848         assert(player);
1849
1850         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1851         pkt << player->getPosition() << player->getPitch() << player->getYaw();
1852
1853         {
1854                 v3f pos = player->getPosition();
1855                 f32 pitch = player->getPitch();
1856                 f32 yaw = player->getYaw();
1857                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1858                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1859                                 << " pitch=" << pitch
1860                                 << " yaw=" << yaw
1861                                 << std::endl;
1862         }
1863
1864         Send(&pkt);
1865 }
1866
1867 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1868 {
1869         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1870                 peer_id);
1871
1872         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1873                         << animation_frames[3] << animation_speed;
1874
1875         Send(&pkt);
1876 }
1877
1878 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1879 {
1880         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1881         pkt << first << third;
1882         Send(&pkt);
1883 }
1884 void Server::SendPlayerPrivileges(u16 peer_id)
1885 {
1886         Player *player = m_env->getPlayer(peer_id);
1887         assert(player);
1888         if(player->peer_id == PEER_ID_INEXISTENT)
1889                 return;
1890
1891         std::set<std::string> privs;
1892         m_script->getAuth(player->getName(), NULL, &privs);
1893
1894         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1895         pkt << (u16) privs.size();
1896
1897         for(std::set<std::string>::const_iterator i = privs.begin();
1898                         i != privs.end(); i++) {
1899                 pkt << (*i);
1900         }
1901
1902         Send(&pkt);
1903 }
1904
1905 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1906 {
1907         Player *player = m_env->getPlayer(peer_id);
1908         assert(player);
1909         if(player->peer_id == PEER_ID_INEXISTENT)
1910                 return;
1911
1912         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1913         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1914         Send(&pkt);
1915 }
1916
1917 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
1918 {
1919         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1920         pkt.putRawString(datas.c_str(), datas.size());
1921         Send(&pkt);
1922         return pkt.getSize();
1923 }
1924
1925 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
1926 {
1927         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1928                         datas.size(), peer_id);
1929
1930         pkt.putRawString(datas.c_str(), datas.size());
1931
1932         m_clients.send(pkt.getPeerId(),
1933                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1934                         &pkt, reliable);
1935
1936 }
1937
1938 s32 Server::playSound(const SimpleSoundSpec &spec,
1939                 const ServerSoundParams &params)
1940 {
1941         // Find out initial position of sound
1942         bool pos_exists = false;
1943         v3f pos = params.getPos(m_env, &pos_exists);
1944         // If position is not found while it should be, cancel sound
1945         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1946                 return -1;
1947
1948         // Filter destination clients
1949         std::vector<u16> dst_clients;
1950         if(params.to_player != "")
1951         {
1952                 Player *player = m_env->getPlayer(params.to_player.c_str());
1953                 if(!player){
1954                         infostream<<"Server::playSound: Player \""<<params.to_player
1955                                         <<"\" not found"<<std::endl;
1956                         return -1;
1957                 }
1958                 if(player->peer_id == PEER_ID_INEXISTENT){
1959                         infostream<<"Server::playSound: Player \""<<params.to_player
1960                                         <<"\" not connected"<<std::endl;
1961                         return -1;
1962                 }
1963                 dst_clients.push_back(player->peer_id);
1964         }
1965         else {
1966                 std::vector<u16> clients = m_clients.getClientIDs();
1967
1968                 for(std::vector<u16>::iterator
1969                                 i = clients.begin(); i != clients.end(); ++i) {
1970                         Player *player = m_env->getPlayer(*i);
1971                         if(!player)
1972                                 continue;
1973
1974                         if(pos_exists) {
1975                                 if(player->getPosition().getDistanceFrom(pos) >
1976                                                 params.max_hear_distance)
1977                                         continue;
1978                         }
1979                         dst_clients.push_back(*i);
1980                 }
1981         }
1982
1983         if(dst_clients.empty())
1984                 return -1;
1985
1986         // Create the sound
1987         s32 id = m_next_sound_id++;
1988         // The sound will exist as a reference in m_playing_sounds
1989         m_playing_sounds[id] = ServerPlayingSound();
1990         ServerPlayingSound &psound = m_playing_sounds[id];
1991         psound.params = params;
1992
1993         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
1994         pkt << id << spec.name << (float) (spec.gain * params.gain)
1995                         << (u8) params.type << pos << params.object << params.loop;
1996
1997         for(std::vector<u16>::iterator i = dst_clients.begin();
1998                         i != dst_clients.end(); i++) {
1999                 psound.clients.insert(*i);
2000                 m_clients.send(*i, 0, &pkt, true);
2001         }
2002         return id;
2003 }
2004 void Server::stopSound(s32 handle)
2005 {
2006         // Get sound reference
2007         std::map<s32, ServerPlayingSound>::iterator i =
2008                         m_playing_sounds.find(handle);
2009         if(i == m_playing_sounds.end())
2010                 return;
2011         ServerPlayingSound &psound = i->second;
2012
2013         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2014         pkt << handle;
2015
2016         for(std::set<u16>::iterator i = psound.clients.begin();
2017                         i != psound.clients.end(); i++) {
2018                 // Send as reliable
2019                 m_clients.send(*i, 0, &pkt, true);
2020         }
2021         // Remove sound reference
2022         m_playing_sounds.erase(i);
2023 }
2024
2025 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2026         std::vector<u16> *far_players, float far_d_nodes)
2027 {
2028         float maxd = far_d_nodes*BS;
2029         v3f p_f = intToFloat(p, BS);
2030
2031         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2032         pkt << p;
2033
2034         std::vector<u16> clients = m_clients.getClientIDs();
2035         for(std::vector<u16>::iterator i = clients.begin();
2036                 i != clients.end(); ++i) {
2037                 if (far_players) {
2038                         // Get player
2039                         if(Player *player = m_env->getPlayer(*i)) {
2040                                 // If player is far away, only set modified blocks not sent
2041                                 v3f player_pos = player->getPosition();
2042                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2043                                         far_players->push_back(*i);
2044                                         continue;
2045                                 }
2046                         }
2047                 }
2048
2049                 // Send as reliable
2050                 m_clients.send(*i, 0, &pkt, true);
2051         }
2052 }
2053
2054 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2055                 std::vector<u16> *far_players, float far_d_nodes,
2056                 bool remove_metadata)
2057 {
2058         float maxd = far_d_nodes*BS;
2059         v3f p_f = intToFloat(p, BS);
2060
2061         std::vector<u16> clients = m_clients.getClientIDs();
2062         for(std::vector<u16>::iterator i = clients.begin();
2063                         i != clients.end(); ++i) {
2064
2065                 if(far_players) {
2066                         // Get player
2067                         if(Player *player = m_env->getPlayer(*i)) {
2068                                 // If player is far away, only set modified blocks not sent
2069                                 v3f player_pos = player->getPosition();
2070                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2071                                         far_players->push_back(*i);
2072                                         continue;
2073                                 }
2074                         }
2075                 }
2076
2077                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2078                 m_clients.Lock();
2079                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2080                 if (client != 0) {
2081                         pkt << p << n.param0 << n.param1 << n.param2
2082                                         << (u8) (remove_metadata ? 0 : 1);
2083
2084                         if (!remove_metadata) {
2085                                 if (client->net_proto_version <= 21) {
2086                                         // Old clients always clear metadata; fix it
2087                                         // by sending the full block again.
2088                                         client->SetBlockNotSent(p);
2089                                 }
2090                         }
2091                 }
2092                 m_clients.Unlock();
2093
2094                 // Send as reliable
2095                 if (pkt.getSize() > 0)
2096                         m_clients.send(*i, 0, &pkt, true);
2097         }
2098 }
2099
2100 void Server::setBlockNotSent(v3s16 p)
2101 {
2102         std::vector<u16> clients = m_clients.getClientIDs();
2103         m_clients.Lock();
2104         for(std::vector<u16>::iterator i = clients.begin();
2105                 i != clients.end(); ++i) {
2106                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2107                 client->SetBlockNotSent(p);
2108         }
2109         m_clients.Unlock();
2110 }
2111
2112 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2113 {
2114         DSTACK(__FUNCTION_NAME);
2115
2116         v3s16 p = block->getPos();
2117
2118         /*
2119                 Create a packet with the block in the right format
2120         */
2121
2122         std::ostringstream os(std::ios_base::binary);
2123         block->serialize(os, ver, false);
2124         block->serializeNetworkSpecific(os, net_proto_version);
2125         std::string s = os.str();
2126
2127         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2128
2129         pkt << p;
2130         pkt.putRawString(s.c_str(), s.size());
2131         Send(&pkt);
2132 }
2133
2134 void Server::SendBlocks(float dtime)
2135 {
2136         DSTACK(__FUNCTION_NAME);
2137
2138         JMutexAutoLock envlock(m_env_mutex);
2139         //TODO check if one big lock could be faster then multiple small ones
2140
2141         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2142
2143         std::vector<PrioritySortedBlockTransfer> queue;
2144
2145         s32 total_sending = 0;
2146
2147         {
2148                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2149
2150                 std::vector<u16> clients = m_clients.getClientIDs();
2151
2152                 m_clients.Lock();
2153                 for(std::vector<u16>::iterator i = clients.begin();
2154                         i != clients.end(); ++i) {
2155                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2156
2157                         if (client == NULL)
2158                                 continue;
2159
2160                         total_sending += client->SendingCount();
2161                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2162                 }
2163                 m_clients.Unlock();
2164         }
2165
2166         // Sort.
2167         // Lowest priority number comes first.
2168         // Lowest is most important.
2169         std::sort(queue.begin(), queue.end());
2170
2171         m_clients.Lock();
2172         for(u32 i=0; i<queue.size(); i++)
2173         {
2174                 //TODO: Calculate limit dynamically
2175                 if(total_sending >= g_settings->getS32
2176                                 ("max_simultaneous_block_sends_server_total"))
2177                         break;
2178
2179                 PrioritySortedBlockTransfer q = queue[i];
2180
2181                 MapBlock *block = NULL;
2182                 try
2183                 {
2184                         block = m_env->getMap().getBlockNoCreate(q.pos);
2185                 }
2186                 catch(InvalidPositionException &e)
2187                 {
2188                         continue;
2189                 }
2190
2191                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2192
2193                 if(!client)
2194                         continue;
2195
2196                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2197
2198                 client->SentBlock(q.pos);
2199                 total_sending++;
2200         }
2201         m_clients.Unlock();
2202 }
2203
2204 void Server::fillMediaCache()
2205 {
2206         DSTACK(__FUNCTION_NAME);
2207
2208         infostream<<"Server: Calculating media file checksums"<<std::endl;
2209
2210         // Collect all media file paths
2211         std::vector<std::string> paths;
2212         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2213                         i != m_mods.end(); i++) {
2214                 const ModSpec &mod = *i;
2215                 paths.push_back(mod.path + DIR_DELIM + "textures");
2216                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2217                 paths.push_back(mod.path + DIR_DELIM + "media");
2218                 paths.push_back(mod.path + DIR_DELIM + "models");
2219         }
2220         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2221
2222         // Collect media file information from paths into cache
2223         for(std::vector<std::string>::iterator i = paths.begin();
2224                         i != paths.end(); i++) {
2225                 std::string mediapath = *i;
2226                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2227                 for (u32 j = 0; j < dirlist.size(); j++) {
2228                         if (dirlist[j].dir) // Ignode dirs
2229                                 continue;
2230                         std::string filename = dirlist[j].name;
2231                         // If name contains illegal characters, ignore the file
2232                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2233                                 infostream<<"Server: ignoring illegal file name: \""
2234                                                 << filename << "\"" << std::endl;
2235                                 continue;
2236                         }
2237                         // If name is not in a supported format, ignore it
2238                         const char *supported_ext[] = {
2239                                 ".png", ".jpg", ".bmp", ".tga",
2240                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2241                                 ".ogg",
2242                                 ".x", ".b3d", ".md2", ".obj",
2243                                 NULL
2244                         };
2245                         if (removeStringEnd(filename, supported_ext) == ""){
2246                                 infostream << "Server: ignoring unsupported file extension: \""
2247                                                 << filename << "\"" << std::endl;
2248                                 continue;
2249                         }
2250                         // Ok, attempt to load the file and add to cache
2251                         std::string filepath = mediapath + DIR_DELIM + filename;
2252                         // Read data
2253                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2254                         if (!fis.good()) {
2255                                 errorstream << "Server::fillMediaCache(): Could not open \""
2256                                                 << filename << "\" for reading" << std::endl;
2257                                 continue;
2258                         }
2259                         std::ostringstream tmp_os(std::ios_base::binary);
2260                         bool bad = false;
2261                         for(;;) {
2262                                 char buf[1024];
2263                                 fis.read(buf, 1024);
2264                                 std::streamsize len = fis.gcount();
2265                                 tmp_os.write(buf, len);
2266                                 if (fis.eof())
2267                                         break;
2268                                 if (!fis.good()) {
2269                                         bad = true;
2270                                         break;
2271                                 }
2272                         }
2273                         if(bad) {
2274                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2275                                                 << filename << "\"" << std::endl;
2276                                 continue;
2277                         }
2278                         if(tmp_os.str().length() == 0) {
2279                                 errorstream << "Server::fillMediaCache(): Empty file \""
2280                                                 << filepath << "\"" << std::endl;
2281                                 continue;
2282                         }
2283
2284                         SHA1 sha1;
2285                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2286
2287                         unsigned char *digest = sha1.getDigest();
2288                         std::string sha1_base64 = base64_encode(digest, 20);
2289                         std::string sha1_hex = hex_encode((char*)digest, 20);
2290                         free(digest);
2291
2292                         // Put in list
2293                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2294                         verbosestream << "Server: " << sha1_hex << " is " << filename
2295                                         << std::endl;
2296                 }
2297         }
2298 }
2299
2300 struct SendableMediaAnnouncement
2301 {
2302         std::string name;
2303         std::string sha1_digest;
2304
2305         SendableMediaAnnouncement(const std::string &name_="",
2306                                   const std::string &sha1_digest_=""):
2307                 name(name_),
2308                 sha1_digest(sha1_digest_)
2309         {}
2310 };
2311
2312 void Server::sendMediaAnnouncement(u16 peer_id)
2313 {
2314         DSTACK(__FUNCTION_NAME);
2315
2316         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
2317                         <<std::endl;
2318
2319         std::vector<SendableMediaAnnouncement> file_announcements;
2320
2321         for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
2322                         i != m_media.end(); i++){
2323                 // Put in list
2324                 file_announcements.push_back(
2325                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
2326         }
2327
2328         // Make packet
2329         std::ostringstream os(std::ios_base::binary);
2330
2331         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2332         pkt << (u16) file_announcements.size();
2333
2334         for (std::vector<SendableMediaAnnouncement>::iterator
2335                         j = file_announcements.begin();
2336                         j != file_announcements.end(); ++j) {
2337                 pkt << j->name << j->sha1_digest;
2338         }
2339
2340         pkt << g_settings->get("remote_media");
2341         Send(&pkt);
2342 }
2343
2344 struct SendableMedia
2345 {
2346         std::string name;
2347         std::string path;
2348         std::string data;
2349
2350         SendableMedia(const std::string &name_="", const std::string &path_="",
2351                       const std::string &data_=""):
2352                 name(name_),
2353                 path(path_),
2354                 data(data_)
2355         {}
2356 };
2357
2358 void Server::sendRequestedMedia(u16 peer_id,
2359                 const std::vector<std::string> &tosend)
2360 {
2361         DSTACK(__FUNCTION_NAME);
2362
2363         verbosestream<<"Server::sendRequestedMedia(): "
2364                         <<"Sending files to client"<<std::endl;
2365
2366         /* Read files */
2367
2368         // Put 5kB in one bunch (this is not accurate)
2369         u32 bytes_per_bunch = 5000;
2370
2371         std::vector< std::vector<SendableMedia> > file_bunches;
2372         file_bunches.push_back(std::vector<SendableMedia>());
2373
2374         u32 file_size_bunch_total = 0;
2375
2376         for(std::vector<std::string>::const_iterator i = tosend.begin();
2377                         i != tosend.end(); ++i) {
2378                 const std::string &name = *i;
2379
2380                 if(m_media.find(name) == m_media.end()) {
2381                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2382                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2383                         continue;
2384                 }
2385
2386                 //TODO get path + name
2387                 std::string tpath = m_media[name].path;
2388
2389                 // Read data
2390                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2391                 if(fis.good() == false){
2392                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2393                                         <<tpath<<"\" for reading"<<std::endl;
2394                         continue;
2395                 }
2396                 std::ostringstream tmp_os(std::ios_base::binary);
2397                 bool bad = false;
2398                 for(;;) {
2399                         char buf[1024];
2400                         fis.read(buf, 1024);
2401                         std::streamsize len = fis.gcount();
2402                         tmp_os.write(buf, len);
2403                         file_size_bunch_total += len;
2404                         if(fis.eof())
2405                                 break;
2406                         if(!fis.good()) {
2407                                 bad = true;
2408                                 break;
2409                         }
2410                 }
2411                 if(bad) {
2412                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2413                                         <<name<<"\""<<std::endl;
2414                         continue;
2415                 }
2416                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2417                                 <<tname<<"\""<<std::endl;*/
2418                 // Put in list
2419                 file_bunches[file_bunches.size()-1].push_back(
2420                                 SendableMedia(name, tpath, tmp_os.str()));
2421
2422                 // Start next bunch if got enough data
2423                 if(file_size_bunch_total >= bytes_per_bunch) {
2424                         file_bunches.push_back(std::vector<SendableMedia>());
2425                         file_size_bunch_total = 0;
2426                 }
2427
2428         }
2429
2430         /* Create and send packets */
2431
2432         u16 num_bunches = file_bunches.size();
2433         for(u16 i = 0; i < num_bunches; i++) {
2434                 /*
2435                         u16 command
2436                         u16 total number of texture bunches
2437                         u16 index of this bunch
2438                         u32 number of files in this bunch
2439                         for each file {
2440                                 u16 length of name
2441                                 string name
2442                                 u32 length of data
2443                                 data
2444                         }
2445                 */
2446
2447                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2448                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2449
2450                 for(std::vector<SendableMedia>::iterator
2451                                 j = file_bunches[i].begin();
2452                                 j != file_bunches[i].end(); ++j) {
2453                         pkt << j->name;
2454                         pkt.putLongString(j->data);
2455                 }
2456
2457                 verbosestream << "Server::sendRequestedMedia(): bunch "
2458                                 << i << "/" << num_bunches
2459                                 << " files=" << file_bunches[i].size()
2460                                 << " size="  << pkt.getSize() << std::endl;
2461                 Send(&pkt);
2462         }
2463 }
2464
2465 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2466 {
2467         if(m_detached_inventories.count(name) == 0) {
2468                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2469                 return;
2470         }
2471         Inventory *inv = m_detached_inventories[name];
2472         std::ostringstream os(std::ios_base::binary);
2473
2474         os << serializeString(name);
2475         inv->serialize(os);
2476
2477         // Make data buffer
2478         std::string s = os.str();
2479
2480         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2481         pkt.putRawString(s.c_str(), s.size());
2482
2483         if (peer_id != PEER_ID_INEXISTENT) {
2484                 Send(&pkt);
2485         }
2486         else {
2487                 m_clients.sendToAll(0, &pkt, true);
2488         }
2489 }
2490
2491 void Server::sendDetachedInventories(u16 peer_id)
2492 {
2493         DSTACK(__FUNCTION_NAME);
2494
2495         for(std::map<std::string, Inventory*>::iterator
2496                         i = m_detached_inventories.begin();
2497                         i != m_detached_inventories.end(); i++) {
2498                 const std::string &name = i->first;
2499                 //Inventory *inv = i->second;
2500                 sendDetachedInventory(name, peer_id);
2501         }
2502 }
2503
2504 /*
2505         Something random
2506 */
2507
2508 void Server::DiePlayer(u16 peer_id)
2509 {
2510         DSTACK(__FUNCTION_NAME);
2511
2512         PlayerSAO *playersao = getPlayerSAO(peer_id);
2513         assert(playersao);
2514
2515         infostream << "Server::DiePlayer(): Player "
2516                         << playersao->getPlayer()->getName()
2517                         << " dies" << std::endl;
2518
2519         playersao->setHP(0);
2520
2521         // Trigger scripted stuff
2522         m_script->on_dieplayer(playersao);
2523
2524         SendPlayerHP(peer_id);
2525         SendDeathscreen(peer_id, false, v3f(0,0,0));
2526 }
2527
2528 void Server::RespawnPlayer(u16 peer_id)
2529 {
2530         DSTACK(__FUNCTION_NAME);
2531
2532         PlayerSAO *playersao = getPlayerSAO(peer_id);
2533         assert(playersao);
2534
2535         infostream << "Server::RespawnPlayer(): Player "
2536                         << playersao->getPlayer()->getName()
2537                         << " respawns" << std::endl;
2538
2539         playersao->setHP(PLAYER_MAX_HP);
2540         playersao->setBreath(PLAYER_MAX_BREATH);
2541
2542         SendPlayerHP(peer_id);
2543         SendPlayerBreath(peer_id);
2544
2545         bool repositioned = m_script->on_respawnplayer(playersao);
2546         if(!repositioned){
2547                 v3f pos = findSpawnPos();
2548                 // setPos will send the new position to client
2549                 playersao->setPos(pos);
2550         }
2551 }
2552 void Server::DenySudoAccess(u16 peer_id)
2553 {
2554         DSTACK(__FUNCTION_NAME);
2555
2556         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2557         Send(&pkt);
2558 }
2559
2560 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2561 {
2562         DSTACK(__FUNCTION_NAME);
2563
2564         SendAccessDenied(peer_id, reason, custom_reason);
2565         m_clients.event(peer_id, CSE_SetDenied);
2566         m_con.DisconnectPeer(peer_id);
2567 }
2568
2569 // 13/03/15: remove this function when protocol version 25 will become
2570 // the minimum version for MT users, maybe in 1 year
2571 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2572 {
2573         DSTACK(__FUNCTION_NAME);
2574
2575         SendAccessDenied_Legacy(peer_id, reason);
2576         m_clients.event(peer_id, CSE_SetDenied);
2577         m_con.DisconnectPeer(peer_id);
2578 }
2579
2580 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2581 {
2582         DSTACK(__FUNCTION_NAME);
2583
2584         if (!forSudoMode) {
2585                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2586
2587                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2588
2589                 // Right now, the auth mechs don't change between login and sudo mode.
2590                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2591                 client->allowed_sudo_mechs = sudo_auth_mechs;
2592
2593                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2594                                 << g_settings->getFloat("dedicated_server_step")
2595                                 << sudo_auth_mechs;
2596
2597                 Send(&resp_pkt);
2598                 m_clients.event(peer_id, CSE_AuthAccept);
2599         } else {
2600                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2601
2602                 // We only support SRP right now
2603                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2604
2605                 resp_pkt << sudo_auth_mechs;
2606                 Send(&resp_pkt);
2607                 m_clients.event(peer_id, CSE_SudoSuccess);
2608         }
2609 }
2610
2611 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2612 {
2613         DSTACK(__FUNCTION_NAME);
2614         std::wstring message;
2615         {
2616                 /*
2617                         Clear references to playing sounds
2618                 */
2619                 for(std::map<s32, ServerPlayingSound>::iterator
2620                                 i = m_playing_sounds.begin();
2621                                 i != m_playing_sounds.end();)
2622                 {
2623                         ServerPlayingSound &psound = i->second;
2624                         psound.clients.erase(peer_id);
2625                         if(psound.clients.empty())
2626                                 m_playing_sounds.erase(i++);
2627                         else
2628                                 i++;
2629                 }
2630
2631                 Player *player = m_env->getPlayer(peer_id);
2632
2633                 // Collect information about leaving in chat
2634                 {
2635                         if(player != NULL && reason != CDR_DENY)
2636                         {
2637                                 std::wstring name = narrow_to_wide(player->getName());
2638                                 message += L"*** ";
2639                                 message += name;
2640                                 message += L" left the game.";
2641                                 if(reason == CDR_TIMEOUT)
2642                                         message += L" (timed out)";
2643                         }
2644                 }
2645
2646                 /* Run scripts and remove from environment */
2647                 {
2648                         if(player != NULL)
2649                         {
2650                                 PlayerSAO *playersao = player->getPlayerSAO();
2651                                 assert(playersao);
2652
2653                                 m_script->on_leaveplayer(playersao);
2654
2655                                 playersao->disconnected();
2656                         }
2657                 }
2658
2659                 /*
2660                         Print out action
2661                 */
2662                 {
2663                         if(player != NULL && reason != CDR_DENY) {
2664                                 std::ostringstream os(std::ios_base::binary);
2665                                 std::vector<u16> clients = m_clients.getClientIDs();
2666
2667                                 for(std::vector<u16>::iterator i = clients.begin();
2668                                         i != clients.end(); ++i) {
2669                                         // Get player
2670                                         Player *player = m_env->getPlayer(*i);
2671                                         if(!player)
2672                                                 continue;
2673
2674                                         // Get name of player
2675                                         os << player->getName() << " ";
2676                                 }
2677
2678                                 actionstream << player->getName() << " "
2679                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2680                                                 << " List of players: " << os.str() << std::endl;
2681                         }
2682                 }
2683                 {
2684                         JMutexAutoLock env_lock(m_env_mutex);
2685                         m_clients.DeleteClient(peer_id);
2686                 }
2687         }
2688
2689         // Send leave chat message to all remaining clients
2690         if(message.length() != 0)
2691                 SendChatMessage(PEER_ID_INEXISTENT,message);
2692 }
2693
2694 void Server::UpdateCrafting(Player* player)
2695 {
2696         DSTACK(__FUNCTION_NAME);
2697
2698         // Get a preview for crafting
2699         ItemStack preview;
2700         InventoryLocation loc;
2701         loc.setPlayer(player->getName());
2702         std::vector<ItemStack> output_replacements;
2703         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2704         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
2705
2706         // Put the new preview in
2707         InventoryList *plist = player->inventory.getList("craftpreview");
2708         sanity_check(plist);
2709         sanity_check(plist->getSize() >= 1);
2710         plist->changeItem(0, preview);
2711 }
2712
2713 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2714 {
2715         RemoteClient *client = getClientNoEx(peer_id,state_min);
2716         if(!client)
2717                 throw ClientNotFoundException("Client not found");
2718
2719         return client;
2720 }
2721 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2722 {
2723         return m_clients.getClientNoEx(peer_id, state_min);
2724 }
2725
2726 std::string Server::getPlayerName(u16 peer_id)
2727 {
2728         Player *player = m_env->getPlayer(peer_id);
2729         if(player == NULL)
2730                 return "[id="+itos(peer_id)+"]";
2731         return player->getName();
2732 }
2733
2734 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2735 {
2736         Player *player = m_env->getPlayer(peer_id);
2737         if(player == NULL)
2738                 return NULL;
2739         return player->getPlayerSAO();
2740 }
2741
2742 std::wstring Server::getStatusString()
2743 {
2744         std::wostringstream os(std::ios_base::binary);
2745         os<<L"# Server: ";
2746         // Version
2747         os<<L"version="<<narrow_to_wide(g_version_string);
2748         // Uptime
2749         os<<L", uptime="<<m_uptime.get();
2750         // Max lag estimate
2751         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2752         // Information about clients
2753         bool first = true;
2754         os<<L", clients={";
2755         std::vector<u16> clients = m_clients.getClientIDs();
2756         for(std::vector<u16>::iterator i = clients.begin();
2757                 i != clients.end(); ++i) {
2758                 // Get player
2759                 Player *player = m_env->getPlayer(*i);
2760                 // Get name of player
2761                 std::wstring name = L"unknown";
2762                 if(player != NULL)
2763                         name = narrow_to_wide(player->getName());
2764                 // Add name to information string
2765                 if(!first)
2766                         os << L", ";
2767                 else
2768                         first = false;
2769                 os << name;
2770         }
2771         os << L"}";
2772         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2773                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2774         if(g_settings->get("motd") != "")
2775                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2776         return os.str();
2777 }
2778
2779 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2780 {
2781         std::set<std::string> privs;
2782         m_script->getAuth(name, NULL, &privs);
2783         return privs;
2784 }
2785
2786 bool Server::checkPriv(const std::string &name, const std::string &priv)
2787 {
2788         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2789         return (privs.count(priv) != 0);
2790 }
2791
2792 void Server::reportPrivsModified(const std::string &name)
2793 {
2794         if(name == "") {
2795                 std::vector<u16> clients = m_clients.getClientIDs();
2796                 for(std::vector<u16>::iterator i = clients.begin();
2797                                 i != clients.end(); ++i) {
2798                         Player *player = m_env->getPlayer(*i);
2799                         reportPrivsModified(player->getName());
2800                 }
2801         } else {
2802                 Player *player = m_env->getPlayer(name.c_str());
2803                 if(!player)
2804                         return;
2805                 SendPlayerPrivileges(player->peer_id);
2806                 PlayerSAO *sao = player->getPlayerSAO();
2807                 if(!sao)
2808                         return;
2809                 sao->updatePrivileges(
2810                                 getPlayerEffectivePrivs(name),
2811                                 isSingleplayer());
2812         }
2813 }
2814
2815 void Server::reportInventoryFormspecModified(const std::string &name)
2816 {
2817         Player *player = m_env->getPlayer(name.c_str());
2818         if(!player)
2819                 return;
2820         SendPlayerInventoryFormspec(player->peer_id);
2821 }
2822
2823 void Server::setIpBanned(const std::string &ip, const std::string &name)
2824 {
2825         m_banmanager->add(ip, name);
2826 }
2827
2828 void Server::unsetIpBanned(const std::string &ip_or_name)
2829 {
2830         m_banmanager->remove(ip_or_name);
2831 }
2832
2833 std::string Server::getBanDescription(const std::string &ip_or_name)
2834 {
2835         return m_banmanager->getBanDescription(ip_or_name);
2836 }
2837
2838 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2839 {
2840         Player *player = m_env->getPlayer(name);
2841         if(!player)
2842                 return;
2843
2844         if (player->peer_id == PEER_ID_INEXISTENT)
2845                 return;
2846
2847         SendChatMessage(player->peer_id, msg);
2848 }
2849
2850 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
2851 {
2852         Player *player = m_env->getPlayer(playername);
2853
2854         if(!player)
2855         {
2856                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
2857                 return false;
2858         }
2859
2860         SendShowFormspecMessage(player->peer_id, formspec, formname);
2861         return true;
2862 }
2863
2864 u32 Server::hudAdd(Player *player, HudElement *form) {
2865         if (!player)
2866                 return -1;
2867
2868         u32 id = player->addHud(form);
2869
2870         SendHUDAdd(player->peer_id, id, form);
2871
2872         return id;
2873 }
2874
2875 bool Server::hudRemove(Player *player, u32 id) {
2876         if (!player)
2877                 return false;
2878
2879         HudElement* todel = player->removeHud(id);
2880
2881         if (!todel)
2882                 return false;
2883
2884         delete todel;
2885
2886         SendHUDRemove(player->peer_id, id);
2887         return true;
2888 }
2889
2890 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
2891         if (!player)
2892                 return false;
2893
2894         SendHUDChange(player->peer_id, id, stat, data);
2895         return true;
2896 }
2897
2898 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
2899         if (!player)
2900                 return false;
2901
2902         SendHUDSetFlags(player->peer_id, flags, mask);
2903         player->hud_flags = flags;
2904
2905         PlayerSAO* playersao = player->getPlayerSAO();
2906
2907         if (playersao == NULL)
2908                 return false;
2909
2910         m_script->player_event(playersao, "hud_changed");
2911         return true;
2912 }
2913
2914 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
2915         if (!player)
2916                 return false;
2917         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
2918                 return false;
2919
2920         player->setHotbarItemcount(hotbar_itemcount);
2921         std::ostringstream os(std::ios::binary);
2922         writeS32(os, hotbar_itemcount);
2923         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
2924         return true;
2925 }
2926
2927 s32 Server::hudGetHotbarItemcount(Player *player) {
2928         if (!player)
2929                 return 0;
2930         return player->getHotbarItemcount();
2931 }
2932
2933 void Server::hudSetHotbarImage(Player *player, std::string name) {
2934         if (!player)
2935                 return;
2936
2937         player->setHotbarImage(name);
2938         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
2939 }
2940
2941 std::string Server::hudGetHotbarImage(Player *player) {
2942         if (!player)
2943                 return "";
2944         return player->getHotbarImage();
2945 }
2946
2947 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
2948         if (!player)
2949                 return;
2950
2951         player->setHotbarSelectedImage(name);
2952         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
2953 }
2954
2955 std::string Server::hudGetHotbarSelectedImage(Player *player) {
2956         if (!player)
2957                 return "";
2958
2959         return player->getHotbarSelectedImage();
2960 }
2961
2962 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
2963 {
2964         if (!player)
2965                 return false;
2966
2967         player->setLocalAnimations(animation_frames, frame_speed);
2968         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
2969         return true;
2970 }
2971
2972 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
2973 {
2974         if (!player)
2975                 return false;
2976
2977         player->eye_offset_first = first;
2978         player->eye_offset_third = third;
2979         SendEyeOffset(player->peer_id, first, third);
2980         return true;
2981 }
2982
2983 bool Server::setSky(Player *player, const video::SColor &bgcolor,
2984                 const std::string &type, const std::vector<std::string> &params)
2985 {
2986         if (!player)
2987                 return false;
2988
2989         player->setSky(bgcolor, type, params);
2990         SendSetSky(player->peer_id, bgcolor, type, params);
2991         return true;
2992 }
2993
2994 bool Server::overrideDayNightRatio(Player *player, bool do_override,
2995                 float ratio)
2996 {
2997         if (!player)
2998                 return false;
2999
3000         player->overrideDayNightRatio(do_override, ratio);
3001         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3002         return true;
3003 }
3004
3005 void Server::notifyPlayers(const std::wstring &msg)
3006 {
3007         SendChatMessage(PEER_ID_INEXISTENT,msg);
3008 }
3009
3010 void Server::spawnParticle(const char *playername, v3f pos,
3011                 v3f velocity, v3f acceleration,
3012                 float expirationtime, float size, bool
3013                 collisiondetection, bool vertical, std::string texture)
3014 {
3015         Player *player = m_env->getPlayer(playername);
3016         if(!player)
3017                 return;
3018         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
3019                         expirationtime, size, collisiondetection, vertical, texture);
3020 }
3021
3022 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
3023                 float expirationtime, float size,
3024                 bool collisiondetection, bool vertical, std::string texture)
3025 {
3026         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
3027                         expirationtime, size, collisiondetection, vertical, texture);
3028 }
3029
3030 u32 Server::addParticleSpawner(const char *playername,
3031                 u16 amount, float spawntime,
3032                 v3f minpos, v3f maxpos,
3033                 v3f minvel, v3f maxvel,
3034                 v3f minacc, v3f maxacc,
3035                 float minexptime, float maxexptime,
3036                 float minsize, float maxsize,
3037                 bool collisiondetection, bool vertical, std::string texture)
3038 {
3039         Player *player = m_env->getPlayer(playername);
3040         if(!player)
3041                 return -1;
3042
3043         u32 id = 0;
3044         for(;;) // look for unused particlespawner id
3045         {
3046                 id++;
3047                 if (std::find(m_particlespawner_ids.begin(),
3048                                 m_particlespawner_ids.end(), id)
3049                                 == m_particlespawner_ids.end())
3050                 {
3051                         m_particlespawner_ids.push_back(id);
3052                         break;
3053                 }
3054         }
3055
3056         SendAddParticleSpawner(player->peer_id, amount, spawntime,
3057                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3058                 minexptime, maxexptime, minsize, maxsize,
3059                 collisiondetection, vertical, texture, id);
3060
3061         return id;
3062 }
3063
3064 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
3065                 v3f minpos, v3f maxpos,
3066                 v3f minvel, v3f maxvel,
3067                 v3f minacc, v3f maxacc,
3068                 float minexptime, float maxexptime,
3069                 float minsize, float maxsize,
3070                 bool collisiondetection, bool vertical, std::string texture)
3071 {
3072         u32 id = 0;
3073         for(;;) // look for unused particlespawner id
3074         {
3075                 id++;
3076                 if (std::find(m_particlespawner_ids.begin(),
3077                                 m_particlespawner_ids.end(), id)
3078                                 == m_particlespawner_ids.end())
3079                 {
3080                         m_particlespawner_ids.push_back(id);
3081                         break;
3082                 }
3083         }
3084
3085         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
3086                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3087                 minexptime, maxexptime, minsize, maxsize,
3088                 collisiondetection, vertical, texture, id);
3089
3090         return id;
3091 }
3092
3093 void Server::deleteParticleSpawner(const char *playername, u32 id)
3094 {
3095         Player *player = m_env->getPlayer(playername);
3096         if(!player)
3097                 return;
3098
3099         m_particlespawner_ids.erase(
3100                         std::remove(m_particlespawner_ids.begin(),
3101                         m_particlespawner_ids.end(), id),
3102                         m_particlespawner_ids.end());
3103         SendDeleteParticleSpawner(player->peer_id, id);
3104 }
3105
3106 void Server::deleteParticleSpawnerAll(u32 id)
3107 {
3108         m_particlespawner_ids.erase(
3109                         std::remove(m_particlespawner_ids.begin(),
3110                         m_particlespawner_ids.end(), id),
3111                         m_particlespawner_ids.end());
3112         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3113 }
3114
3115 Inventory* Server::createDetachedInventory(const std::string &name)
3116 {
3117         if(m_detached_inventories.count(name) > 0){
3118                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3119                 delete m_detached_inventories[name];
3120         } else {
3121                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3122         }
3123         Inventory *inv = new Inventory(m_itemdef);
3124         sanity_check(inv);
3125         m_detached_inventories[name] = inv;
3126         //TODO find a better way to do this
3127         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3128         return inv;
3129 }
3130
3131 class BoolScopeSet
3132 {
3133 public:
3134         BoolScopeSet(bool *dst, bool val):
3135                 m_dst(dst)
3136         {
3137                 m_orig_state = *m_dst;
3138                 *m_dst = val;
3139         }
3140         ~BoolScopeSet()
3141         {
3142                 *m_dst = m_orig_state;
3143         }
3144 private:
3145         bool *m_dst;
3146         bool m_orig_state;
3147 };
3148
3149 // actions: time-reversed list
3150 // Return value: success/failure
3151 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3152                 std::list<std::string> *log)
3153 {
3154         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3155         ServerMap *map = (ServerMap*)(&m_env->getMap());
3156
3157         // Fail if no actions to handle
3158         if(actions.empty()){
3159                 log->push_back("Nothing to do.");
3160                 return false;
3161         }
3162
3163         int num_tried = 0;
3164         int num_failed = 0;
3165
3166         for(std::list<RollbackAction>::const_iterator
3167                         i = actions.begin();
3168                         i != actions.end(); i++)
3169         {
3170                 const RollbackAction &action = *i;
3171                 num_tried++;
3172                 bool success = action.applyRevert(map, this, this);
3173                 if(!success){
3174                         num_failed++;
3175                         std::ostringstream os;
3176                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3177                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3178                         if(log)
3179                                 log->push_back(os.str());
3180                 }else{
3181                         std::ostringstream os;
3182                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3183                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3184                         if(log)
3185                                 log->push_back(os.str());
3186                 }
3187         }
3188
3189         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3190                         <<" failed"<<std::endl;
3191
3192         // Call it done if less than half failed
3193         return num_failed <= num_tried/2;
3194 }
3195
3196 // IGameDef interface
3197 // Under envlock
3198 IItemDefManager* Server::getItemDefManager()
3199 {
3200         return m_itemdef;
3201 }
3202 INodeDefManager* Server::getNodeDefManager()
3203 {
3204         return m_nodedef;
3205 }
3206 ICraftDefManager* Server::getCraftDefManager()
3207 {
3208         return m_craftdef;
3209 }
3210 ITextureSource* Server::getTextureSource()
3211 {
3212         return NULL;
3213 }
3214 IShaderSource* Server::getShaderSource()
3215 {
3216         return NULL;
3217 }
3218 scene::ISceneManager* Server::getSceneManager()
3219 {
3220         return NULL;
3221 }
3222
3223 u16 Server::allocateUnknownNodeId(const std::string &name)
3224 {
3225         return m_nodedef->allocateDummy(name);
3226 }
3227 ISoundManager* Server::getSoundManager()
3228 {
3229         return &dummySoundManager;
3230 }
3231 MtEventManager* Server::getEventManager()
3232 {
3233         return m_event;
3234 }
3235
3236 IWritableItemDefManager* Server::getWritableItemDefManager()
3237 {
3238         return m_itemdef;
3239 }
3240 IWritableNodeDefManager* Server::getWritableNodeDefManager()
3241 {
3242         return m_nodedef;
3243 }
3244 IWritableCraftDefManager* Server::getWritableCraftDefManager()
3245 {
3246         return m_craftdef;
3247 }
3248
3249 const ModSpec* Server::getModSpec(const std::string &modname) const
3250 {
3251         for(std::vector<ModSpec>::const_iterator i = m_mods.begin();
3252                         i != m_mods.end(); i++){
3253                 const ModSpec &mod = *i;
3254                 if(mod.name == modname)
3255                         return &mod;
3256         }
3257         return NULL;
3258 }
3259 void Server::getModNames(std::vector<std::string> &modlist)
3260 {
3261         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++) {
3262                 modlist.push_back(i->name);
3263         }
3264 }
3265 std::string Server::getBuiltinLuaPath()
3266 {
3267         return porting::path_share + DIR_DELIM + "builtin";
3268 }
3269
3270 v3f Server::findSpawnPos()
3271 {
3272         ServerMap &map = m_env->getServerMap();
3273         v3f nodeposf;
3274         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3275                 return nodeposf * BS;
3276         }
3277
3278         // Default position is static_spawnpoint
3279         // We will return it if we don't found a good place
3280         v3s16 nodepos(nodeposf.X, nodeposf.Y, nodeposf.Z);
3281
3282         s16 water_level = map.getWaterLevel();
3283
3284         bool is_good = false;
3285
3286         // Try to find a good place a few times
3287         for(s32 i = 0; i < 1000 && !is_good; i++) {
3288                 s32 range = 1 + i;
3289                 // We're going to try to throw the player to this position
3290                 v2s16 nodepos2d = v2s16(
3291                                 -range + (myrand() % (range * 2)),
3292                                 -range + (myrand() % (range * 2)));
3293
3294                 // Get ground height at point
3295                 s16 groundheight = map.findGroundLevel(nodepos2d);
3296                 if (groundheight <= water_level) // Don't go underwater
3297                         continue;
3298                 if (groundheight > water_level + 6) // Don't go to high places
3299                         continue;
3300
3301                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
3302
3303                 s32 air_count = 0;
3304                 for (s32 i = 0; i < 10; i++) {
3305                         v3s16 blockpos = getNodeBlockPos(nodepos);
3306                         map.emergeBlock(blockpos, true);
3307                         content_t c = map.getNodeNoEx(nodepos).getContent();
3308                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3309                                 air_count++;
3310                                 if (air_count >= 2){
3311                                         is_good = true;
3312                                         break;
3313                                 }
3314                         }
3315                         nodepos.Y++;
3316                 }
3317         }
3318
3319         return intToFloat(nodepos, BS);
3320 }
3321
3322 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
3323 {
3324         bool newplayer = false;
3325
3326         /*
3327                 Try to get an existing player
3328         */
3329         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3330
3331         // If player is already connected, cancel
3332         if(player != NULL && player->peer_id != 0)
3333         {
3334                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3335                 return NULL;
3336         }
3337
3338         /*
3339                 If player with the wanted peer_id already exists, cancel.
3340         */
3341         if(m_env->getPlayer(peer_id) != NULL)
3342         {
3343                 infostream<<"emergePlayer(): Player with wrong name but same"
3344                                 " peer_id already exists"<<std::endl;
3345                 return NULL;
3346         }
3347
3348         // Load player if it isn't already loaded
3349         if (!player) {
3350                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3351         }
3352
3353         // Create player if it doesn't exist
3354         if (!player) {
3355                 newplayer = true;
3356                 player = new RemotePlayer(this, name);
3357                 // Set player position
3358                 infostream<<"Server: Finding spawn place for player \""
3359                                 <<name<<"\""<<std::endl;
3360                 v3f pos = findSpawnPos();
3361                 player->setPosition(pos);
3362
3363                 // Make sure the player is saved
3364                 player->setModified(true);
3365
3366                 // Add player to environment
3367                 m_env->addPlayer(player);
3368         }
3369
3370         // Create a new player active object
3371         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3372                         getPlayerEffectivePrivs(player->getName()),
3373                         isSingleplayer());
3374
3375         /* Clean up old HUD elements from previous sessions */
3376         player->clearHud();
3377
3378         /* Add object to environment */
3379         m_env->addActiveObject(playersao);
3380
3381         /* Run scripts */
3382         if (newplayer) {
3383                 m_script->on_newplayer(playersao);
3384         }
3385
3386         return playersao;
3387 }
3388
3389 void dedicated_server_loop(Server &server, bool &kill)
3390 {
3391         DSTACK(__FUNCTION_NAME);
3392
3393         verbosestream<<"dedicated_server_loop()"<<std::endl;
3394
3395         IntervalLimiter m_profiler_interval;
3396
3397         for(;;)
3398         {
3399                 float steplen = g_settings->getFloat("dedicated_server_step");
3400                 // This is kind of a hack but can be done like this
3401                 // because server.step() is very light
3402                 {
3403                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3404                         sleep_ms((int)(steplen*1000.0));
3405                 }
3406                 server.step(steplen);
3407
3408                 if(server.getShutdownRequested() || kill)
3409                 {
3410                         infostream<<"Dedicated server quitting"<<std::endl;
3411 #if USE_CURL
3412                         if(g_settings->getBool("server_announce"))
3413                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3414 #endif
3415                         break;
3416                 }
3417
3418                 /*
3419                         Profiler
3420                 */
3421                 float profiler_print_interval =
3422                                 g_settings->getFloat("profiler_print_interval");
3423                 if(profiler_print_interval != 0)
3424                 {
3425                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3426                         {
3427                                 infostream<<"Profiler:"<<std::endl;
3428                                 g_profiler->print(infostream);
3429                                 g_profiler->clear();
3430                         }
3431                 }
3432         }
3433 }