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