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