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