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