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