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