]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
6a1e8085b530b5c8f343239d511a30540085d5fe
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "jthread/jmutexautolock.h"
30 #include "main.h"
31 #include "constants.h"
32 #include "voxel.h"
33 #include "config.h"
34 #include "version.h"
35 #include "filesys.h"
36 #include "mapblock.h"
37 #include "serverobject.h"
38 #include "genericobject.h"
39 #include "settings.h"
40 #include "profiler.h"
41 #include "log.h"
42 #include "scripting_game.h"
43 #include "nodedef.h"
44 #include "itemdef.h"
45 #include "craftdef.h"
46 #include "emerge.h"
47 #include "mapgen.h"
48 #include "mg_biome.h"
49 #include "content_mapnode.h"
50 #include "content_nodemeta.h"
51 #include "content_abm.h"
52 #include "content_sao.h"
53 #include "mods.h"
54 #include "sound.h" // dummySoundManager
55 #include "event_manager.h"
56 #include "serverlist.h"
57 #include "util/string.h"
58 #include "util/mathconstants.h"
59 #include "rollback.h"
60 #include "util/serialize.h"
61 #include "util/thread.h"
62 #include "defaultsettings.h"
63 #include "util/base64.h"
64 #include "util/sha1.h"
65 #include "util/hex.h"
66
67 class ClientNotFoundException : public BaseException
68 {
69 public:
70         ClientNotFoundException(const char *s):
71                 BaseException(s)
72         {}
73 };
74
75 class ServerThread : public JThread
76 {
77         Server *m_server;
78
79 public:
80
81         ServerThread(Server *server):
82                 JThread(),
83                 m_server(server)
84         {
85         }
86
87         void * Thread();
88 };
89
90 void * ServerThread::Thread()
91 {
92         log_register_thread("ServerThread");
93
94         DSTACK(__FUNCTION_NAME);
95         BEGIN_DEBUG_EXCEPTION_HANDLER
96
97         m_server->AsyncRunStep(true);
98
99         ThreadStarted();
100
101         porting::setThreadName("ServerThread");
102
103         while(!StopRequested())
104         {
105                 try{
106                         //TimeTaker timer("AsyncRunStep() + Receive()");
107
108                         m_server->AsyncRunStep();
109
110                         m_server->Receive();
111
112                 }
113                 catch(con::NoIncomingDataException &e)
114                 {
115                 }
116                 catch(con::PeerNotFoundException &e)
117                 {
118                         infostream<<"Server: PeerNotFoundException"<<std::endl;
119                 }
120                 catch(ClientNotFoundException &e)
121                 {
122                 }
123                 catch(con::ConnectionBindFailed &e)
124                 {
125                         m_server->setAsyncFatalError(e.what());
126                 }
127                 catch(LuaError &e)
128                 {
129                         m_server->setAsyncFatalError(e.what());
130                 }
131         }
132
133         END_DEBUG_EXCEPTION_HANDLER(errorstream)
134
135         return NULL;
136 }
137
138 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
139 {
140         if(pos_exists) *pos_exists = false;
141         switch(type){
142         case SSP_LOCAL:
143                 return v3f(0,0,0);
144         case SSP_POSITIONAL:
145                 if(pos_exists) *pos_exists = true;
146                 return pos;
147         case SSP_OBJECT: {
148                 if(object == 0)
149                         return v3f(0,0,0);
150                 ServerActiveObject *sao = env->getActiveObject(object);
151                 if(!sao)
152                         return v3f(0,0,0);
153                 if(pos_exists) *pos_exists = true;
154                 return sao->getBasePosition(); }
155         }
156         return v3f(0,0,0);
157 }
158
159
160
161 /*
162         Server
163 */
164
165 Server::Server(
166                 const std::string &path_world,
167                 const SubgameSpec &gamespec,
168                 bool simple_singleplayer_mode,
169                 bool ipv6
170         ):
171         m_path_world(path_world),
172         m_gamespec(gamespec),
173         m_simple_singleplayer_mode(simple_singleplayer_mode),
174         m_async_fatal_error(""),
175         m_env(NULL),
176         m_con(PROTOCOL_ID,
177                         512,
178                         CONNECTION_TIMEOUT,
179                         ipv6,
180                         this),
181         m_banmanager(NULL),
182         m_rollback(NULL),
183         m_enable_rollback_recording(false),
184         m_emerge(NULL),
185         m_script(NULL),
186         m_itemdef(createItemDefManager()),
187         m_nodedef(createNodeDefManager()),
188         m_craftdef(createCraftDefManager()),
189         m_event(new EventManager()),
190         m_thread(NULL),
191         m_time_of_day_send_timer(0),
192         m_uptime(0),
193         m_clients(&m_con),
194         m_shutdown_requested(false),
195         m_ignore_map_edit_events(false),
196         m_ignore_map_edit_events_peer_id(0),
197         m_next_sound_id(0)
198
199 {
200         m_liquid_transform_timer = 0.0;
201         m_liquid_transform_every = 1.0;
202         m_print_info_timer = 0.0;
203         m_masterserver_timer = 0.0;
204         m_objectdata_timer = 0.0;
205         m_emergethread_trigger_timer = 0.0;
206         m_savemap_timer = 0.0;
207
208         m_step_dtime = 0.0;
209         m_lag = g_settings->getFloat("dedicated_server_step");
210
211         if(path_world == "")
212                 throw ServerError("Supplied empty world path");
213
214         if(!gamespec.isValid())
215                 throw ServerError("Supplied invalid gamespec");
216
217         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
218         if(m_simple_singleplayer_mode)
219                 infostream<<" in simple singleplayer mode"<<std::endl;
220         else
221                 infostream<<std::endl;
222         infostream<<"- world:  "<<m_path_world<<std::endl;
223         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
224
225         // Initialize default settings and override defaults with those provided
226         // by the game
227         set_default_settings(g_settings);
228         Settings gamedefaults;
229         getGameMinetestConfig(gamespec.path, gamedefaults);
230         override_default_settings(g_settings, &gamedefaults);
231
232         // Create server thread
233         m_thread = new ServerThread(this);
234
235         // Create emerge manager
236         m_emerge = new EmergeManager(this);
237
238         // Create world if it doesn't exist
239         if(!initializeWorld(m_path_world, m_gamespec.id))
240                 throw ServerError("Failed to initialize world");
241
242         // Create ban manager
243         std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
244         m_banmanager = new BanManager(ban_path);
245
246         ModConfiguration modconf(m_path_world);
247         m_mods = modconf.getMods();
248         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
249         // complain about mods with unsatisfied dependencies
250         if(!modconf.isConsistent())
251         {
252                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
253                         it != unsatisfied_mods.end(); ++it)
254                 {
255                         ModSpec mod = *it;
256                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
257                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
258                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
259                                 errorstream << " \"" << *dep_it << "\"";
260                         errorstream << std::endl;
261                 }
262         }
263
264         Settings worldmt_settings;
265         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
266         worldmt_settings.readConfigFile(worldmt.c_str());
267         std::vector<std::string> names = worldmt_settings.getNames();
268         std::set<std::string> load_mod_names;
269         for(std::vector<std::string>::iterator it = names.begin();
270                 it != names.end(); ++it)
271         {
272                 std::string name = *it;
273                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
274                         load_mod_names.insert(name.substr(9));
275         }
276         // complain about mods declared to be loaded, but not found
277         for(std::vector<ModSpec>::iterator it = m_mods.begin();
278                         it != m_mods.end(); ++it)
279                 load_mod_names.erase((*it).name);
280         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
281                         it != unsatisfied_mods.end(); ++it)
282                 load_mod_names.erase((*it).name);
283         if(!load_mod_names.empty())
284         {
285                 errorstream << "The following mods could not be found:";
286                 for(std::set<std::string>::iterator it = load_mod_names.begin();
287                         it != load_mod_names.end(); ++it)
288                         errorstream << " \"" << (*it) << "\"";
289                 errorstream << std::endl;
290         }
291
292         // Lock environment
293         JMutexAutoLock envlock(m_env_mutex);
294
295         // Load mapgen params from Settings
296         m_emerge->loadMapgenParams();
297
298         // Create the Map (loads map_meta.txt, overriding configured mapgen params)
299         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
300
301         // Initialize scripting
302         infostream<<"Server: Initializing Lua"<<std::endl;
303
304         m_script = new GameScripting(this);
305
306         std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
307
308         if (!m_script->loadScript(scriptpath))
309                 throw ModError("Failed to load and run " + scriptpath);
310
311         // Print 'em
312         infostream<<"Server: Loading mods: ";
313         for(std::vector<ModSpec>::iterator i = m_mods.begin();
314                         i != m_mods.end(); i++){
315                 const ModSpec &mod = *i;
316                 infostream<<mod.name<<" ";
317         }
318         infostream<<std::endl;
319         // Load and run "mod" scripts
320         for(std::vector<ModSpec>::iterator i = m_mods.begin();
321                         i != m_mods.end(); i++){
322                 const ModSpec &mod = *i;
323                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
324                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
325                                 <<scriptpath<<"\"]"<<std::endl;
326                 bool success = m_script->loadMod(scriptpath, mod.name);
327                 if(!success){
328                         errorstream<<"Server: Failed to load and run "
329                                         <<scriptpath<<std::endl;
330                         throw ModError("Failed to load and run "+scriptpath);
331                 }
332         }
333
334         // Read Textures and calculate sha1 sums
335         fillMediaCache();
336
337         // Apply item aliases in the node definition manager
338         m_nodedef->updateAliases(m_itemdef);
339
340         m_nodedef->setNodeRegistrationStatus(true);
341
342         // Perform pending node name resolutions
343         m_nodedef->runNodeResolverCallbacks();
344
345         // Initialize Environment
346         m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
347
348         m_clients.setEnv(m_env);
349
350         // Initialize mapgens
351         m_emerge->initMapgens();
352
353         m_enable_rollback_recording = g_settings->getBool("enable_rollback_recording");
354         if (m_enable_rollback_recording) {
355                 // Create rollback manager
356                 m_rollback = new RollbackManager(m_path_world, this);
357         }
358
359         // Give environment reference to scripting api
360         m_script->initializeEnvironment(m_env);
361
362         // Register us to receive map edit events
363         servermap->addEventReceiver(this);
364
365         // If file exists, load environment metadata
366         if(fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt"))
367         {
368                 infostream<<"Server: Loading environment metadata"<<std::endl;
369                 m_env->loadMeta();
370         }
371
372         // Add some test ActiveBlockModifiers to environment
373         add_legacy_abms(m_env, m_nodedef);
374
375         m_liquid_transform_every = g_settings->getFloat("liquid_update");
376 }
377
378 Server::~Server()
379 {
380         infostream<<"Server destructing"<<std::endl;
381
382         // Send shutdown message
383         SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
384
385         {
386                 JMutexAutoLock envlock(m_env_mutex);
387
388                 // Execute script shutdown hooks
389                 m_script->on_shutdown();
390
391                 infostream<<"Server: Saving players"<<std::endl;
392                 m_env->saveLoadedPlayers();
393
394                 infostream<<"Server: Saving environment metadata"<<std::endl;
395                 m_env->saveMeta();
396         }
397
398         // Stop threads
399         stop();
400         delete m_thread;
401
402         // stop all emerge threads before deleting players that may have
403         // requested blocks to be emerged
404         m_emerge->stopThreads();
405
406         // Delete things in the reverse order of creation
407         delete m_env;
408
409         // N.B. the EmergeManager should be deleted after the Environment since Map
410         // depends on EmergeManager to write its current params to the map meta
411         delete m_emerge;
412         delete m_rollback;
413         delete m_banmanager;
414         delete m_event;
415         delete m_itemdef;
416         delete m_nodedef;
417         delete m_craftdef;
418
419         // Deinitialize scripting
420         infostream<<"Server: Deinitializing scripting"<<std::endl;
421         delete m_script;
422
423         // Delete detached inventories
424         for (std::map<std::string, Inventory*>::iterator
425                         i = m_detached_inventories.begin();
426                         i != m_detached_inventories.end(); i++) {
427                 delete i->second;
428         }
429 }
430
431 void Server::start(Address bind_addr)
432 {
433         DSTACK(__FUNCTION_NAME);
434
435         m_bind_addr = bind_addr;
436
437         infostream<<"Starting server on "
438                         << bind_addr.serializeString() <<"..."<<std::endl;
439
440         // Stop thread if already running
441         m_thread->Stop();
442
443         // Initialize connection
444         m_con.SetTimeoutMs(30);
445         m_con.Serve(bind_addr);
446
447         // Start thread
448         m_thread->Start();
449
450         // ASCII art for the win!
451         actionstream
452         <<"        .__               __                   __   "<<std::endl
453         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
454         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
455         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
456         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
457         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
458         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
459         actionstream<<"Server for gameid=\""<<m_gamespec.id
460                         <<"\" listening on "<<bind_addr.serializeString()<<":"
461                         <<bind_addr.getPort() << "."<<std::endl;
462 }
463
464 void Server::stop()
465 {
466         DSTACK(__FUNCTION_NAME);
467
468         infostream<<"Server: Stopping and waiting threads"<<std::endl;
469
470         // Stop threads (set run=false first so both start stopping)
471         m_thread->Stop();
472         //m_emergethread.setRun(false);
473         m_thread->Wait();
474         //m_emergethread.stop();
475
476         infostream<<"Server: Threads stopped"<<std::endl;
477 }
478
479 void Server::step(float dtime)
480 {
481         DSTACK(__FUNCTION_NAME);
482         // Limit a bit
483         if(dtime > 2.0)
484                 dtime = 2.0;
485         {
486                 JMutexAutoLock lock(m_step_dtime_mutex);
487                 m_step_dtime += dtime;
488         }
489         // Throw if fatal error occurred in thread
490         std::string async_err = m_async_fatal_error.get();
491         if(async_err != ""){
492                 throw ServerError(async_err);
493         }
494 }
495
496 void Server::AsyncRunStep(bool initial_step)
497 {
498         DSTACK(__FUNCTION_NAME);
499
500         g_profiler->add("Server::AsyncRunStep (num)", 1);
501
502         float dtime;
503         {
504                 JMutexAutoLock lock1(m_step_dtime_mutex);
505                 dtime = m_step_dtime;
506         }
507
508         {
509                 // Send blocks to clients
510                 SendBlocks(dtime);
511         }
512
513         if((dtime < 0.001) && (initial_step == false))
514                 return;
515
516         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
517
518         //infostream<<"Server steps "<<dtime<<std::endl;
519         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
520
521         {
522                 JMutexAutoLock lock1(m_step_dtime_mutex);
523                 m_step_dtime -= dtime;
524         }
525
526         /*
527                 Update uptime
528         */
529         {
530                 m_uptime.set(m_uptime.get() + dtime);
531         }
532
533         handlePeerChanges();
534
535         /*
536                 Update time of day and overall game time
537         */
538         {
539                 JMutexAutoLock envlock(m_env_mutex);
540
541                 m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
542
543                 /*
544                         Send to clients at constant intervals
545                 */
546
547                 m_time_of_day_send_timer -= dtime;
548                 if(m_time_of_day_send_timer < 0.0)
549                 {
550                         m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
551                         u16 time = m_env->getTimeOfDay();
552                         float time_speed = g_settings->getFloat("time_speed");
553                         SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
554                 }
555         }
556
557         {
558                 JMutexAutoLock lock(m_env_mutex);
559                 // Figure out and report maximum lag to environment
560                 float max_lag = m_env->getMaxLagEstimate();
561                 max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
562                 if(dtime > max_lag){
563                         if(dtime > 0.1 && dtime > max_lag * 2.0)
564                                 infostream<<"Server: Maximum lag peaked to "<<dtime
565                                                 <<" s"<<std::endl;
566                         max_lag = dtime;
567                 }
568                 m_env->reportMaxLagEstimate(max_lag);
569                 // Step environment
570                 ScopeProfiler sp(g_profiler, "SEnv step");
571                 ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
572                 m_env->step(dtime);
573         }
574
575         static const float map_timer_and_unload_dtime = 2.92;
576         if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
577         {
578                 JMutexAutoLock lock(m_env_mutex);
579                 // Run Map's timers and unload unused data
580                 ScopeProfiler sp(g_profiler, "Server: map timer and unload");
581                 m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
582                                 g_settings->getFloat("server_unload_unused_data_timeout"));
583         }
584
585         /*
586                 Do background stuff
587         */
588
589         /*
590                 Handle players
591         */
592         {
593                 JMutexAutoLock lock(m_env_mutex);
594
595                 std::list<u16> clientids = m_clients.getClientIDs();
596
597                 ScopeProfiler sp(g_profiler, "Server: handle players");
598
599                 for(std::list<u16>::iterator
600                         i = clientids.begin();
601                         i != clientids.end(); ++i)
602                 {
603                         PlayerSAO *playersao = getPlayerSAO(*i);
604                         if(playersao == NULL)
605                                 continue;
606
607                         /*
608                                 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, 6);
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                 if(far_players) {
2090                         // Get player
2091                         if(Player *player = m_env->getPlayer(*i)) {
2092                                 // If player is far away, only set modified blocks not sent
2093                                 v3f player_pos = player->getPosition();
2094                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2095                                         far_players->push_back(*i);
2096                                         continue;
2097                                 }
2098                         }
2099                 }
2100
2101                 // Send as reliable
2102                 m_clients.send(*i, 0, pkt, true, false);
2103         }
2104         // This loop needs the deletion of the packet here
2105         delete pkt;
2106 }
2107
2108 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2109                 std::list<u16> *far_players, float far_d_nodes,
2110                 bool remove_metadata)
2111 {
2112         float maxd = far_d_nodes*BS;
2113         v3f p_f = intToFloat(p, BS);
2114
2115         std::list<u16> clients = m_clients.getClientIDs();
2116         for(std::list<u16>::iterator
2117                         i = clients.begin();
2118                         i != clients.end(); ++i)
2119                 {
2120
2121                 if(far_players)
2122                 {
2123                         // Get player
2124                         Player *player = m_env->getPlayer(*i);
2125                         if(player)
2126                         {
2127                                 // If player is far away, only set modified blocks not sent
2128                                 v3f player_pos = player->getPosition();
2129                                 if(player_pos.getDistanceFrom(p_f) > maxd)
2130                                 {
2131                                         far_players->push_back(*i);
2132                                         continue;
2133                                 }
2134                         }
2135                 }
2136
2137                 NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2138                 m_clients.Lock();
2139                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2140                 if (client != 0) {
2141                         *pkt << p << n.param0 << n.param1 << n.param2
2142                                         << (u8) (remove_metadata ? 0 : 1);
2143
2144                         if (!remove_metadata) {
2145                                 if (client->net_proto_version <= 21) {
2146                                         // Old clients always clear metadata; fix it
2147                                         // by sending the full block again.
2148                                         client->SetBlockNotSent(p);
2149                                 }
2150                         }
2151                 }
2152                 m_clients.Unlock();
2153
2154                 // Send as reliable
2155                 if (pkt->getSize() > 0)
2156                         m_clients.send(*i, 0, pkt, true);
2157         }
2158 }
2159
2160 void Server::setBlockNotSent(v3s16 p)
2161 {
2162         std::list<u16> clients = m_clients.getClientIDs();
2163         m_clients.Lock();
2164         for(std::list<u16>::iterator
2165                 i = clients.begin();
2166                 i != clients.end(); ++i)
2167         {
2168                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2169                 client->SetBlockNotSent(p);
2170         }
2171         m_clients.Unlock();
2172 }
2173
2174 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2175 {
2176         DSTACK(__FUNCTION_NAME);
2177
2178         v3s16 p = block->getPos();
2179
2180         /*
2181                 Create a packet with the block in the right format
2182         */
2183
2184         std::ostringstream os(std::ios_base::binary);
2185         block->serialize(os, ver, false);
2186         block->serializeNetworkSpecific(os, net_proto_version);
2187         std::string s = os.str();
2188
2189         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_BLOCKDATA,
2190                 2 + 2 + 2 + 2 + s.size(), peer_id);
2191
2192         *pkt << p;
2193         pkt->putRawString(s.c_str(), s.size());
2194         Send(pkt);
2195 }
2196
2197 void Server::SendBlocks(float dtime)
2198 {
2199         DSTACK(__FUNCTION_NAME);
2200
2201         JMutexAutoLock envlock(m_env_mutex);
2202         //TODO check if one big lock could be faster then multiple small ones
2203
2204         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2205
2206         std::vector<PrioritySortedBlockTransfer> queue;
2207
2208         s32 total_sending = 0;
2209
2210         {
2211                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2212
2213                 std::list<u16> clients = m_clients.getClientIDs();
2214
2215                 m_clients.Lock();
2216                 for(std::list<u16>::iterator
2217                         i = clients.begin();
2218                         i != clients.end(); ++i)
2219                 {
2220                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2221
2222                         if (client == NULL)
2223                                 continue;
2224
2225                         total_sending += client->SendingCount();
2226                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2227                 }
2228                 m_clients.Unlock();
2229         }
2230
2231         // Sort.
2232         // Lowest priority number comes first.
2233         // Lowest is most important.
2234         std::sort(queue.begin(), queue.end());
2235
2236         m_clients.Lock();
2237         for(u32 i=0; i<queue.size(); i++)
2238         {
2239                 //TODO: Calculate limit dynamically
2240                 if(total_sending >= g_settings->getS32
2241                                 ("max_simultaneous_block_sends_server_total"))
2242                         break;
2243
2244                 PrioritySortedBlockTransfer q = queue[i];
2245
2246                 MapBlock *block = NULL;
2247                 try
2248                 {
2249                         block = m_env->getMap().getBlockNoCreate(q.pos);
2250                 }
2251                 catch(InvalidPositionException &e)
2252                 {
2253                         continue;
2254                 }
2255
2256                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2257
2258                 if(!client)
2259                         continue;
2260
2261                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2262
2263                 client->SentBlock(q.pos);
2264                 total_sending++;
2265         }
2266         m_clients.Unlock();
2267 }
2268
2269 void Server::fillMediaCache()
2270 {
2271         DSTACK(__FUNCTION_NAME);
2272
2273         infostream<<"Server: Calculating media file checksums"<<std::endl;
2274
2275         // Collect all media file paths
2276         std::list<std::string> paths;
2277         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2278                         i != m_mods.end(); i++){
2279                 const ModSpec &mod = *i;
2280                 paths.push_back(mod.path + DIR_DELIM + "textures");
2281                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2282                 paths.push_back(mod.path + DIR_DELIM + "media");
2283                 paths.push_back(mod.path + DIR_DELIM + "models");
2284         }
2285         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2286
2287         // Collect media file information from paths into cache
2288         for(std::list<std::string>::iterator i = paths.begin();
2289                         i != paths.end(); i++)
2290         {
2291                 std::string mediapath = *i;
2292                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2293                 for(u32 j=0; j<dirlist.size(); j++){
2294                         if(dirlist[j].dir) // Ignode dirs
2295                                 continue;
2296                         std::string filename = dirlist[j].name;
2297                         // If name contains illegal characters, ignore the file
2298                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
2299                                 infostream<<"Server: ignoring illegal file name: \""
2300                                                 <<filename<<"\""<<std::endl;
2301                                 continue;
2302                         }
2303                         // If name is not in a supported format, ignore it
2304                         const char *supported_ext[] = {
2305                                 ".png", ".jpg", ".bmp", ".tga",
2306                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2307                                 ".ogg",
2308                                 ".x", ".b3d", ".md2", ".obj",
2309                                 NULL
2310                         };
2311                         if(removeStringEnd(filename, supported_ext) == ""){
2312                                 infostream<<"Server: ignoring unsupported file extension: \""
2313                                                 <<filename<<"\""<<std::endl;
2314                                 continue;
2315                         }
2316                         // Ok, attempt to load the file and add to cache
2317                         std::string filepath = mediapath + DIR_DELIM + filename;
2318                         // Read data
2319                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2320                         if(fis.good() == false){
2321                                 errorstream<<"Server::fillMediaCache(): Could not open \""
2322                                                 <<filename<<"\" for reading"<<std::endl;
2323                                 continue;
2324                         }
2325                         std::ostringstream tmp_os(std::ios_base::binary);
2326                         bool bad = false;
2327                         for(;;){
2328                                 char buf[1024];
2329                                 fis.read(buf, 1024);
2330                                 std::streamsize len = fis.gcount();
2331                                 tmp_os.write(buf, len);
2332                                 if(fis.eof())
2333                                         break;
2334                                 if(!fis.good()){
2335                                         bad = true;
2336                                         break;
2337                                 }
2338                         }
2339                         if(bad){
2340                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2341                                                 <<filename<<"\""<<std::endl;
2342                                 continue;
2343                         }
2344                         if(tmp_os.str().length() == 0){
2345                                 errorstream<<"Server::fillMediaCache(): Empty file \""
2346                                                 <<filepath<<"\""<<std::endl;
2347                                 continue;
2348                         }
2349
2350                         SHA1 sha1;
2351                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2352
2353                         unsigned char *digest = sha1.getDigest();
2354                         std::string sha1_base64 = base64_encode(digest, 20);
2355                         std::string sha1_hex = hex_encode((char*)digest, 20);
2356                         free(digest);
2357
2358                         // Put in list
2359                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
2360                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
2361                 }
2362         }
2363 }
2364
2365 struct SendableMediaAnnouncement
2366 {
2367         std::string name;
2368         std::string sha1_digest;
2369
2370         SendableMediaAnnouncement(const std::string &name_="",
2371                                   const std::string &sha1_digest_=""):
2372                 name(name_),
2373                 sha1_digest(sha1_digest_)
2374         {}
2375 };
2376
2377 void Server::sendMediaAnnouncement(u16 peer_id)
2378 {
2379         DSTACK(__FUNCTION_NAME);
2380
2381         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
2382                         <<std::endl;
2383
2384         std::list<SendableMediaAnnouncement> file_announcements;
2385
2386         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
2387                         i != m_media.end(); i++){
2388                 // Put in list
2389                 file_announcements.push_back(
2390                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
2391         }
2392
2393         // Make packet
2394         std::ostringstream os(std::ios_base::binary);
2395
2396         /*
2397                 u32 number of files
2398                 for each texture {
2399                         u16 length of name
2400                         string name
2401                         u16 length of sha1_digest
2402                         string sha1_digest
2403                 }
2404         */
2405
2406         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2407         *pkt << (u16) file_announcements.size();
2408
2409         for(std::list<SendableMediaAnnouncement>::iterator
2410                         j = file_announcements.begin();
2411                         j != file_announcements.end(); ++j) {
2412                 *pkt << j->name << j->sha1_digest;
2413         }
2414
2415         *pkt << g_settings->get("remote_media");
2416         Send(pkt);
2417 }
2418
2419 struct SendableMedia
2420 {
2421         std::string name;
2422         std::string path;
2423         std::string data;
2424
2425         SendableMedia(const std::string &name_="", const std::string &path_="",
2426                       const std::string &data_=""):
2427                 name(name_),
2428                 path(path_),
2429                 data(data_)
2430         {}
2431 };
2432
2433 void Server::sendRequestedMedia(u16 peer_id,
2434                 const std::list<std::string> &tosend)
2435 {
2436         DSTACK(__FUNCTION_NAME);
2437
2438         verbosestream<<"Server::sendRequestedMedia(): "
2439                         <<"Sending files to client"<<std::endl;
2440
2441         /* Read files */
2442
2443         // Put 5kB in one bunch (this is not accurate)
2444         u32 bytes_per_bunch = 5000;
2445
2446         std::vector< std::list<SendableMedia> > file_bunches;
2447         file_bunches.push_back(std::list<SendableMedia>());
2448
2449         u32 file_size_bunch_total = 0;
2450
2451         for(std::list<std::string>::const_iterator i = tosend.begin();
2452                         i != tosend.end(); ++i)
2453         {
2454                 const std::string &name = *i;
2455
2456                 if(m_media.find(name) == m_media.end()) {
2457                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2458                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2459                         continue;
2460                 }
2461
2462                 //TODO get path + name
2463                 std::string tpath = m_media[name].path;
2464
2465                 // Read data
2466                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2467                 if(fis.good() == false){
2468                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2469                                         <<tpath<<"\" for reading"<<std::endl;
2470                         continue;
2471                 }
2472                 std::ostringstream tmp_os(std::ios_base::binary);
2473                 bool bad = false;
2474                 for(;;) {
2475                         char buf[1024];
2476                         fis.read(buf, 1024);
2477                         std::streamsize len = fis.gcount();
2478                         tmp_os.write(buf, len);
2479                         file_size_bunch_total += len;
2480                         if(fis.eof())
2481                                 break;
2482                         if(!fis.good()) {
2483                                 bad = true;
2484                                 break;
2485                         }
2486                 }
2487                 if(bad) {
2488                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2489                                         <<name<<"\""<<std::endl;
2490                         continue;
2491                 }
2492                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2493                                 <<tname<<"\""<<std::endl;*/
2494                 // Put in list
2495                 file_bunches[file_bunches.size()-1].push_back(
2496                                 SendableMedia(name, tpath, tmp_os.str()));
2497
2498                 // Start next bunch if got enough data
2499                 if(file_size_bunch_total >= bytes_per_bunch) {
2500                         file_bunches.push_back(std::list<SendableMedia>());
2501                         file_size_bunch_total = 0;
2502                 }
2503
2504         }
2505
2506         /* Create and send packets */
2507
2508         u16 num_bunches = file_bunches.size();
2509         for(u16 i = 0; i < num_bunches; i++) {
2510                 /*
2511                         u16 command
2512                         u16 total number of texture bunches
2513                         u16 index of this bunch
2514                         u32 number of files in this bunch
2515                         for each file {
2516                                 u16 length of name
2517                                 string name
2518                                 u32 length of data
2519                                 data
2520                         }
2521                 */
2522
2523                 NetworkPacket* pkt = new NetworkPacket(TOCLIENT_MEDIA, 0, peer_id);
2524                 *pkt << num_bunches << i << (u32) file_bunches[i].size();
2525
2526                 for(std::list<SendableMedia>::iterator
2527                                 j = file_bunches[i].begin();
2528                                 j != file_bunches[i].end(); ++j) {
2529                         *pkt << j->name;
2530                         pkt->putLongString(j->data);
2531                 }
2532
2533                 verbosestream << "Server::sendRequestedMedia(): bunch "
2534                                 << i << "/" << num_bunches
2535                                 << " files=" << file_bunches[i].size()
2536                                 << " size="  << pkt->getSize() << std::endl;
2537                 Send(pkt);
2538         }
2539 }
2540
2541 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2542 {
2543         if(m_detached_inventories.count(name) == 0) {
2544                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2545                 return;
2546         }
2547         Inventory *inv = m_detached_inventories[name];
2548         std::ostringstream os(std::ios_base::binary);
2549
2550         os << serializeString(name);
2551         inv->serialize(os);
2552
2553         // Make data buffer
2554         std::string s = os.str();
2555
2556         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2557         pkt->putRawString(s.c_str(), s.size());
2558
2559         if (peer_id != PEER_ID_INEXISTENT) {
2560                 Send(pkt);
2561         }
2562         else {
2563                 m_clients.sendToAll(0, pkt, true);
2564         }
2565 }
2566
2567 void Server::sendDetachedInventories(u16 peer_id)
2568 {
2569         DSTACK(__FUNCTION_NAME);
2570
2571         for(std::map<std::string, Inventory*>::iterator
2572                         i = m_detached_inventories.begin();
2573                         i != m_detached_inventories.end(); i++) {
2574                 const std::string &name = i->first;
2575                 //Inventory *inv = i->second;
2576                 sendDetachedInventory(name, peer_id);
2577         }
2578 }
2579
2580 /*
2581         Something random
2582 */
2583
2584 void Server::DiePlayer(u16 peer_id)
2585 {
2586         DSTACK(__FUNCTION_NAME);
2587
2588         PlayerSAO *playersao = getPlayerSAO(peer_id);
2589         assert(playersao);
2590
2591         infostream<<"Server::DiePlayer(): Player "
2592                         <<playersao->getPlayer()->getName()
2593                         <<" dies"<<std::endl;
2594
2595         playersao->setHP(0);
2596
2597         // Trigger scripted stuff
2598         m_script->on_dieplayer(playersao);
2599
2600         SendPlayerHP(peer_id);
2601         SendDeathscreen(peer_id, false, v3f(0,0,0));
2602 }
2603
2604 void Server::RespawnPlayer(u16 peer_id)
2605 {
2606         DSTACK(__FUNCTION_NAME);
2607
2608         PlayerSAO *playersao = getPlayerSAO(peer_id);
2609         assert(playersao);
2610
2611         infostream<<"Server::RespawnPlayer(): Player "
2612                         <<playersao->getPlayer()->getName()
2613                         <<" respawns"<<std::endl;
2614
2615         playersao->setHP(PLAYER_MAX_HP);
2616         playersao->setBreath(PLAYER_MAX_BREATH);
2617
2618         bool repositioned = m_script->on_respawnplayer(playersao);
2619         if(!repositioned){
2620                 v3f pos = findSpawnPos(m_env->getServerMap());
2621                 playersao->setPos(pos);
2622         }
2623 }
2624
2625 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
2626 {
2627         DSTACK(__FUNCTION_NAME);
2628
2629         SendAccessDenied(peer_id, reason);
2630         m_clients.event(peer_id, CSE_SetDenied);
2631         m_con.DisconnectPeer(peer_id);
2632 }
2633
2634 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2635 {
2636         DSTACK(__FUNCTION_NAME);
2637         std::wstring message;
2638         {
2639                 /*
2640                         Clear references to playing sounds
2641                 */
2642                 for(std::map<s32, ServerPlayingSound>::iterator
2643                                 i = m_playing_sounds.begin();
2644                                 i != m_playing_sounds.end();)
2645                 {
2646                         ServerPlayingSound &psound = i->second;
2647                         psound.clients.erase(peer_id);
2648                         if(psound.clients.empty())
2649                                 m_playing_sounds.erase(i++);
2650                         else
2651                                 i++;
2652                 }
2653
2654                 Player *player = m_env->getPlayer(peer_id);
2655
2656                 // Collect information about leaving in chat
2657                 {
2658                         if(player != NULL && reason != CDR_DENY)
2659                         {
2660                                 std::wstring name = narrow_to_wide(player->getName());
2661                                 message += L"*** ";
2662                                 message += name;
2663                                 message += L" left the game.";
2664                                 if(reason == CDR_TIMEOUT)
2665                                         message += L" (timed out)";
2666                         }
2667                 }
2668
2669                 /* Run scripts and remove from environment */
2670                 {
2671                         if(player != NULL)
2672                         {
2673                                 PlayerSAO *playersao = player->getPlayerSAO();
2674                                 assert(playersao);
2675
2676                                 m_script->on_leaveplayer(playersao);
2677
2678                                 playersao->disconnected();
2679                         }
2680                 }
2681
2682                 /*
2683                         Print out action
2684                 */
2685                 {
2686                         if(player != NULL && reason != CDR_DENY)
2687                         {
2688                                 std::ostringstream os(std::ios_base::binary);
2689                                 std::list<u16> clients = m_clients.getClientIDs();
2690
2691                                 for(std::list<u16>::iterator
2692                                         i = clients.begin();
2693                                         i != clients.end(); ++i)
2694                                 {
2695                                         // Get player
2696                                         Player *player = m_env->getPlayer(*i);
2697                                         if(!player)
2698                                                 continue;
2699                                         // Get name of player
2700                                         os<<player->getName()<<" ";
2701                                 }
2702
2703                                 actionstream<<player->getName()<<" "
2704                                                 <<(reason==CDR_TIMEOUT?"times out.":"leaves game.")
2705                                                 <<" List of players: "<<os.str()<<std::endl;
2706                         }
2707                 }
2708                 {
2709                         JMutexAutoLock env_lock(m_env_mutex);
2710                         m_clients.DeleteClient(peer_id);
2711                 }
2712         }
2713
2714         // Send leave chat message to all remaining clients
2715         if(message.length() != 0)
2716                 SendChatMessage(PEER_ID_INEXISTENT,message);
2717 }
2718
2719 void Server::UpdateCrafting(u16 peer_id)
2720 {
2721         DSTACK(__FUNCTION_NAME);
2722
2723         Player* player = m_env->getPlayer(peer_id);
2724         assert(player);
2725
2726         // Get a preview for crafting
2727         ItemStack preview;
2728         InventoryLocation loc;
2729         loc.setPlayer(player->getName());
2730         getCraftingResult(&player->inventory, preview, false, this);
2731         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
2732
2733         // Put the new preview in
2734         InventoryList *plist = player->inventory.getList("craftpreview");
2735         assert(plist);
2736         assert(plist->getSize() >= 1);
2737         plist->changeItem(0, preview);
2738 }
2739
2740 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2741 {
2742         RemoteClient *client = getClientNoEx(peer_id,state_min);
2743         if(!client)
2744                 throw ClientNotFoundException("Client not found");
2745
2746         return client;
2747 }
2748 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2749 {
2750         return m_clients.getClientNoEx(peer_id, state_min);
2751 }
2752
2753 std::string Server::getPlayerName(u16 peer_id)
2754 {
2755         Player *player = m_env->getPlayer(peer_id);
2756         if(player == NULL)
2757                 return "[id="+itos(peer_id)+"]";
2758         return player->getName();
2759 }
2760
2761 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2762 {
2763         Player *player = m_env->getPlayer(peer_id);
2764         if(player == NULL)
2765                 return NULL;
2766         return player->getPlayerSAO();
2767 }
2768
2769 std::wstring Server::getStatusString()
2770 {
2771         std::wostringstream os(std::ios_base::binary);
2772         os<<L"# Server: ";
2773         // Version
2774         os<<L"version="<<narrow_to_wide(minetest_version_simple);
2775         // Uptime
2776         os<<L", uptime="<<m_uptime.get();
2777         // Max lag estimate
2778         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2779         // Information about clients
2780         bool first = true;
2781         os<<L", clients={";
2782         std::list<u16> clients = m_clients.getClientIDs();
2783         for(std::list<u16>::iterator i = clients.begin();
2784                 i != clients.end(); ++i)
2785         {
2786                 // Get player
2787                 Player *player = m_env->getPlayer(*i);
2788                 // Get name of player
2789                 std::wstring name = L"unknown";
2790                 if(player != NULL)
2791                         name = narrow_to_wide(player->getName());
2792                 // Add name to information string
2793                 if(!first)
2794                         os<<L", ";
2795                 else
2796                         first = false;
2797                 os<<name;
2798         }
2799         os<<L"}";
2800         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2801                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2802         if(g_settings->get("motd") != "")
2803                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2804         return os.str();
2805 }
2806
2807 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2808 {
2809         std::set<std::string> privs;
2810         m_script->getAuth(name, NULL, &privs);
2811         return privs;
2812 }
2813
2814 bool Server::checkPriv(const std::string &name, const std::string &priv)
2815 {
2816         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2817         return (privs.count(priv) != 0);
2818 }
2819
2820 void Server::reportPrivsModified(const std::string &name)
2821 {
2822         if(name == ""){
2823                 std::list<u16> clients = m_clients.getClientIDs();
2824                 for(std::list<u16>::iterator
2825                                 i = clients.begin();
2826                                 i != clients.end(); ++i){
2827                         Player *player = m_env->getPlayer(*i);
2828                         reportPrivsModified(player->getName());
2829                 }
2830         } else {
2831                 Player *player = m_env->getPlayer(name.c_str());
2832                 if(!player)
2833                         return;
2834                 SendPlayerPrivileges(player->peer_id);
2835                 PlayerSAO *sao = player->getPlayerSAO();
2836                 if(!sao)
2837                         return;
2838                 sao->updatePrivileges(
2839                                 getPlayerEffectivePrivs(name),
2840                                 isSingleplayer());
2841         }
2842 }
2843
2844 void Server::reportInventoryFormspecModified(const std::string &name)
2845 {
2846         Player *player = m_env->getPlayer(name.c_str());
2847         if(!player)
2848                 return;
2849         SendPlayerInventoryFormspec(player->peer_id);
2850 }
2851
2852 void Server::setIpBanned(const std::string &ip, const std::string &name)
2853 {
2854         m_banmanager->add(ip, name);
2855 }
2856
2857 void Server::unsetIpBanned(const std::string &ip_or_name)
2858 {
2859         m_banmanager->remove(ip_or_name);
2860 }
2861
2862 std::string Server::getBanDescription(const std::string &ip_or_name)
2863 {
2864         return m_banmanager->getBanDescription(ip_or_name);
2865 }
2866
2867 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2868 {
2869         Player *player = m_env->getPlayer(name);
2870         if(!player)
2871                 return;
2872
2873         if (player->peer_id == PEER_ID_INEXISTENT)
2874                 return;
2875
2876         SendChatMessage(player->peer_id, msg);
2877 }
2878
2879 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
2880 {
2881         Player *player = m_env->getPlayer(playername);
2882
2883         if(!player)
2884         {
2885                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
2886                 return false;
2887         }
2888
2889         SendShowFormspecMessage(player->peer_id, formspec, formname);
2890         return true;
2891 }
2892
2893 u32 Server::hudAdd(Player *player, HudElement *form) {
2894         if (!player)
2895                 return -1;
2896
2897         u32 id = player->addHud(form);
2898
2899         SendHUDAdd(player->peer_id, id, form);
2900
2901         return id;
2902 }
2903
2904 bool Server::hudRemove(Player *player, u32 id) {
2905         if (!player)
2906                 return false;
2907
2908         HudElement* todel = player->removeHud(id);
2909
2910         if (!todel)
2911                 return false;
2912
2913         delete todel;
2914
2915         SendHUDRemove(player->peer_id, id);
2916         return true;
2917 }
2918
2919 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
2920         if (!player)
2921                 return false;
2922
2923         SendHUDChange(player->peer_id, id, stat, data);
2924         return true;
2925 }
2926
2927 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
2928         if (!player)
2929                 return false;
2930
2931         SendHUDSetFlags(player->peer_id, flags, mask);
2932         player->hud_flags = flags;
2933
2934         PlayerSAO* playersao = player->getPlayerSAO();
2935
2936         if (playersao == NULL)
2937                 return false;
2938
2939         m_script->player_event(playersao, "hud_changed");
2940         return true;
2941 }
2942
2943 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
2944         if (!player)
2945                 return false;
2946         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
2947                 return false;
2948
2949         std::ostringstream os(std::ios::binary);
2950         writeS32(os, hotbar_itemcount);
2951         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
2952         return true;
2953 }
2954
2955 void Server::hudSetHotbarImage(Player *player, std::string name) {
2956         if (!player)
2957                 return;
2958
2959         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
2960 }
2961
2962 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
2963         if (!player)
2964                 return;
2965
2966         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
2967 }
2968
2969 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
2970 {
2971         if (!player)
2972                 return false;
2973
2974         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
2975         return true;
2976 }
2977
2978 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
2979 {
2980         if (!player)
2981                 return false;
2982
2983         SendEyeOffset(player->peer_id, first, third);
2984         return true;
2985 }
2986
2987 bool Server::setSky(Player *player, const video::SColor &bgcolor,
2988                 const std::string &type, const std::vector<std::string> &params)
2989 {
2990         if (!player)
2991                 return false;
2992
2993         SendSetSky(player->peer_id, bgcolor, type, params);
2994         return true;
2995 }
2996
2997 bool Server::overrideDayNightRatio(Player *player, bool do_override,
2998                 float ratio)
2999 {
3000         if (!player)
3001                 return false;
3002
3003         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3004         return true;
3005 }
3006
3007 void Server::notifyPlayers(const std::wstring &msg)
3008 {
3009         SendChatMessage(PEER_ID_INEXISTENT,msg);
3010 }
3011
3012 void Server::spawnParticle(const char *playername, v3f pos,
3013                 v3f velocity, v3f acceleration,
3014                 float expirationtime, float size, bool
3015                 collisiondetection, bool vertical, std::string texture)
3016 {
3017         Player *player = m_env->getPlayer(playername);
3018         if(!player)
3019                 return;
3020         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
3021                         expirationtime, size, collisiondetection, vertical, texture);
3022 }
3023
3024 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
3025                 float expirationtime, float size,
3026                 bool collisiondetection, bool vertical, std::string texture)
3027 {
3028         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
3029                         expirationtime, size, collisiondetection, vertical, texture);
3030 }
3031
3032 u32 Server::addParticleSpawner(const char *playername,
3033                 u16 amount, float spawntime,
3034                 v3f minpos, v3f maxpos,
3035                 v3f minvel, v3f maxvel,
3036                 v3f minacc, v3f maxacc,
3037                 float minexptime, float maxexptime,
3038                 float minsize, float maxsize,
3039                 bool collisiondetection, bool vertical, std::string texture)
3040 {
3041         Player *player = m_env->getPlayer(playername);
3042         if(!player)
3043                 return -1;
3044
3045         u32 id = 0;
3046         for(;;) // look for unused particlespawner id
3047         {
3048                 id++;
3049                 if (std::find(m_particlespawner_ids.begin(),
3050                                 m_particlespawner_ids.end(), id)
3051                                 == m_particlespawner_ids.end())
3052                 {
3053                         m_particlespawner_ids.push_back(id);
3054                         break;
3055                 }
3056         }
3057
3058         SendAddParticleSpawner(player->peer_id, amount, spawntime,
3059                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3060                 minexptime, maxexptime, minsize, maxsize,
3061                 collisiondetection, vertical, texture, id);
3062
3063         return id;
3064 }
3065
3066 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
3067                 v3f minpos, v3f maxpos,
3068                 v3f minvel, v3f maxvel,
3069                 v3f minacc, v3f maxacc,
3070                 float minexptime, float maxexptime,
3071                 float minsize, float maxsize,
3072                 bool collisiondetection, bool vertical, std::string texture)
3073 {
3074         u32 id = 0;
3075         for(;;) // look for unused particlespawner id
3076         {
3077                 id++;
3078                 if (std::find(m_particlespawner_ids.begin(),
3079                                 m_particlespawner_ids.end(), id)
3080                                 == m_particlespawner_ids.end())
3081                 {
3082                         m_particlespawner_ids.push_back(id);
3083                         break;
3084                 }
3085         }
3086
3087         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
3088                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3089                 minexptime, maxexptime, minsize, maxsize,
3090                 collisiondetection, vertical, texture, id);
3091
3092         return id;
3093 }
3094
3095 void Server::deleteParticleSpawner(const char *playername, u32 id)
3096 {
3097         Player *player = m_env->getPlayer(playername);
3098         if(!player)
3099                 return;
3100
3101         m_particlespawner_ids.erase(
3102                         std::remove(m_particlespawner_ids.begin(),
3103                         m_particlespawner_ids.end(), id),
3104                         m_particlespawner_ids.end());
3105         SendDeleteParticleSpawner(player->peer_id, id);
3106 }
3107
3108 void Server::deleteParticleSpawnerAll(u32 id)
3109 {
3110         m_particlespawner_ids.erase(
3111                         std::remove(m_particlespawner_ids.begin(),
3112                         m_particlespawner_ids.end(), id),
3113                         m_particlespawner_ids.end());
3114         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3115 }
3116
3117 Inventory* Server::createDetachedInventory(const std::string &name)
3118 {
3119         if(m_detached_inventories.count(name) > 0){
3120                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3121                 delete m_detached_inventories[name];
3122         } else {
3123                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3124         }
3125         Inventory *inv = new Inventory(m_itemdef);
3126         assert(inv);
3127         m_detached_inventories[name] = inv;
3128         //TODO find a better way to do this
3129         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3130         return inv;
3131 }
3132
3133 class BoolScopeSet
3134 {
3135 public:
3136         BoolScopeSet(bool *dst, bool val):
3137                 m_dst(dst)
3138         {
3139                 m_orig_state = *m_dst;
3140                 *m_dst = val;
3141         }
3142         ~BoolScopeSet()
3143         {
3144                 *m_dst = m_orig_state;
3145         }
3146 private:
3147         bool *m_dst;
3148         bool m_orig_state;
3149 };
3150
3151 // actions: time-reversed list
3152 // Return value: success/failure
3153 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3154                 std::list<std::string> *log)
3155 {
3156         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3157         ServerMap *map = (ServerMap*)(&m_env->getMap());
3158
3159         // Fail if no actions to handle
3160         if(actions.empty()){
3161                 log->push_back("Nothing to do.");
3162                 return false;
3163         }
3164
3165         int num_tried = 0;
3166         int num_failed = 0;
3167
3168         for(std::list<RollbackAction>::const_iterator
3169                         i = actions.begin();
3170                         i != actions.end(); i++)
3171         {
3172                 const RollbackAction &action = *i;
3173                 num_tried++;
3174                 bool success = action.applyRevert(map, this, this);
3175                 if(!success){
3176                         num_failed++;
3177                         std::ostringstream os;
3178                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3179                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3180                         if(log)
3181                                 log->push_back(os.str());
3182                 }else{
3183                         std::ostringstream os;
3184                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3185                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3186                         if(log)
3187                                 log->push_back(os.str());
3188                 }
3189         }
3190
3191         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3192                         <<" failed"<<std::endl;
3193
3194         // Call it done if less than half failed
3195         return num_failed <= num_tried/2;
3196 }
3197
3198 // IGameDef interface
3199 // Under envlock
3200 IItemDefManager* Server::getItemDefManager()
3201 {
3202         return m_itemdef;
3203 }
3204 INodeDefManager* Server::getNodeDefManager()
3205 {
3206         return m_nodedef;
3207 }
3208 ICraftDefManager* Server::getCraftDefManager()
3209 {
3210         return m_craftdef;
3211 }
3212 ITextureSource* Server::getTextureSource()
3213 {
3214         return NULL;
3215 }
3216 IShaderSource* Server::getShaderSource()
3217 {
3218         return NULL;
3219 }
3220 scene::ISceneManager* Server::getSceneManager()
3221 {
3222         return NULL;
3223 }
3224
3225 u16 Server::allocateUnknownNodeId(const std::string &name)
3226 {
3227         return m_nodedef->allocateDummy(name);
3228 }
3229 ISoundManager* Server::getSoundManager()
3230 {
3231         return &dummySoundManager;
3232 }
3233 MtEventManager* Server::getEventManager()
3234 {
3235         return m_event;
3236 }
3237
3238 IWritableItemDefManager* Server::getWritableItemDefManager()
3239 {
3240         return m_itemdef;
3241 }
3242 IWritableNodeDefManager* Server::getWritableNodeDefManager()
3243 {
3244         return m_nodedef;
3245 }
3246 IWritableCraftDefManager* Server::getWritableCraftDefManager()
3247 {
3248         return m_craftdef;
3249 }
3250
3251 const ModSpec* Server::getModSpec(const std::string &modname)
3252 {
3253         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3254                         i != m_mods.end(); i++){
3255                 const ModSpec &mod = *i;
3256                 if(mod.name == modname)
3257                         return &mod;
3258         }
3259         return NULL;
3260 }
3261 void Server::getModNames(std::list<std::string> &modlist)
3262 {
3263         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
3264         {
3265                 modlist.push_back(i->name);
3266         }
3267 }
3268 std::string Server::getBuiltinLuaPath()
3269 {
3270         return porting::path_share + DIR_DELIM + "builtin";
3271 }
3272
3273 v3f findSpawnPos(ServerMap &map)
3274 {
3275         //return v3f(50,50,50)*BS;
3276
3277         v3s16 nodepos;
3278
3279 #if 0
3280         nodepos = v2s16(0,0);
3281         groundheight = 20;
3282 #endif
3283
3284 #if 1
3285         s16 water_level = map.getWaterLevel();
3286
3287         // Try to find a good place a few times
3288         for(s32 i=0; i<1000; i++)
3289         {
3290                 s32 range = 1 + i;
3291                 // We're going to try to throw the player to this position
3292                 v2s16 nodepos2d = v2s16(
3293                                 -range + (myrand() % (range * 2)),
3294                                 -range + (myrand() % (range * 2)));
3295
3296                 // Get ground height at point
3297                 s16 groundheight = map.findGroundLevel(nodepos2d);
3298                 if (groundheight <= water_level) // Don't go underwater
3299                         continue;
3300                 if (groundheight > water_level + 6) // Don't go to high places
3301                         continue;
3302
3303                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
3304                 bool is_good = false;
3305                 s32 air_count = 0;
3306                 for (s32 i = 0; i < 10; i++) {
3307                         v3s16 blockpos = getNodeBlockPos(nodepos);
3308                         map.emergeBlock(blockpos, true);
3309                         content_t c = map.getNodeNoEx(nodepos).getContent();
3310                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3311                                 air_count++;
3312                                 if (air_count >= 2){
3313                                         is_good = true;
3314                                         break;
3315                                 }
3316                         }
3317                         nodepos.Y++;
3318                 }
3319                 if(is_good){
3320                         // Found a good place
3321                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
3322                         break;
3323                 }
3324         }
3325 #endif
3326
3327         return intToFloat(nodepos, BS);
3328 }
3329
3330 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
3331 {
3332         bool newplayer = false;
3333
3334         /*
3335                 Try to get an existing player
3336         */
3337         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3338
3339         // If player is already connected, cancel
3340         if(player != NULL && player->peer_id != 0)
3341         {
3342                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3343                 return NULL;
3344         }
3345
3346         /*
3347                 If player with the wanted peer_id already exists, cancel.
3348         */
3349         if(m_env->getPlayer(peer_id) != NULL)
3350         {
3351                 infostream<<"emergePlayer(): Player with wrong name but same"
3352                                 " peer_id already exists"<<std::endl;
3353                 return NULL;
3354         }
3355
3356         // Load player if it isn't already loaded
3357         if (!player) {
3358                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3359         }
3360
3361         // Create player if it doesn't exist
3362         if (!player) {
3363                 newplayer = true;
3364                 player = new RemotePlayer(this, name);
3365                 // Set player position
3366                 infostream<<"Server: Finding spawn place for player \""
3367                                 <<name<<"\""<<std::endl;
3368                 v3f pos = findSpawnPos(m_env->getServerMap());
3369                 player->setPosition(pos);
3370
3371                 // Make sure the player is saved
3372                 player->setModified(true);
3373
3374                 // Add player to environment
3375                 m_env->addPlayer(player);
3376         }
3377
3378         // Create a new player active object
3379         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3380                         getPlayerEffectivePrivs(player->getName()),
3381                         isSingleplayer());
3382
3383         /* Clean up old HUD elements from previous sessions */
3384         player->clearHud();
3385
3386         /* Add object to environment */
3387         m_env->addActiveObject(playersao);
3388
3389         /* Run scripts */
3390         if (newplayer) {
3391                 m_script->on_newplayer(playersao);
3392         }
3393
3394         return playersao;
3395 }
3396
3397 void dedicated_server_loop(Server &server, bool &kill)
3398 {
3399         DSTACK(__FUNCTION_NAME);
3400
3401         verbosestream<<"dedicated_server_loop()"<<std::endl;
3402
3403         IntervalLimiter m_profiler_interval;
3404
3405         for(;;)
3406         {
3407                 float steplen = g_settings->getFloat("dedicated_server_step");
3408                 // This is kind of a hack but can be done like this
3409                 // because server.step() is very light
3410                 {
3411                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3412                         sleep_ms((int)(steplen*1000.0));
3413                 }
3414                 server.step(steplen);
3415
3416                 if(server.getShutdownRequested() || kill)
3417                 {
3418                         infostream<<"Dedicated server quitting"<<std::endl;
3419 #if USE_CURL
3420                         if(g_settings->getBool("server_announce"))
3421                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3422 #endif
3423                         break;
3424                 }
3425
3426                 /*
3427                         Profiler
3428                 */
3429                 float profiler_print_interval =
3430                                 g_settings->getFloat("profiler_print_interval");
3431                 if(profiler_print_interval != 0)
3432                 {
3433                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3434                         {
3435                                 infostream<<"Profiler:"<<std::endl;
3436                                 g_profiler->print(infostream);
3437                                 g_profiler->clear();
3438                         }
3439                 }
3440         }
3441 }
3442
3443