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