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