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