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