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