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