Performance improvement: Use std::list instead of std::vector for request_media,...
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "jthread/jmutexautolock.h"
30 #include "main.h"
31 #include "constants.h"
32 #include "voxel.h"
33 #include "config.h"
34 #include "version.h"
35 #include "filesys.h"
36 #include "mapblock.h"
37 #include "serverobject.h"
38 #include "genericobject.h"
39 #include "settings.h"
40 #include "profiler.h"
41 #include "log.h"
42 #include "scripting_game.h"
43 #include "nodedef.h"
44 #include "itemdef.h"
45 #include "craftdef.h"
46 #include "emerge.h"
47 #include "mapgen.h"
48 #include "mg_biome.h"
49 #include "content_mapnode.h"
50 #include "content_nodemeta.h"
51 #include "content_abm.h"
52 #include "content_sao.h"
53 #include "mods.h"
54 #include "sound.h" // dummySoundManager
55 #include "event_manager.h"
56 #include "serverlist.h"
57 #include "util/string.h"
58 #include "util/mathconstants.h"
59 #include "rollback.h"
60 #include "util/serialize.h"
61 #include "util/thread.h"
62 #include "defaultsettings.h"
63 #include "util/base64.h"
64 #include "util/sha1.h"
65 #include "util/hex.h"
66
67 class ClientNotFoundException : public BaseException
68 {
69 public:
70         ClientNotFoundException(const char *s):
71                 BaseException(s)
72         {}
73 };
74
75 class ServerThread : public JThread
76 {
77         Server *m_server;
78
79 public:
80
81         ServerThread(Server *server):
82                 JThread(),
83                 m_server(server)
84         {
85         }
86
87         void * Thread();
88 };
89
90 void * ServerThread::Thread()
91 {
92         log_register_thread("ServerThread");
93
94         DSTACK(__FUNCTION_NAME);
95         BEGIN_DEBUG_EXCEPTION_HANDLER
96
97         m_server->AsyncRunStep(true);
98
99         ThreadStarted();
100
101         porting::setThreadName("ServerThread");
102
103         while(!StopRequested())
104         {
105                 try{
106                         //TimeTaker timer("AsyncRunStep() + Receive()");
107
108                         m_server->AsyncRunStep();
109
110                         m_server->Receive();
111
112                 }
113                 catch(con::NoIncomingDataException &e)
114                 {
115                 }
116                 catch(con::PeerNotFoundException &e)
117                 {
118                         infostream<<"Server: PeerNotFoundException"<<std::endl;
119                 }
120                 catch(ClientNotFoundException &e)
121                 {
122                 }
123                 catch(con::ConnectionBindFailed &e)
124                 {
125                         m_server->setAsyncFatalError(e.what());
126                 }
127                 catch(LuaError &e)
128                 {
129                         m_server->setAsyncFatalError(e.what());
130                 }
131         }
132
133         END_DEBUG_EXCEPTION_HANDLER(errorstream)
134
135         return NULL;
136 }
137
138 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
139 {
140         if(pos_exists) *pos_exists = false;
141         switch(type){
142         case SSP_LOCAL:
143                 return v3f(0,0,0);
144         case SSP_POSITIONAL:
145                 if(pos_exists) *pos_exists = true;
146                 return pos;
147         case SSP_OBJECT: {
148                 if(object == 0)
149                         return v3f(0,0,0);
150                 ServerActiveObject *sao = env->getActiveObject(object);
151                 if(!sao)
152                         return v3f(0,0,0);
153                 if(pos_exists) *pos_exists = true;
154                 return sao->getBasePosition(); }
155         }
156         return v3f(0,0,0);
157 }
158
159
160
161 /*
162         Server
163 */
164
165 Server::Server(
166                 const std::string &path_world,
167                 const SubgameSpec &gamespec,
168                 bool simple_singleplayer_mode,
169                 bool ipv6
170         ):
171         m_path_world(path_world),
172         m_gamespec(gamespec),
173         m_simple_singleplayer_mode(simple_singleplayer_mode),
174         m_async_fatal_error(""),
175         m_env(NULL),
176         m_con(PROTOCOL_ID,
177                         512,
178                         CONNECTION_TIMEOUT,
179                         ipv6,
180                         this),
181         m_banmanager(NULL),
182         m_rollback(NULL),
183         m_enable_rollback_recording(false),
184         m_emerge(NULL),
185         m_script(NULL),
186         m_itemdef(createItemDefManager()),
187         m_nodedef(createNodeDefManager()),
188         m_craftdef(createCraftDefManager()),
189         m_event(new EventManager()),
190         m_thread(NULL),
191         m_time_of_day_send_timer(0),
192         m_uptime(0),
193         m_clients(&m_con),
194         m_shutdown_requested(false),
195         m_ignore_map_edit_events(false),
196         m_ignore_map_edit_events_peer_id(0),
197         m_next_sound_id(0)
198
199 {
200         m_liquid_transform_timer = 0.0;
201         m_liquid_transform_every = 1.0;
202         m_print_info_timer = 0.0;
203         m_masterserver_timer = 0.0;
204         m_objectdata_timer = 0.0;
205         m_emergethread_trigger_timer = 0.0;
206         m_savemap_timer = 0.0;
207
208         m_step_dtime = 0.0;
209         m_lag = g_settings->getFloat("dedicated_server_step");
210
211         if(path_world == "")
212                 throw ServerError("Supplied empty world path");
213
214         if(!gamespec.isValid())
215                 throw ServerError("Supplied invalid gamespec");
216
217         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
218         if(m_simple_singleplayer_mode)
219                 infostream<<" in simple singleplayer mode"<<std::endl;
220         else
221                 infostream<<std::endl;
222         infostream<<"- world:  "<<m_path_world<<std::endl;
223         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
224
225         // Initialize default settings and override defaults with those provided
226         // by the game
227         set_default_settings(g_settings);
228         Settings gamedefaults;
229         getGameMinetestConfig(gamespec.path, gamedefaults);
230         override_default_settings(g_settings, &gamedefaults);
231
232         // Create server thread
233         m_thread = new ServerThread(this);
234
235         // Create emerge manager
236         m_emerge = new EmergeManager(this);
237
238         // Create world if it doesn't exist
239         if(!initializeWorld(m_path_world, m_gamespec.id))
240                 throw ServerError("Failed to initialize world");
241
242         // Create ban manager
243         std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
244         m_banmanager = new BanManager(ban_path);
245
246         ModConfiguration modconf(m_path_world);
247         m_mods = modconf.getMods();
248         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
249         // complain about mods with unsatisfied dependencies
250         if(!modconf.isConsistent())
251         {
252                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
253                         it != unsatisfied_mods.end(); ++it)
254                 {
255                         ModSpec mod = *it;
256                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
257                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
258                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
259                                 errorstream << " \"" << *dep_it << "\"";
260                         errorstream << std::endl;
261                 }
262         }
263
264         Settings worldmt_settings;
265         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
266         worldmt_settings.readConfigFile(worldmt.c_str());
267         std::vector<std::string> names = worldmt_settings.getNames();
268         std::set<std::string> load_mod_names;
269         for(std::vector<std::string>::iterator it = names.begin();
270                 it != names.end(); ++it)
271         {
272                 std::string name = *it;
273                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
274                         load_mod_names.insert(name.substr(9));
275         }
276         // complain about mods declared to be loaded, but not found
277         for(std::vector<ModSpec>::iterator it = m_mods.begin();
278                         it != m_mods.end(); ++it)
279                 load_mod_names.erase((*it).name);
280         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
281                         it != unsatisfied_mods.end(); ++it)
282                 load_mod_names.erase((*it).name);
283         if(!load_mod_names.empty())
284         {
285                 errorstream << "The following mods could not be found:";
286                 for(std::set<std::string>::iterator it = load_mod_names.begin();
287                         it != load_mod_names.end(); ++it)
288                         errorstream << " \"" << (*it) << "\"";
289                 errorstream << std::endl;
290         }
291
292         // Lock environment
293         JMutexAutoLock envlock(m_env_mutex);
294
295         // Load mapgen params from Settings
296         m_emerge->loadMapgenParams();
297
298         // Create the Map (loads map_meta.txt, overriding configured mapgen params)
299         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
300
301         // Initialize scripting
302         infostream<<"Server: Initializing Lua"<<std::endl;
303
304         m_script = new GameScripting(this);
305
306         std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
307
308         if (!m_script->loadScript(scriptpath))
309                 throw ModError("Failed to load and run " + scriptpath);
310
311         // Print 'em
312         infostream<<"Server: Loading mods: ";
313         for(std::vector<ModSpec>::iterator i = m_mods.begin();
314                         i != m_mods.end(); i++){
315                 const ModSpec &mod = *i;
316                 infostream<<mod.name<<" ";
317         }
318         infostream<<std::endl;
319         // Load and run "mod" scripts
320         for(std::vector<ModSpec>::iterator i = m_mods.begin();
321                         i != m_mods.end(); i++){
322                 const ModSpec &mod = *i;
323                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
324                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
325                                 <<scriptpath<<"\"]"<<std::endl;
326                 bool success = m_script->loadMod(scriptpath, mod.name);
327                 if(!success){
328                         errorstream<<"Server: Failed to load and run "
329                                         <<scriptpath<<std::endl;
330                         throw ModError("Failed to load and run "+scriptpath);
331                 }
332         }
333
334         // Read Textures and calculate sha1 sums
335         fillMediaCache();
336
337         // Apply item aliases in the node definition manager
338         m_nodedef->updateAliases(m_itemdef);
339
340         m_nodedef->setNodeRegistrationStatus(true);
341
342         // Perform pending node name resolutions
343         m_nodedef->runNodeResolverCallbacks();
344
345         // Initialize Environment
346         m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
347
348         m_clients.setEnv(m_env);
349
350         // Initialize mapgens
351         m_emerge->initMapgens();
352
353         m_enable_rollback_recording = g_settings->getBool("enable_rollback_recording");
354         if (m_enable_rollback_recording) {
355                 // Create rollback manager
356                 m_rollback = new RollbackManager(m_path_world, this);
357         }
358
359         // Give environment reference to scripting api
360         m_script->initializeEnvironment(m_env);
361
362         // Register us to receive map edit events
363         servermap->addEventReceiver(this);
364
365         // If file exists, load environment metadata
366         if(fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt"))
367         {
368                 infostream<<"Server: Loading environment metadata"<<std::endl;
369                 m_env->loadMeta();
370         }
371
372         // Add some test ActiveBlockModifiers to environment
373         add_legacy_abms(m_env, m_nodedef);
374
375         m_liquid_transform_every = g_settings->getFloat("liquid_update");
376 }
377
378 Server::~Server()
379 {
380         infostream<<"Server destructing"<<std::endl;
381
382         // Send shutdown message
383         SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
384
385         {
386                 JMutexAutoLock envlock(m_env_mutex);
387
388                 // Execute script shutdown hooks
389                 m_script->on_shutdown();
390
391                 infostream<<"Server: Saving players"<<std::endl;
392                 m_env->saveLoadedPlayers();
393
394                 infostream<<"Server: Saving environment metadata"<<std::endl;
395                 m_env->saveMeta();
396         }
397
398         // Stop threads
399         stop();
400         delete m_thread;
401
402         // stop all emerge threads before deleting players that may have
403         // requested blocks to be emerged
404         m_emerge->stopThreads();
405
406         // Delete things in the reverse order of creation
407         delete m_env;
408
409         // N.B. the EmergeManager should be deleted after the Environment since Map
410         // depends on EmergeManager to write its current params to the map meta
411         delete m_emerge;
412         delete m_rollback;
413         delete m_banmanager;
414         delete m_event;
415         delete m_itemdef;
416         delete m_nodedef;
417         delete m_craftdef;
418
419         // Deinitialize scripting
420         infostream<<"Server: Deinitializing scripting"<<std::endl;
421         delete m_script;
422
423         // Delete detached inventories
424         for (std::map<std::string, Inventory*>::iterator
425                         i = m_detached_inventories.begin();
426                         i != m_detached_inventories.end(); i++) {
427                 delete i->second;
428         }
429 }
430
431 void Server::start(Address bind_addr)
432 {
433         DSTACK(__FUNCTION_NAME);
434
435         m_bind_addr = bind_addr;
436
437         infostream<<"Starting server on "
438                         << bind_addr.serializeString() <<"..."<<std::endl;
439
440         // Stop thread if already running
441         m_thread->Stop();
442
443         // Initialize connection
444         m_con.SetTimeoutMs(30);
445         m_con.Serve(bind_addr);
446
447         // Start thread
448         m_thread->Start();
449
450         // ASCII art for the win!
451         actionstream
452         <<"        .__               __                   __   "<<std::endl
453         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
454         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
455         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
456         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
457         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
458         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
459         actionstream<<"Server for gameid=\""<<m_gamespec.id
460                         <<"\" listening on "<<bind_addr.serializeString()<<":"
461                         <<bind_addr.getPort() << "."<<std::endl;
462 }
463
464 void Server::stop()
465 {
466         DSTACK(__FUNCTION_NAME);
467
468         infostream<<"Server: Stopping and waiting threads"<<std::endl;
469
470         // Stop threads (set run=false first so both start stopping)
471         m_thread->Stop();
472         //m_emergethread.setRun(false);
473         m_thread->Wait();
474         //m_emergethread.stop();
475
476         infostream<<"Server: Threads stopped"<<std::endl;
477 }
478
479 void Server::step(float dtime)
480 {
481         DSTACK(__FUNCTION_NAME);
482         // Limit a bit
483         if(dtime > 2.0)
484                 dtime = 2.0;
485         {
486                 JMutexAutoLock lock(m_step_dtime_mutex);
487                 m_step_dtime += dtime;
488         }
489         // Throw if fatal error occurred in thread
490         std::string async_err = m_async_fatal_error.get();
491         if(async_err != ""){
492                 throw ServerError(async_err);
493         }
494 }
495
496 void Server::AsyncRunStep(bool initial_step)
497 {
498         DSTACK(__FUNCTION_NAME);
499
500         g_profiler->add("Server::AsyncRunStep (num)", 1);
501
502         float dtime;
503         {
504                 JMutexAutoLock lock1(m_step_dtime_mutex);
505                 dtime = m_step_dtime;
506         }
507
508         {
509                 // Send blocks to clients
510                 SendBlocks(dtime);
511         }
512
513         if((dtime < 0.001) && (initial_step == false))
514                 return;
515
516         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
517
518         //infostream<<"Server steps "<<dtime<<std::endl;
519         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
520
521         {
522                 JMutexAutoLock lock1(m_step_dtime_mutex);
523                 m_step_dtime -= dtime;
524         }
525
526         /*
527                 Update uptime
528         */
529         {
530                 m_uptime.set(m_uptime.get() + dtime);
531         }
532
533         handlePeerChanges();
534
535         /*
536                 Update time of day and overall game time
537         */
538         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.front();
910                         m_unsent_map_edit_queue.pop();
911
912                         // Players far away from the change are stored here.
913                         // Instead of sending the changes, MapBlocks are set not sent
914                         // for them.
915                         std::list<u16> far_players;
916
917                         if(event->type == MEET_ADDNODE || event->type == MEET_SWAPNODE)
918                         {
919                                 //infostream<<"Server: MEET_ADDNODE"<<std::endl;
920                                 prof.add("MEET_ADDNODE", 1);
921                                 if(disable_single_change_sending)
922                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
923                                                         &far_players, 5, event->type == MEET_ADDNODE);
924                                 else
925                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
926                                                         &far_players, 30, event->type == MEET_ADDNODE);
927                         }
928                         else if(event->type == MEET_REMOVENODE)
929                         {
930                                 //infostream<<"Server: MEET_REMOVENODE"<<std::endl;
931                                 prof.add("MEET_REMOVENODE", 1);
932                                 if(disable_single_change_sending)
933                                         sendRemoveNode(event->p, event->already_known_by_peer,
934                                                         &far_players, 5);
935                                 else
936                                         sendRemoveNode(event->p, event->already_known_by_peer,
937                                                         &far_players, 30);
938                         }
939                         else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
940                         {
941                                 infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
942                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
943                                 setBlockNotSent(event->p);
944                         }
945                         else if(event->type == MEET_OTHER)
946                         {
947                                 infostream<<"Server: MEET_OTHER"<<std::endl;
948                                 prof.add("MEET_OTHER", 1);
949                                 for(std::set<v3s16>::iterator
950                                                 i = event->modified_blocks.begin();
951                                                 i != event->modified_blocks.end(); ++i)
952                                 {
953                                         setBlockNotSent(*i);
954                                 }
955                         }
956                         else
957                         {
958                                 prof.add("unknown", 1);
959                                 infostream<<"WARNING: Server: Unknown MapEditEvent "
960                                                 <<((u32)event->type)<<std::endl;
961                         }
962
963                         /*
964                                 Set blocks not sent to far players
965                         */
966                         if(!far_players.empty())
967                         {
968                                 // Convert list format to that wanted by SetBlocksNotSent
969                                 std::map<v3s16, MapBlock*> modified_blocks2;
970                                 for(std::set<v3s16>::iterator
971                                                 i = event->modified_blocks.begin();
972                                                 i != event->modified_blocks.end(); ++i)
973                                 {
974                                         modified_blocks2[*i] =
975                                                         m_env->getMap().getBlockNoCreateNoEx(*i);
976                                 }
977                                 // Set blocks not sent
978                                 for(std::list<u16>::iterator
979                                                 i = far_players.begin();
980                                                 i != far_players.end(); ++i)
981                                 {
982                                         u16 peer_id = *i;
983                                         RemoteClient *client = getClient(peer_id);
984                                         if(client==NULL)
985                                                 continue;
986                                         client->SetBlocksNotSent(modified_blocks2);
987                                 }
988                         }
989
990                         delete event;
991
992                         /*// Don't send too many at a time
993                         count++;
994                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
995                                 break;*/
996                 }
997
998                 if(event_count >= 5){
999                         infostream<<"Server: MapEditEvents:"<<std::endl;
1000                         prof.print(infostream);
1001                 } else if(event_count != 0){
1002                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
1003                         prof.print(verbosestream);
1004                 }
1005
1006         }
1007
1008         /*
1009                 Trigger emergethread (it somehow gets to a non-triggered but
1010                 bysy state sometimes)
1011         */
1012         {
1013                 float &counter = m_emergethread_trigger_timer;
1014                 counter += dtime;
1015                 if(counter >= 2.0)
1016                 {
1017                         counter = 0.0;
1018
1019                         m_emerge->startThreads();
1020                 }
1021         }
1022
1023         // Save map, players and auth stuff
1024         {
1025                 float &counter = m_savemap_timer;
1026                 counter += dtime;
1027                 if(counter >= g_settings->getFloat("server_map_save_interval"))
1028                 {
1029                         counter = 0.0;
1030                         JMutexAutoLock lock(m_env_mutex);
1031
1032                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1033
1034                         // Save ban file
1035                         if (m_banmanager->isModified()) {
1036                                 m_banmanager->save();
1037                         }
1038
1039                         // Save changed parts of map
1040                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1041
1042                         // Save players
1043                         m_env->saveLoadedPlayers();
1044
1045                         // Save environment metadata
1046                         m_env->saveMeta();
1047                 }
1048         }
1049 }
1050
1051 void Server::Receive()
1052 {
1053         DSTACK(__FUNCTION_NAME);
1054         SharedBuffer<u8> data;
1055         u16 peer_id;
1056         u32 datasize;
1057         try {
1058                 datasize = m_con.Receive(peer_id,data);
1059                 ProcessData(*data, datasize, peer_id);
1060         }
1061         catch(con::InvalidIncomingDataException &e) {
1062                 infostream<<"Server::Receive(): "
1063                                 "InvalidIncomingDataException: what()="
1064                                 <<e.what()<<std::endl;
1065         }
1066         catch(SerializationError &e) {
1067                 infostream<<"Server::Receive(): "
1068                                 "SerializationError: what()="
1069                                 <<e.what()<<std::endl;
1070         }
1071         catch(ClientStateError &e) {
1072                 errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1073                 DenyAccess(peer_id, L"Your client sent something server didn't expect."
1074                                 L"Try reconnecting or updating your client");
1075         }
1076         catch(con::PeerNotFoundException &e) {
1077                 // Do nothing
1078         }
1079 }
1080
1081 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1082 {
1083         std::string playername = "";
1084         PlayerSAO *playersao = NULL;
1085         m_clients.Lock();
1086         try {
1087                 RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
1088                 if (client != NULL) {
1089                         playername = client->getName();
1090                         playersao = emergePlayer(playername.c_str(), peer_id);
1091                 }
1092         } catch (std::exception &e) {
1093                 m_clients.Unlock();
1094                 throw;
1095         }
1096         m_clients.Unlock();
1097
1098         RemotePlayer *player =
1099                 static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
1100
1101         // If failed, cancel
1102         if((playersao == NULL) || (player == NULL)) {
1103                 if(player && player->peer_id != 0) {
1104                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1105                                         <<" (player allocated to an another client)"<<std::endl;
1106                         DenyAccess(peer_id, L"Another client is connected with this "
1107                                         L"name. If your client closed unexpectedly, try again in "
1108                                         L"a minute.");
1109                 } else {
1110                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1111                                         <<std::endl;
1112                         DenyAccess(peer_id, L"Could not allocate player.");
1113                 }
1114                 return NULL;
1115         }
1116
1117         /*
1118                 Send complete position information
1119         */
1120         SendMovePlayer(peer_id);
1121
1122         // Send privileges
1123         SendPlayerPrivileges(peer_id);
1124
1125         // Send inventory formspec
1126         SendPlayerInventoryFormspec(peer_id);
1127
1128         // Send inventory
1129         SendInventory(playersao);
1130
1131         // Send HP
1132         if(g_settings->getBool("enable_damage"))
1133                 SendPlayerHP(peer_id);
1134
1135         // Send Breath
1136         SendPlayerBreath(peer_id);
1137
1138         // Show death screen if necessary
1139         if(player->hp == 0)
1140                 SendDeathscreen(peer_id, false, v3f(0,0,0));
1141
1142         // Note things in chat if not in simple singleplayer mode
1143         if(!m_simple_singleplayer_mode) {
1144                 // Send information about server to player in chat
1145                 SendChatMessage(peer_id, getStatusString());
1146
1147                 // Send information about joining in chat
1148                 {
1149                         std::wstring name = L"unknown";
1150                         Player *player = m_env->getPlayer(peer_id);
1151                         if(player != NULL)
1152                                 name = narrow_to_wide(player->getName());
1153
1154                         std::wstring message;
1155                         message += L"*** ";
1156                         message += name;
1157                         message += L" joined the game.";
1158                         SendChatMessage(PEER_ID_INEXISTENT,message);
1159                 }
1160         }
1161         Address addr = getPeerAddress(player->peer_id);
1162         std::string ip_str = addr.serializeString();
1163         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1164         /*
1165                 Print out action
1166         */
1167         {
1168                 std::vector<std::string> names = m_clients.getPlayerNames();
1169
1170                 actionstream<<player->getName() <<" joins game. List of players: ";
1171
1172                 for (std::vector<std::string>::iterator i = names.begin();
1173                                 i != names.end(); i++) {
1174                         actionstream << *i << " ";
1175                 }
1176
1177                 actionstream << player->getName() <<std::endl;
1178         }
1179         return playersao;
1180 }
1181
1182 inline void Server::handleCommand(NetworkPacket* pkt)
1183 {
1184         const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
1185         (this->*opHandle.handler)(pkt);
1186 }
1187
1188 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1189 {
1190         DSTACK(__FUNCTION_NAME);
1191         // Environment is locked first.
1192         JMutexAutoLock envlock(m_env_mutex);
1193
1194         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1195
1196         try {
1197                 Address address = getPeerAddress(peer_id);
1198                 std::string addr_s = address.serializeString();
1199
1200                 if(m_banmanager->isIpBanned(addr_s)) {
1201                         std::string ban_name = m_banmanager->getBanName(addr_s);
1202                         infostream << "Server: A banned client tried to connect from "
1203                                         << addr_s << "; banned name was "
1204                                         << ban_name << std::endl;
1205                         // This actually doesn't seem to transfer to the client
1206                         DenyAccess(peer_id, L"Your ip is banned. Banned name was "
1207                                         + narrow_to_wide(ban_name));
1208                         return;
1209                 }
1210         }
1211         catch(con::PeerNotFoundException &e) {
1212                 /*
1213                  * no peer for this packet found
1214                  * most common reason is peer timeout, e.g. peer didn't
1215                  * respond for some time, your server was overloaded or
1216                  * things like that.
1217                  */
1218                 infostream << "Server::ProcessData(): Cancelling: peer "
1219                                 << peer_id << " not found" << std::endl;
1220                 return;
1221         }
1222
1223         try {
1224                 if(datasize < 2)
1225                         return;
1226
1227                 NetworkPacket* pkt = new NetworkPacket(data, datasize, peer_id);
1228
1229                 ToServerCommand command = (ToServerCommand) pkt->getCommand();
1230
1231                 // Command must be handled into ToServerCommandHandler
1232                 if (command >= TOSERVER_NUM_MSG_TYPES) {
1233                         infostream << "Server: Ignoring unknown command "
1234                                          << command << std::endl;
1235                 }
1236
1237                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1238                         handleCommand(pkt);
1239                         delete pkt;
1240                         return;
1241                 }
1242
1243                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1244
1245                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1246                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1247                                         " serialization format invalid or not initialized."
1248                                         " Skipping incoming command=" << command << std::endl;
1249
1250                         delete pkt;
1251                         return;
1252                 }
1253
1254                 /* Handle commands related to client startup */
1255                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1256                         handleCommand(pkt);
1257                         delete pkt;
1258                         return;
1259                 }
1260
1261                 if (m_clients.getClientState(peer_id) < CS_Active) {
1262                         if (command == TOSERVER_PLAYERPOS) return;
1263
1264                         errorstream << "Got packet command: " << command << " for peer id "
1265                                         << peer_id << " but client isn't active yet. Dropping packet "
1266                                         << std::endl;
1267
1268                         delete pkt;
1269                         return;
1270                 }
1271
1272                 handleCommand(pkt);
1273                 delete pkt;
1274
1275         }
1276         catch(SendFailedException &e) {
1277                 errorstream << "Server::ProcessData(): SendFailedException: "
1278                                 << "what=" << e.what()
1279                                 << std::endl;
1280         }
1281 }
1282
1283 void Server::setTimeOfDay(u32 time)
1284 {
1285         m_env->setTimeOfDay(time);
1286         m_time_of_day_send_timer = 0;
1287 }
1288
1289 void Server::onMapEditEvent(MapEditEvent *event)
1290 {
1291         if(m_ignore_map_edit_events)
1292                 return;
1293         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1294                 return;
1295         MapEditEvent *e = event->clone();
1296         m_unsent_map_edit_queue.push(e);
1297 }
1298
1299 Inventory* Server::getInventory(const InventoryLocation &loc)
1300 {
1301         switch (loc.type) {
1302         case InventoryLocation::UNDEFINED:
1303         case InventoryLocation::CURRENT_PLAYER:
1304                 break;
1305         case InventoryLocation::PLAYER:
1306         {
1307                 Player *player = m_env->getPlayer(loc.name.c_str());
1308                 if(!player)
1309                         return NULL;
1310                 PlayerSAO *playersao = player->getPlayerSAO();
1311                 if(!playersao)
1312                         return NULL;
1313                 return playersao->getInventory();
1314         }
1315                 break;
1316         case InventoryLocation::NODEMETA:
1317         {
1318                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1319                 if(!meta)
1320                         return NULL;
1321                 return meta->getInventory();
1322         }
1323                 break;
1324         case InventoryLocation::DETACHED:
1325         {
1326                 if(m_detached_inventories.count(loc.name) == 0)
1327                         return NULL;
1328                 return m_detached_inventories[loc.name];
1329         }
1330                 break;
1331         default:
1332                 assert(0);
1333                 break;
1334         }
1335         return NULL;
1336 }
1337 void Server::setInventoryModified(const InventoryLocation &loc)
1338 {
1339         switch(loc.type){
1340         case InventoryLocation::UNDEFINED:
1341                 break;
1342         case InventoryLocation::PLAYER:
1343         {
1344                 Player *player = m_env->getPlayer(loc.name.c_str());
1345                 if(!player)
1346                         return;
1347                 PlayerSAO *playersao = player->getPlayerSAO();
1348                 if(!playersao)
1349                         return;
1350
1351                 SendInventory(playersao);
1352         }
1353                 break;
1354         case InventoryLocation::NODEMETA:
1355         {
1356                 v3s16 blockpos = getNodeBlockPos(loc.p);
1357
1358                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1359                 if(block)
1360                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1361
1362                 setBlockNotSent(blockpos);
1363         }
1364                 break;
1365         case InventoryLocation::DETACHED:
1366         {
1367                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1368         }
1369                 break;
1370         default:
1371                 assert(0);
1372                 break;
1373         }
1374 }
1375
1376 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1377 {
1378         std::vector<u16> clients = m_clients.getClientIDs();
1379         m_clients.Lock();
1380         // Set the modified blocks unsent for all the clients
1381         for (std::vector<u16>::iterator i = clients.begin();
1382                  i != clients.end(); ++i) {
1383                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1384                                 client->SetBlocksNotSent(block);
1385         }
1386         m_clients.Unlock();
1387 }
1388
1389 void Server::peerAdded(con::Peer *peer)
1390 {
1391         DSTACK(__FUNCTION_NAME);
1392         verbosestream<<"Server::peerAdded(): peer->id="
1393                         <<peer->id<<std::endl;
1394
1395         con::PeerChange c;
1396         c.type = con::PEER_ADDED;
1397         c.peer_id = peer->id;
1398         c.timeout = false;
1399         m_peer_change_queue.push(c);
1400 }
1401
1402 void Server::deletingPeer(con::Peer *peer, bool timeout)
1403 {
1404         DSTACK(__FUNCTION_NAME);
1405         verbosestream<<"Server::deletingPeer(): peer->id="
1406                         <<peer->id<<", timeout="<<timeout<<std::endl;
1407
1408         m_clients.event(peer->id, CSE_Disconnect);
1409         con::PeerChange c;
1410         c.type = con::PEER_REMOVED;
1411         c.peer_id = peer->id;
1412         c.timeout = timeout;
1413         m_peer_change_queue.push(c);
1414 }
1415
1416 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1417 {
1418         *retval = m_con.getPeerStat(peer_id,type);
1419         if (*retval == -1) return false;
1420         return true;
1421 }
1422
1423 bool Server::getClientInfo(
1424                 u16          peer_id,
1425                 ClientState* state,
1426                 u32*         uptime,
1427                 u8*          ser_vers,
1428                 u16*         prot_vers,
1429                 u8*          major,
1430                 u8*          minor,
1431                 u8*          patch,
1432                 std::string* vers_string
1433         )
1434 {
1435         *state = m_clients.getClientState(peer_id);
1436         m_clients.Lock();
1437         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1438
1439         if (client == NULL) {
1440                 m_clients.Unlock();
1441                 return false;
1442         }
1443
1444         *uptime = client->uptime();
1445         *ser_vers = client->serialization_version;
1446         *prot_vers = client->net_proto_version;
1447
1448         *major = client->getMajor();
1449         *minor = client->getMinor();
1450         *patch = client->getPatch();
1451         *vers_string = client->getPatch();
1452
1453         m_clients.Unlock();
1454
1455         return true;
1456 }
1457
1458 void Server::handlePeerChanges()
1459 {
1460         while(m_peer_change_queue.size() > 0)
1461         {
1462                 con::PeerChange c = m_peer_change_queue.front();
1463                 m_peer_change_queue.pop();
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(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::vector<u16> clients = m_clients.getClientIDs();
1958
1959                 for(std::vector<u16>::iterator
1960                                 i = clients.begin(); i != clients.end(); ++i) {
1961                         Player *player = m_env->getPlayer(*i);
1962                         if(!player)
1963                                 continue;
1964
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
1974         if(dst_clients.empty())
1975                 return -1;
1976
1977         // Create the sound
1978         s32 id = m_next_sound_id++;
1979         // The sound will exist as a reference in m_playing_sounds
1980         m_playing_sounds[id] = ServerPlayingSound();
1981         ServerPlayingSound &psound = m_playing_sounds[id];
1982         psound.params = params;
1983         for(std::list<u16>::iterator i = dst_clients.begin();
1984                         i != dst_clients.end(); i++)
1985                 psound.clients.insert(*i);
1986
1987         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_PLAY_SOUND, 0);
1988         *pkt << id << spec.name << (float) (spec.gain * params.gain)
1989                         << (u8) params.type << pos << params.object << params.loop;
1990         for(std::list<u16>::iterator i = dst_clients.begin();
1991                         i != dst_clients.end(); i++) {
1992                 // Send as reliable
1993                 m_clients.send(*i, 0, pkt, true, false);
1994         }
1995         delete pkt;
1996         return id;
1997 }
1998 void Server::stopSound(s32 handle)
1999 {
2000         // Get sound reference
2001         std::map<s32, ServerPlayingSound>::iterator i =
2002                         m_playing_sounds.find(handle);
2003         if(i == m_playing_sounds.end())
2004                 return;
2005         ServerPlayingSound &psound = i->second;
2006
2007         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_STOP_SOUND, 4);
2008         *pkt << handle;
2009
2010         for(std::set<u16>::iterator i = psound.clients.begin();
2011                         i != psound.clients.end(); i++) {
2012                 // Send as reliable
2013                 m_clients.send(*i, 0, pkt, true, false);
2014         }
2015         delete pkt;
2016         // Remove sound reference
2017         m_playing_sounds.erase(i);
2018 }
2019
2020 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2021         std::list<u16> *far_players, float far_d_nodes)
2022 {
2023         float maxd = far_d_nodes*BS;
2024         v3f p_f = intToFloat(p, BS);
2025
2026         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_REMOVENODE, 6);
2027         *pkt << p;
2028
2029         std::vector<u16> clients = m_clients.getClientIDs();
2030         for(std::vector<u16>::iterator 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::vector<u16> clients = m_clients.getClientIDs();
2059         for(std::vector<u16>::iterator i = clients.begin();
2060                         i != clients.end(); ++i) {
2061
2062                 if(far_players) {
2063                         // Get player
2064                         if(Player *player = m_env->getPlayer(*i)) {
2065                                 // If player is far away, only set modified blocks not sent
2066                                 v3f player_pos = player->getPosition();
2067                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2068                                         far_players->push_back(*i);
2069                                         continue;
2070                                 }
2071                         }
2072                 }
2073
2074                 NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2075                 m_clients.Lock();
2076                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2077                 if (client != 0) {
2078                         *pkt << p << n.param0 << n.param1 << n.param2
2079                                         << (u8) (remove_metadata ? 0 : 1);
2080
2081                         if (!remove_metadata) {
2082                                 if (client->net_proto_version <= 21) {
2083                                         // Old clients always clear metadata; fix it
2084                                         // by sending the full block again.
2085                                         client->SetBlockNotSent(p);
2086                                 }
2087                         }
2088                 }
2089                 m_clients.Unlock();
2090
2091                 // Send as reliable
2092                 if (pkt->getSize() > 0)
2093                         m_clients.send(*i, 0, pkt, true);
2094         }
2095 }
2096
2097 void Server::setBlockNotSent(v3s16 p)
2098 {
2099         std::vector<u16> clients = m_clients.getClientIDs();
2100         m_clients.Lock();
2101         for(std::vector<u16>::iterator i = clients.begin();
2102                 i != clients.end(); ++i) {
2103                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2104                 client->SetBlockNotSent(p);
2105         }
2106         m_clients.Unlock();
2107 }
2108
2109 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2110 {
2111         DSTACK(__FUNCTION_NAME);
2112
2113         v3s16 p = block->getPos();
2114
2115         /*
2116                 Create a packet with the block in the right format
2117         */
2118
2119         std::ostringstream os(std::ios_base::binary);
2120         block->serialize(os, ver, false);
2121         block->serializeNetworkSpecific(os, net_proto_version);
2122         std::string s = os.str();
2123
2124         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_BLOCKDATA,
2125                 2 + 2 + 2 + 2 + s.size(), peer_id);
2126
2127         *pkt << p;
2128         pkt->putRawString(s.c_str(), s.size());
2129         Send(pkt);
2130 }
2131
2132 void Server::SendBlocks(float dtime)
2133 {
2134         DSTACK(__FUNCTION_NAME);
2135
2136         JMutexAutoLock envlock(m_env_mutex);
2137         //TODO check if one big lock could be faster then multiple small ones
2138
2139         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2140
2141         std::vector<PrioritySortedBlockTransfer> queue;
2142
2143         s32 total_sending = 0;
2144
2145         {
2146                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2147
2148                 std::vector<u16> clients = m_clients.getClientIDs();
2149
2150                 m_clients.Lock();
2151                 for(std::vector<u16>::iterator i = clients.begin();
2152                         i != clients.end(); ++i) {
2153                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2154
2155                         if (client == NULL)
2156                                 continue;
2157
2158                         total_sending += client->SendingCount();
2159                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2160                 }
2161                 m_clients.Unlock();
2162         }
2163
2164         // Sort.
2165         // Lowest priority number comes first.
2166         // Lowest is most important.
2167         std::sort(queue.begin(), queue.end());
2168
2169         m_clients.Lock();
2170         for(u32 i=0; i<queue.size(); i++)
2171         {
2172                 //TODO: Calculate limit dynamically
2173                 if(total_sending >= g_settings->getS32
2174                                 ("max_simultaneous_block_sends_server_total"))
2175                         break;
2176
2177                 PrioritySortedBlockTransfer q = queue[i];
2178
2179                 MapBlock *block = NULL;
2180                 try
2181                 {
2182                         block = m_env->getMap().getBlockNoCreate(q.pos);
2183                 }
2184                 catch(InvalidPositionException &e)
2185                 {
2186                         continue;
2187                 }
2188
2189                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2190
2191                 if(!client)
2192                         continue;
2193
2194                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2195
2196                 client->SentBlock(q.pos);
2197                 total_sending++;
2198         }
2199         m_clients.Unlock();
2200 }
2201
2202 void Server::fillMediaCache()
2203 {
2204         DSTACK(__FUNCTION_NAME);
2205
2206         infostream<<"Server: Calculating media file checksums"<<std::endl;
2207
2208         // Collect all media file paths
2209         std::list<std::string> paths;
2210         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2211                         i != m_mods.end(); i++){
2212                 const ModSpec &mod = *i;
2213                 paths.push_back(mod.path + DIR_DELIM + "textures");
2214                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2215                 paths.push_back(mod.path + DIR_DELIM + "media");
2216                 paths.push_back(mod.path + DIR_DELIM + "models");
2217         }
2218         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2219
2220         // Collect media file information from paths into cache
2221         for(std::list<std::string>::iterator i = paths.begin();
2222                         i != paths.end(); i++)
2223         {
2224                 std::string mediapath = *i;
2225                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2226                 for(u32 j=0; j<dirlist.size(); j++){
2227                         if(dirlist[j].dir) // Ignode dirs
2228                                 continue;
2229                         std::string filename = dirlist[j].name;
2230                         // If name contains illegal characters, ignore the file
2231                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
2232                                 infostream<<"Server: ignoring illegal file name: \""
2233                                                 <<filename<<"\""<<std::endl;
2234                                 continue;
2235                         }
2236                         // If name is not in a supported format, ignore it
2237                         const char *supported_ext[] = {
2238                                 ".png", ".jpg", ".bmp", ".tga",
2239                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2240                                 ".ogg",
2241                                 ".x", ".b3d", ".md2", ".obj",
2242                                 NULL
2243                         };
2244                         if(removeStringEnd(filename, supported_ext) == ""){
2245                                 infostream<<"Server: ignoring unsupported file extension: \""
2246                                                 <<filename<<"\""<<std::endl;
2247                                 continue;
2248                         }
2249                         // Ok, attempt to load the file and add to cache
2250                         std::string filepath = mediapath + DIR_DELIM + filename;
2251                         // Read data
2252                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2253                         if(fis.good() == false){
2254                                 errorstream<<"Server::fillMediaCache(): Could not open \""
2255                                                 <<filename<<"\" for reading"<<std::endl;
2256                                 continue;
2257                         }
2258                         std::ostringstream tmp_os(std::ios_base::binary);
2259                         bool bad = false;
2260                         for(;;){
2261                                 char buf[1024];
2262                                 fis.read(buf, 1024);
2263                                 std::streamsize len = fis.gcount();
2264                                 tmp_os.write(buf, len);
2265                                 if(fis.eof())
2266                                         break;
2267                                 if(!fis.good()){
2268                                         bad = true;
2269                                         break;
2270                                 }
2271                         }
2272                         if(bad){
2273                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2274                                                 <<filename<<"\""<<std::endl;
2275                                 continue;
2276                         }
2277                         if(tmp_os.str().length() == 0){
2278                                 errorstream<<"Server::fillMediaCache(): Empty file \""
2279                                                 <<filepath<<"\""<<std::endl;
2280                                 continue;
2281                         }
2282
2283                         SHA1 sha1;
2284                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2285
2286                         unsigned char *digest = sha1.getDigest();
2287                         std::string sha1_base64 = base64_encode(digest, 20);
2288                         std::string sha1_hex = hex_encode((char*)digest, 20);
2289                         free(digest);
2290
2291                         // Put in list
2292                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
2293                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
2294                 }
2295         }
2296 }
2297
2298 struct SendableMediaAnnouncement
2299 {
2300         std::string name;
2301         std::string sha1_digest;
2302
2303         SendableMediaAnnouncement(const std::string &name_="",
2304                                   const std::string &sha1_digest_=""):
2305                 name(name_),
2306                 sha1_digest(sha1_digest_)
2307         {}
2308 };
2309
2310 void Server::sendMediaAnnouncement(u16 peer_id)
2311 {
2312         DSTACK(__FUNCTION_NAME);
2313
2314         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
2315                         <<std::endl;
2316
2317         std::list<SendableMediaAnnouncement> file_announcements;
2318
2319         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
2320                         i != m_media.end(); i++){
2321                 // Put in list
2322                 file_announcements.push_back(
2323                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
2324         }
2325
2326         // Make packet
2327         std::ostringstream os(std::ios_base::binary);
2328
2329         /*
2330                 u32 number of files
2331                 for each texture {
2332                         u16 length of name
2333                         string name
2334                         u16 length of sha1_digest
2335                         string sha1_digest
2336                 }
2337         */
2338
2339         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2340         *pkt << (u16) file_announcements.size();
2341
2342         for(std::list<SendableMediaAnnouncement>::iterator
2343                         j = file_announcements.begin();
2344                         j != file_announcements.end(); ++j) {
2345                 *pkt << j->name << j->sha1_digest;
2346         }
2347
2348         *pkt << g_settings->get("remote_media");
2349         Send(pkt);
2350 }
2351
2352 struct SendableMedia
2353 {
2354         std::string name;
2355         std::string path;
2356         std::string data;
2357
2358         SendableMedia(const std::string &name_="", const std::string &path_="",
2359                       const std::string &data_=""):
2360                 name(name_),
2361                 path(path_),
2362                 data(data_)
2363         {}
2364 };
2365
2366 void Server::sendRequestedMedia(u16 peer_id,
2367                 const std::list<std::string> &tosend)
2368 {
2369         DSTACK(__FUNCTION_NAME);
2370
2371         verbosestream<<"Server::sendRequestedMedia(): "
2372                         <<"Sending files to client"<<std::endl;
2373
2374         /* Read files */
2375
2376         // Put 5kB in one bunch (this is not accurate)
2377         u32 bytes_per_bunch = 5000;
2378
2379         std::vector< std::list<SendableMedia> > file_bunches;
2380         file_bunches.push_back(std::list<SendableMedia>());
2381
2382         u32 file_size_bunch_total = 0;
2383
2384         for(std::list<std::string>::const_iterator i = tosend.begin();
2385                         i != tosend.end(); ++i)
2386         {
2387                 const std::string &name = *i;
2388
2389                 if(m_media.find(name) == m_media.end()) {
2390                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2391                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2392                         continue;
2393                 }
2394
2395                 //TODO get path + name
2396                 std::string tpath = m_media[name].path;
2397
2398                 // Read data
2399                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2400                 if(fis.good() == false){
2401                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2402                                         <<tpath<<"\" for reading"<<std::endl;
2403                         continue;
2404                 }
2405                 std::ostringstream tmp_os(std::ios_base::binary);
2406                 bool bad = false;
2407                 for(;;) {
2408                         char buf[1024];
2409                         fis.read(buf, 1024);
2410                         std::streamsize len = fis.gcount();
2411                         tmp_os.write(buf, len);
2412                         file_size_bunch_total += len;
2413                         if(fis.eof())
2414                                 break;
2415                         if(!fis.good()) {
2416                                 bad = true;
2417                                 break;
2418                         }
2419                 }
2420                 if(bad) {
2421                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2422                                         <<name<<"\""<<std::endl;
2423                         continue;
2424                 }
2425                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2426                                 <<tname<<"\""<<std::endl;*/
2427                 // Put in list
2428                 file_bunches[file_bunches.size()-1].push_back(
2429                                 SendableMedia(name, tpath, tmp_os.str()));
2430
2431                 // Start next bunch if got enough data
2432                 if(file_size_bunch_total >= bytes_per_bunch) {
2433                         file_bunches.push_back(std::list<SendableMedia>());
2434                         file_size_bunch_total = 0;
2435                 }
2436
2437         }
2438
2439         /* Create and send packets */
2440
2441         u16 num_bunches = file_bunches.size();
2442         for(u16 i = 0; i < num_bunches; i++) {
2443                 /*
2444                         u16 command
2445                         u16 total number of texture bunches
2446                         u16 index of this bunch
2447                         u32 number of files in this bunch
2448                         for each file {
2449                                 u16 length of name
2450                                 string name
2451                                 u32 length of data
2452                                 data
2453                         }
2454                 */
2455
2456                 NetworkPacket* pkt = new NetworkPacket(TOCLIENT_MEDIA, 0, peer_id);
2457                 *pkt << num_bunches << i << (u32) file_bunches[i].size();
2458
2459                 for(std::list<SendableMedia>::iterator
2460                                 j = file_bunches[i].begin();
2461                                 j != file_bunches[i].end(); ++j) {
2462                         *pkt << j->name;
2463                         pkt->putLongString(j->data);
2464                 }
2465
2466                 verbosestream << "Server::sendRequestedMedia(): bunch "
2467                                 << i << "/" << num_bunches
2468                                 << " files=" << file_bunches[i].size()
2469                                 << " size="  << pkt->getSize() << std::endl;
2470                 Send(pkt);
2471         }
2472 }
2473
2474 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2475 {
2476         if(m_detached_inventories.count(name) == 0) {
2477                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2478                 return;
2479         }
2480         Inventory *inv = m_detached_inventories[name];
2481         std::ostringstream os(std::ios_base::binary);
2482
2483         os << serializeString(name);
2484         inv->serialize(os);
2485
2486         // Make data buffer
2487         std::string s = os.str();
2488
2489         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2490         pkt->putRawString(s.c_str(), s.size());
2491
2492         if (peer_id != PEER_ID_INEXISTENT) {
2493                 Send(pkt);
2494         }
2495         else {
2496                 m_clients.sendToAll(0, pkt, true);
2497         }
2498 }
2499
2500 void Server::sendDetachedInventories(u16 peer_id)
2501 {
2502         DSTACK(__FUNCTION_NAME);
2503
2504         for(std::map<std::string, Inventory*>::iterator
2505                         i = m_detached_inventories.begin();
2506                         i != m_detached_inventories.end(); i++) {
2507                 const std::string &name = i->first;
2508                 //Inventory *inv = i->second;
2509                 sendDetachedInventory(name, peer_id);
2510         }
2511 }
2512
2513 /*
2514         Something random
2515 */
2516
2517 void Server::DiePlayer(u16 peer_id)
2518 {
2519         DSTACK(__FUNCTION_NAME);
2520
2521         PlayerSAO *playersao = getPlayerSAO(peer_id);
2522         assert(playersao);
2523
2524         infostream << "Server::DiePlayer(): Player "
2525                         << playersao->getPlayer()->getName()
2526                         << " dies" << std::endl;
2527
2528         playersao->setHP(0);
2529
2530         // Trigger scripted stuff
2531         m_script->on_dieplayer(playersao);
2532
2533         SendPlayerHP(peer_id);
2534         SendDeathscreen(peer_id, false, v3f(0,0,0));
2535 }
2536
2537 void Server::RespawnPlayer(u16 peer_id)
2538 {
2539         DSTACK(__FUNCTION_NAME);
2540
2541         PlayerSAO *playersao = getPlayerSAO(peer_id);
2542         assert(playersao);
2543
2544         infostream << "Server::RespawnPlayer(): Player "
2545                         << playersao->getPlayer()->getName()
2546                         << " respawns" << std::endl;
2547
2548         playersao->setHP(PLAYER_MAX_HP);
2549         playersao->setBreath(PLAYER_MAX_BREATH);
2550
2551         SendPlayerHP(peer_id);
2552         SendPlayerBreath(peer_id);
2553
2554         bool repositioned = m_script->on_respawnplayer(playersao);
2555         if(!repositioned){
2556                 v3f pos = findSpawnPos(m_env->getServerMap());
2557                 // setPos will send the new position to client
2558                 playersao->setPos(pos);
2559         }
2560 }
2561
2562 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
2563 {
2564         DSTACK(__FUNCTION_NAME);
2565
2566         SendAccessDenied(peer_id, reason);
2567         m_clients.event(peer_id, CSE_SetDenied);
2568         m_con.DisconnectPeer(peer_id);
2569 }
2570
2571 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2572 {
2573         DSTACK(__FUNCTION_NAME);
2574         std::wstring message;
2575         {
2576                 /*
2577                         Clear references to playing sounds
2578                 */
2579                 for(std::map<s32, ServerPlayingSound>::iterator
2580                                 i = m_playing_sounds.begin();
2581                                 i != m_playing_sounds.end();)
2582                 {
2583                         ServerPlayingSound &psound = i->second;
2584                         psound.clients.erase(peer_id);
2585                         if(psound.clients.empty())
2586                                 m_playing_sounds.erase(i++);
2587                         else
2588                                 i++;
2589                 }
2590
2591                 Player *player = m_env->getPlayer(peer_id);
2592
2593                 // Collect information about leaving in chat
2594                 {
2595                         if(player != NULL && reason != CDR_DENY)
2596                         {
2597                                 std::wstring name = narrow_to_wide(player->getName());
2598                                 message += L"*** ";
2599                                 message += name;
2600                                 message += L" left the game.";
2601                                 if(reason == CDR_TIMEOUT)
2602                                         message += L" (timed out)";
2603                         }
2604                 }
2605
2606                 /* Run scripts and remove from environment */
2607                 {
2608                         if(player != NULL)
2609                         {
2610                                 PlayerSAO *playersao = player->getPlayerSAO();
2611                                 assert(playersao);
2612
2613                                 m_script->on_leaveplayer(playersao);
2614
2615                                 playersao->disconnected();
2616                         }
2617                 }
2618
2619                 /*
2620                         Print out action
2621                 */
2622                 {
2623                         if(player != NULL && reason != CDR_DENY) {
2624                                 std::ostringstream os(std::ios_base::binary);
2625                                 std::vector<u16> clients = m_clients.getClientIDs();
2626
2627                                 for(std::vector<u16>::iterator i = clients.begin();
2628                                         i != clients.end(); ++i) {
2629                                         // Get player
2630                                         Player *player = m_env->getPlayer(*i);
2631                                         if(!player)
2632                                                 continue;
2633
2634                                         // Get name of player
2635                                         os << player->getName() << " ";
2636                                 }
2637
2638                                 actionstream << player->getName() << " "
2639                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2640                                                 << " List of players: " << os.str() << std::endl;
2641                         }
2642                 }
2643                 {
2644                         JMutexAutoLock env_lock(m_env_mutex);
2645                         m_clients.DeleteClient(peer_id);
2646                 }
2647         }
2648
2649         // Send leave chat message to all remaining clients
2650         if(message.length() != 0)
2651                 SendChatMessage(PEER_ID_INEXISTENT,message);
2652 }
2653
2654 void Server::UpdateCrafting(Player* player)
2655 {
2656         DSTACK(__FUNCTION_NAME);
2657
2658         // Get a preview for crafting
2659         ItemStack preview;
2660         InventoryLocation loc;
2661         loc.setPlayer(player->getName());
2662         getCraftingResult(&player->inventory, preview, false, this);
2663         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
2664
2665         // Put the new preview in
2666         InventoryList *plist = player->inventory.getList("craftpreview");
2667         assert(plist);
2668         assert(plist->getSize() >= 1);
2669         plist->changeItem(0, preview);
2670 }
2671
2672 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2673 {
2674         RemoteClient *client = getClientNoEx(peer_id,state_min);
2675         if(!client)
2676                 throw ClientNotFoundException("Client not found");
2677
2678         return client;
2679 }
2680 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2681 {
2682         return m_clients.getClientNoEx(peer_id, state_min);
2683 }
2684
2685 std::string Server::getPlayerName(u16 peer_id)
2686 {
2687         Player *player = m_env->getPlayer(peer_id);
2688         if(player == NULL)
2689                 return "[id="+itos(peer_id)+"]";
2690         return player->getName();
2691 }
2692
2693 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2694 {
2695         Player *player = m_env->getPlayer(peer_id);
2696         if(player == NULL)
2697                 return NULL;
2698         return player->getPlayerSAO();
2699 }
2700
2701 std::wstring Server::getStatusString()
2702 {
2703         std::wostringstream os(std::ios_base::binary);
2704         os<<L"# Server: ";
2705         // Version
2706         os<<L"version="<<narrow_to_wide(minetest_version_simple);
2707         // Uptime
2708         os<<L", uptime="<<m_uptime.get();
2709         // Max lag estimate
2710         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2711         // Information about clients
2712         bool first = true;
2713         os<<L", clients={";
2714         std::vector<u16> clients = m_clients.getClientIDs();
2715         for(std::vector<u16>::iterator i = clients.begin();
2716                 i != clients.end(); ++i) {
2717                 // Get player
2718                 Player *player = m_env->getPlayer(*i);
2719                 // Get name of player
2720                 std::wstring name = L"unknown";
2721                 if(player != NULL)
2722                         name = narrow_to_wide(player->getName());
2723                 // Add name to information string
2724                 if(!first)
2725                         os << L", ";
2726                 else
2727                         first = false;
2728                 os << name;
2729         }
2730         os << L"}";
2731         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2732                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2733         if(g_settings->get("motd") != "")
2734                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2735         return os.str();
2736 }
2737
2738 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2739 {
2740         std::set<std::string> privs;
2741         m_script->getAuth(name, NULL, &privs);
2742         return privs;
2743 }
2744
2745 bool Server::checkPriv(const std::string &name, const std::string &priv)
2746 {
2747         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2748         return (privs.count(priv) != 0);
2749 }
2750
2751 void Server::reportPrivsModified(const std::string &name)
2752 {
2753         if(name == "") {
2754                 std::vector<u16> clients = m_clients.getClientIDs();
2755                 for(std::vector<u16>::iterator i = clients.begin();
2756                                 i != clients.end(); ++i) {
2757                         Player *player = m_env->getPlayer(*i);
2758                         reportPrivsModified(player->getName());
2759                 }
2760         } else {
2761                 Player *player = m_env->getPlayer(name.c_str());
2762                 if(!player)
2763                         return;
2764                 SendPlayerPrivileges(player->peer_id);
2765                 PlayerSAO *sao = player->getPlayerSAO();
2766                 if(!sao)
2767                         return;
2768                 sao->updatePrivileges(
2769                                 getPlayerEffectivePrivs(name),
2770                                 isSingleplayer());
2771         }
2772 }
2773
2774 void Server::reportInventoryFormspecModified(const std::string &name)
2775 {
2776         Player *player = m_env->getPlayer(name.c_str());
2777         if(!player)
2778                 return;
2779         SendPlayerInventoryFormspec(player->peer_id);
2780 }
2781
2782 void Server::setIpBanned(const std::string &ip, const std::string &name)
2783 {
2784         m_banmanager->add(ip, name);
2785 }
2786
2787 void Server::unsetIpBanned(const std::string &ip_or_name)
2788 {
2789         m_banmanager->remove(ip_or_name);
2790 }
2791
2792 std::string Server::getBanDescription(const std::string &ip_or_name)
2793 {
2794         return m_banmanager->getBanDescription(ip_or_name);
2795 }
2796
2797 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2798 {
2799         Player *player = m_env->getPlayer(name);
2800         if(!player)
2801                 return;
2802
2803         if (player->peer_id == PEER_ID_INEXISTENT)
2804                 return;
2805
2806         SendChatMessage(player->peer_id, msg);
2807 }
2808
2809 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
2810 {
2811         Player *player = m_env->getPlayer(playername);
2812
2813         if(!player)
2814         {
2815                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
2816                 return false;
2817         }
2818
2819         SendShowFormspecMessage(player->peer_id, formspec, formname);
2820         return true;
2821 }
2822
2823 u32 Server::hudAdd(Player *player, HudElement *form) {
2824         if (!player)
2825                 return -1;
2826
2827         u32 id = player->addHud(form);
2828
2829         SendHUDAdd(player->peer_id, id, form);
2830
2831         return id;
2832 }
2833
2834 bool Server::hudRemove(Player *player, u32 id) {
2835         if (!player)
2836                 return false;
2837
2838         HudElement* todel = player->removeHud(id);
2839
2840         if (!todel)
2841                 return false;
2842
2843         delete todel;
2844
2845         SendHUDRemove(player->peer_id, id);
2846         return true;
2847 }
2848
2849 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
2850         if (!player)
2851                 return false;
2852
2853         SendHUDChange(player->peer_id, id, stat, data);
2854         return true;
2855 }
2856
2857 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
2858         if (!player)
2859                 return false;
2860
2861         SendHUDSetFlags(player->peer_id, flags, mask);
2862         player->hud_flags = flags;
2863
2864         PlayerSAO* playersao = player->getPlayerSAO();
2865
2866         if (playersao == NULL)
2867                 return false;
2868
2869         m_script->player_event(playersao, "hud_changed");
2870         return true;
2871 }
2872
2873 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
2874         if (!player)
2875                 return false;
2876         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
2877                 return false;
2878
2879         std::ostringstream os(std::ios::binary);
2880         writeS32(os, hotbar_itemcount);
2881         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
2882         return true;
2883 }
2884
2885 void Server::hudSetHotbarImage(Player *player, std::string name) {
2886         if (!player)
2887                 return;
2888
2889         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
2890 }
2891
2892 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
2893         if (!player)
2894                 return;
2895
2896         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
2897 }
2898
2899 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
2900 {
2901         if (!player)
2902                 return false;
2903
2904         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
2905         return true;
2906 }
2907
2908 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
2909 {
2910         if (!player)
2911                 return false;
2912
2913         SendEyeOffset(player->peer_id, first, third);
2914         return true;
2915 }
2916
2917 bool Server::setSky(Player *player, const video::SColor &bgcolor,
2918                 const std::string &type, const std::vector<std::string> &params)
2919 {
2920         if (!player)
2921                 return false;
2922
2923         SendSetSky(player->peer_id, bgcolor, type, params);
2924         return true;
2925 }
2926
2927 bool Server::overrideDayNightRatio(Player *player, bool do_override,
2928                 float ratio)
2929 {
2930         if (!player)
2931                 return false;
2932
2933         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
2934         return true;
2935 }
2936
2937 void Server::notifyPlayers(const std::wstring &msg)
2938 {
2939         SendChatMessage(PEER_ID_INEXISTENT,msg);
2940 }
2941
2942 void Server::spawnParticle(const char *playername, v3f pos,
2943                 v3f velocity, v3f acceleration,
2944                 float expirationtime, float size, bool
2945                 collisiondetection, bool vertical, std::string texture)
2946 {
2947         Player *player = m_env->getPlayer(playername);
2948         if(!player)
2949                 return;
2950         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
2951                         expirationtime, size, collisiondetection, vertical, texture);
2952 }
2953
2954 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
2955                 float expirationtime, float size,
2956                 bool collisiondetection, bool vertical, std::string texture)
2957 {
2958         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
2959                         expirationtime, size, collisiondetection, vertical, texture);
2960 }
2961
2962 u32 Server::addParticleSpawner(const char *playername,
2963                 u16 amount, float spawntime,
2964                 v3f minpos, v3f maxpos,
2965                 v3f minvel, v3f maxvel,
2966                 v3f minacc, v3f maxacc,
2967                 float minexptime, float maxexptime,
2968                 float minsize, float maxsize,
2969                 bool collisiondetection, bool vertical, std::string texture)
2970 {
2971         Player *player = m_env->getPlayer(playername);
2972         if(!player)
2973                 return -1;
2974
2975         u32 id = 0;
2976         for(;;) // look for unused particlespawner id
2977         {
2978                 id++;
2979                 if (std::find(m_particlespawner_ids.begin(),
2980                                 m_particlespawner_ids.end(), id)
2981                                 == m_particlespawner_ids.end())
2982                 {
2983                         m_particlespawner_ids.push_back(id);
2984                         break;
2985                 }
2986         }
2987
2988         SendAddParticleSpawner(player->peer_id, amount, spawntime,
2989                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
2990                 minexptime, maxexptime, minsize, maxsize,
2991                 collisiondetection, vertical, texture, id);
2992
2993         return id;
2994 }
2995
2996 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
2997                 v3f minpos, v3f maxpos,
2998                 v3f minvel, v3f maxvel,
2999                 v3f minacc, v3f maxacc,
3000                 float minexptime, float maxexptime,
3001                 float minsize, float maxsize,
3002                 bool collisiondetection, bool vertical, std::string texture)
3003 {
3004         u32 id = 0;
3005         for(;;) // look for unused particlespawner id
3006         {
3007                 id++;
3008                 if (std::find(m_particlespawner_ids.begin(),
3009                                 m_particlespawner_ids.end(), id)
3010                                 == m_particlespawner_ids.end())
3011                 {
3012                         m_particlespawner_ids.push_back(id);
3013                         break;
3014                 }
3015         }
3016
3017         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
3018                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3019                 minexptime, maxexptime, minsize, maxsize,
3020                 collisiondetection, vertical, texture, id);
3021
3022         return id;
3023 }
3024
3025 void Server::deleteParticleSpawner(const char *playername, u32 id)
3026 {
3027         Player *player = m_env->getPlayer(playername);
3028         if(!player)
3029                 return;
3030
3031         m_particlespawner_ids.erase(
3032                         std::remove(m_particlespawner_ids.begin(),
3033                         m_particlespawner_ids.end(), id),
3034                         m_particlespawner_ids.end());
3035         SendDeleteParticleSpawner(player->peer_id, id);
3036 }
3037
3038 void Server::deleteParticleSpawnerAll(u32 id)
3039 {
3040         m_particlespawner_ids.erase(
3041                         std::remove(m_particlespawner_ids.begin(),
3042                         m_particlespawner_ids.end(), id),
3043                         m_particlespawner_ids.end());
3044         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3045 }
3046
3047 Inventory* Server::createDetachedInventory(const std::string &name)
3048 {
3049         if(m_detached_inventories.count(name) > 0){
3050                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3051                 delete m_detached_inventories[name];
3052         } else {
3053                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3054         }
3055         Inventory *inv = new Inventory(m_itemdef);
3056         assert(inv);
3057         m_detached_inventories[name] = inv;
3058         //TODO find a better way to do this
3059         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3060         return inv;
3061 }
3062
3063 class BoolScopeSet
3064 {
3065 public:
3066         BoolScopeSet(bool *dst, bool val):
3067                 m_dst(dst)
3068         {
3069                 m_orig_state = *m_dst;
3070                 *m_dst = val;
3071         }
3072         ~BoolScopeSet()
3073         {
3074                 *m_dst = m_orig_state;
3075         }
3076 private:
3077         bool *m_dst;
3078         bool m_orig_state;
3079 };
3080
3081 // actions: time-reversed list
3082 // Return value: success/failure
3083 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3084                 std::list<std::string> *log)
3085 {
3086         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3087         ServerMap *map = (ServerMap*)(&m_env->getMap());
3088
3089         // Fail if no actions to handle
3090         if(actions.empty()){
3091                 log->push_back("Nothing to do.");
3092                 return false;
3093         }
3094
3095         int num_tried = 0;
3096         int num_failed = 0;
3097
3098         for(std::list<RollbackAction>::const_iterator
3099                         i = actions.begin();
3100                         i != actions.end(); i++)
3101         {
3102                 const RollbackAction &action = *i;
3103                 num_tried++;
3104                 bool success = action.applyRevert(map, this, this);
3105                 if(!success){
3106                         num_failed++;
3107                         std::ostringstream os;
3108                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3109                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3110                         if(log)
3111                                 log->push_back(os.str());
3112                 }else{
3113                         std::ostringstream os;
3114                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3115                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3116                         if(log)
3117                                 log->push_back(os.str());
3118                 }
3119         }
3120
3121         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3122                         <<" failed"<<std::endl;
3123
3124         // Call it done if less than half failed
3125         return num_failed <= num_tried/2;
3126 }
3127
3128 // IGameDef interface
3129 // Under envlock
3130 IItemDefManager* Server::getItemDefManager()
3131 {
3132         return m_itemdef;
3133 }
3134 INodeDefManager* Server::getNodeDefManager()
3135 {
3136         return m_nodedef;
3137 }
3138 ICraftDefManager* Server::getCraftDefManager()
3139 {
3140         return m_craftdef;
3141 }
3142 ITextureSource* Server::getTextureSource()
3143 {
3144         return NULL;
3145 }
3146 IShaderSource* Server::getShaderSource()
3147 {
3148         return NULL;
3149 }
3150 scene::ISceneManager* Server::getSceneManager()
3151 {
3152         return NULL;
3153 }
3154
3155 u16 Server::allocateUnknownNodeId(const std::string &name)
3156 {
3157         return m_nodedef->allocateDummy(name);
3158 }
3159 ISoundManager* Server::getSoundManager()
3160 {
3161         return &dummySoundManager;
3162 }
3163 MtEventManager* Server::getEventManager()
3164 {
3165         return m_event;
3166 }
3167
3168 IWritableItemDefManager* Server::getWritableItemDefManager()
3169 {
3170         return m_itemdef;
3171 }
3172 IWritableNodeDefManager* Server::getWritableNodeDefManager()
3173 {
3174         return m_nodedef;
3175 }
3176 IWritableCraftDefManager* Server::getWritableCraftDefManager()
3177 {
3178         return m_craftdef;
3179 }
3180
3181 const ModSpec* Server::getModSpec(const std::string &modname)
3182 {
3183         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3184                         i != m_mods.end(); i++){
3185                 const ModSpec &mod = *i;
3186                 if(mod.name == modname)
3187                         return &mod;
3188         }
3189         return NULL;
3190 }
3191 void Server::getModNames(std::vector<std::string> &modlist)
3192 {
3193         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++) {
3194                 modlist.push_back(i->name);
3195         }
3196 }
3197 std::string Server::getBuiltinLuaPath()
3198 {
3199         return porting::path_share + DIR_DELIM + "builtin";
3200 }
3201
3202 v3f findSpawnPos(ServerMap &map)
3203 {
3204         //return v3f(50,50,50)*BS;
3205
3206         v3s16 nodepos;
3207
3208 #if 0
3209         nodepos = v2s16(0,0);
3210         groundheight = 20;
3211 #endif
3212
3213 #if 1
3214         s16 water_level = map.getWaterLevel();
3215
3216         // Try to find a good place a few times
3217         for(s32 i=0; i<1000; i++)
3218         {
3219                 s32 range = 1 + i;
3220                 // We're going to try to throw the player to this position
3221                 v2s16 nodepos2d = v2s16(
3222                                 -range + (myrand() % (range * 2)),
3223                                 -range + (myrand() % (range * 2)));
3224
3225                 // Get ground height at point
3226                 s16 groundheight = map.findGroundLevel(nodepos2d);
3227                 if (groundheight <= water_level) // Don't go underwater
3228                         continue;
3229                 if (groundheight > water_level + 6) // Don't go to high places
3230                         continue;
3231
3232                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
3233                 bool is_good = false;
3234                 s32 air_count = 0;
3235                 for (s32 i = 0; i < 10; i++) {
3236                         v3s16 blockpos = getNodeBlockPos(nodepos);
3237                         map.emergeBlock(blockpos, true);
3238                         content_t c = map.getNodeNoEx(nodepos).getContent();
3239                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3240                                 air_count++;
3241                                 if (air_count >= 2){
3242                                         is_good = true;
3243                                         break;
3244                                 }
3245                         }
3246                         nodepos.Y++;
3247                 }
3248                 if(is_good){
3249                         // Found a good place
3250                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
3251                         break;
3252                 }
3253         }
3254 #endif
3255
3256         return intToFloat(nodepos, BS);
3257 }
3258
3259 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
3260 {
3261         bool newplayer = false;
3262
3263         /*
3264                 Try to get an existing player
3265         */
3266         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3267
3268         // If player is already connected, cancel
3269         if(player != NULL && player->peer_id != 0)
3270         {
3271                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3272                 return NULL;
3273         }
3274
3275         /*
3276                 If player with the wanted peer_id already exists, cancel.
3277         */
3278         if(m_env->getPlayer(peer_id) != NULL)
3279         {
3280                 infostream<<"emergePlayer(): Player with wrong name but same"
3281                                 " peer_id already exists"<<std::endl;
3282                 return NULL;
3283         }
3284
3285         // Load player if it isn't already loaded
3286         if (!player) {
3287                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3288         }
3289
3290         // Create player if it doesn't exist
3291         if (!player) {
3292                 newplayer = true;
3293                 player = new RemotePlayer(this, name);
3294                 // Set player position
3295                 infostream<<"Server: Finding spawn place for player \""
3296                                 <<name<<"\""<<std::endl;
3297                 v3f pos = findSpawnPos(m_env->getServerMap());
3298                 player->setPosition(pos);
3299
3300                 // Make sure the player is saved
3301                 player->setModified(true);
3302
3303                 // Add player to environment
3304                 m_env->addPlayer(player);
3305         }
3306
3307         // Create a new player active object
3308         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3309                         getPlayerEffectivePrivs(player->getName()),
3310                         isSingleplayer());
3311
3312         /* Clean up old HUD elements from previous sessions */
3313         player->clearHud();
3314
3315         /* Add object to environment */
3316         m_env->addActiveObject(playersao);
3317
3318         /* Run scripts */
3319         if (newplayer) {
3320                 m_script->on_newplayer(playersao);
3321         }
3322
3323         return playersao;
3324 }
3325
3326 void dedicated_server_loop(Server &server, bool &kill)
3327 {
3328         DSTACK(__FUNCTION_NAME);
3329
3330         verbosestream<<"dedicated_server_loop()"<<std::endl;
3331
3332         IntervalLimiter m_profiler_interval;
3333
3334         for(;;)
3335         {
3336                 float steplen = g_settings->getFloat("dedicated_server_step");
3337                 // This is kind of a hack but can be done like this
3338                 // because server.step() is very light
3339                 {
3340                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3341                         sleep_ms((int)(steplen*1000.0));
3342                 }
3343                 server.step(steplen);
3344
3345                 if(server.getShutdownRequested() || kill)
3346                 {
3347                         infostream<<"Dedicated server quitting"<<std::endl;
3348 #if USE_CURL
3349                         if(g_settings->getBool("server_announce"))
3350                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3351 #endif
3352                         break;
3353                 }
3354
3355                 /*
3356                         Profiler
3357                 */
3358                 float profiler_print_interval =
3359                                 g_settings->getFloat("profiler_print_interval");
3360                 if(profiler_print_interval != 0)
3361                 {
3362                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3363                         {
3364                                 infostream<<"Profiler:"<<std::endl;
3365                                 g_profiler->print(infostream);
3366                                 g_profiler->clear();
3367                         }
3368                 }
3369         }
3370 }
3371
3372