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