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