]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Prepare Protocol v25 init & authentication.
[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_Legacy(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_Legacy(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_Legacy(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->isDead())
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_Legacy(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, AccessDeniedCode reason, const std::wstring &custom_reason)
1506 {
1507         DSTACK(__FUNCTION_NAME);
1508
1509         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1510         pkt << (u8) reason;
1511
1512         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING) {
1513                 pkt << custom_reason;
1514         }
1515         Send(&pkt);
1516 }
1517
1518 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1519 {
1520         DSTACK(__FUNCTION_NAME);
1521
1522         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1523         *pkt << reason;
1524         Send(pkt);
1525 }
1526
1527 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1528                 v3f camera_point_target)
1529 {
1530         DSTACK(__FUNCTION_NAME);
1531
1532         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1533         *pkt << set_camera_point_target << camera_point_target;
1534         Send(pkt);
1535 }
1536
1537 void Server::SendItemDef(u16 peer_id,
1538                 IItemDefManager *itemdef, u16 protocol_version)
1539 {
1540         DSTACK(__FUNCTION_NAME);
1541
1542         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ITEMDEF, 0, peer_id);
1543
1544         /*
1545                 u16 command
1546                 u32 length of the next item
1547                 zlib-compressed serialized ItemDefManager
1548         */
1549         std::ostringstream tmp_os(std::ios::binary);
1550         itemdef->serialize(tmp_os, protocol_version);
1551         std::ostringstream tmp_os2(std::ios::binary);
1552         compressZlib(tmp_os.str(), tmp_os2);
1553         pkt->putLongString(tmp_os2.str());
1554
1555         // Make data buffer
1556         verbosestream << "Server: Sending item definitions to id(" << peer_id
1557                         << "): size=" << pkt->getSize() << std::endl;
1558
1559         Send(pkt);
1560 }
1561
1562 void Server::SendNodeDef(u16 peer_id,
1563                 INodeDefManager *nodedef, u16 protocol_version)
1564 {
1565         DSTACK(__FUNCTION_NAME);
1566
1567         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_NODEDEF, 0, peer_id);
1568
1569         /*
1570                 u16 command
1571                 u32 length of the next item
1572                 zlib-compressed serialized NodeDefManager
1573         */
1574         std::ostringstream tmp_os(std::ios::binary);
1575         nodedef->serialize(tmp_os, protocol_version);
1576         std::ostringstream tmp_os2(std::ios::binary);
1577         compressZlib(tmp_os.str(), tmp_os2);
1578
1579         pkt->putLongString(tmp_os2.str());
1580
1581         // Make data buffer
1582         verbosestream << "Server: Sending node definitions to id(" << peer_id
1583                         << "): size=" << pkt->getSize() << std::endl;
1584
1585         Send(pkt);
1586 }
1587
1588 /*
1589         Non-static send methods
1590 */
1591
1592 void Server::SendInventory(PlayerSAO* playerSAO)
1593 {
1594         DSTACK(__FUNCTION_NAME);
1595
1596         UpdateCrafting(playerSAO->getPlayer());
1597
1598         /*
1599                 Serialize it
1600         */
1601
1602         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_INVENTORY, 0,
1603                         playerSAO->getPeerID());
1604
1605         std::ostringstream os;
1606         playerSAO->getInventory()->serialize(os);
1607
1608         std::string s = os.str();
1609
1610         pkt->putRawString(s.c_str(), s.size());
1611         Send(pkt);
1612 }
1613
1614 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
1615 {
1616         DSTACK(__FUNCTION_NAME);
1617
1618         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1619         *pkt << message;
1620
1621         if (peer_id != PEER_ID_INEXISTENT) {
1622                 Send(pkt);
1623         }
1624         else {
1625                 m_clients.sendToAll(0,pkt,true);
1626         }
1627 }
1628
1629 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1630                                      const std::string &formname)
1631 {
1632         DSTACK(__FUNCTION_NAME);
1633
1634         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1635
1636         pkt->putLongString(FORMSPEC_VERSION_STRING + formspec);
1637         *pkt << formname;
1638
1639         Send(pkt);
1640 }
1641
1642 // Spawns a particle on peer with peer_id
1643 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
1644                                 float expirationtime, float size, bool collisiondetection,
1645                                 bool vertical, std::string texture)
1646 {
1647         DSTACK(__FUNCTION_NAME);
1648
1649         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1650
1651         *pkt << pos << velocity << acceleration << expirationtime
1652                         << size << collisiondetection;
1653         pkt->putLongString(texture);
1654         *pkt << vertical;
1655
1656         if (peer_id != PEER_ID_INEXISTENT) {
1657                 Send(pkt);
1658         }
1659         else {
1660                 m_clients.sendToAll(0,pkt,true);
1661         }
1662 }
1663
1664 // Adds a ParticleSpawner on peer with peer_id
1665 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
1666         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1667         float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
1668 {
1669         DSTACK(__FUNCTION_NAME);
1670
1671         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1672
1673         *pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1674                         << minacc << maxacc << minexptime << maxexptime << minsize
1675                         << maxsize << collisiondetection;
1676
1677         pkt->putLongString(texture);
1678
1679         *pkt << id << vertical;
1680
1681         if (peer_id != PEER_ID_INEXISTENT) {
1682                 Send(pkt);
1683         }
1684         else {
1685                 m_clients.sendToAll(0, pkt, true);
1686         }
1687 }
1688
1689 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1690 {
1691         DSTACK(__FUNCTION_NAME);
1692
1693         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1694
1695         // Ugly error in this packet
1696         *pkt << (u16) id;
1697
1698         if (peer_id != PEER_ID_INEXISTENT) {
1699                 Send(pkt);
1700         }
1701         else {
1702                 m_clients.sendToAll(0, pkt, true);
1703         }
1704
1705 }
1706
1707 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1708 {
1709         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_HUDADD, 0 , peer_id);
1710
1711         *pkt << id << (u8) form->type << form->pos << form->name << form->scale
1712                         << form->text << form->number << form->item << form->dir
1713                         << form->align << form->offset << form->world_pos << form->size;
1714
1715         Send(pkt);
1716 }
1717
1718 void Server::SendHUDRemove(u16 peer_id, u32 id)
1719 {
1720         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_HUDRM, 4, peer_id);
1721         *pkt << id;
1722         Send(pkt);
1723 }
1724
1725 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1726 {
1727         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_HUDCHANGE, 0, peer_id);
1728         *pkt << id << (u8) stat;
1729
1730         switch (stat) {
1731                 case HUD_STAT_POS:
1732                 case HUD_STAT_SCALE:
1733                 case HUD_STAT_ALIGN:
1734                 case HUD_STAT_OFFSET:
1735                         *pkt << *(v2f *) value;
1736                         break;
1737                 case HUD_STAT_NAME:
1738                 case HUD_STAT_TEXT:
1739                         *pkt << *(std::string *) value;
1740                         break;
1741                 case HUD_STAT_WORLD_POS:
1742                         *pkt << *(v3f *) value;
1743                         break;
1744                 case HUD_STAT_SIZE:
1745                         *pkt << *(v2s32 *) value;
1746                         break;
1747                 case HUD_STAT_NUMBER:
1748                 case HUD_STAT_ITEM:
1749                 case HUD_STAT_DIR:
1750                 default:
1751                         *pkt << *(u32 *) value;
1752                         break;
1753         }
1754
1755         Send(pkt);
1756 }
1757
1758 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1759 {
1760         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1761
1762         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1763
1764         *pkt << flags << mask;
1765
1766         Send(pkt);
1767 }
1768
1769 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1770 {
1771         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1772         *pkt << param << value;
1773         Send(pkt);
1774 }
1775
1776 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1777                 const std::string &type, const std::vector<std::string> &params)
1778 {
1779         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_SET_SKY, 0, peer_id);
1780         *pkt << bgcolor << type << (u16) params.size();
1781
1782         for(size_t i=0; i<params.size(); i++)
1783                 *pkt << params[i];
1784
1785         Send(pkt);
1786 }
1787
1788 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1789                 float ratio)
1790 {
1791         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1792                         1 + 2, peer_id);
1793
1794         *pkt << do_override << (u16) (ratio * 65535);
1795
1796         Send (pkt);
1797 }
1798
1799 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1800 {
1801         DSTACK(__FUNCTION_NAME);
1802
1803         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1804         *pkt << time << time_speed;
1805
1806         if (peer_id == PEER_ID_INEXISTENT) {
1807                 m_clients.sendToAll(0, pkt, true);
1808         }
1809         else {
1810                 Send(pkt);
1811         }
1812 }
1813
1814 void Server::SendPlayerHP(u16 peer_id)
1815 {
1816         DSTACK(__FUNCTION_NAME);
1817         PlayerSAO *playersao = getPlayerSAO(peer_id);
1818         assert(playersao);
1819         SendHP(peer_id, playersao->getHP());
1820         m_script->player_event(playersao,"health_changed");
1821
1822         // Send to other clients
1823         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1824         ActiveObjectMessage aom(playersao->getId(), true, str);
1825         playersao->m_messages_out.push(aom);
1826 }
1827
1828 void Server::SendPlayerBreath(u16 peer_id)
1829 {
1830         DSTACK(__FUNCTION_NAME);
1831         PlayerSAO *playersao = getPlayerSAO(peer_id);
1832         assert(playersao);
1833
1834         m_script->player_event(playersao, "breath_changed");
1835         SendBreath(peer_id, playersao->getBreath());
1836 }
1837
1838 void Server::SendMovePlayer(u16 peer_id)
1839 {
1840         DSTACK(__FUNCTION_NAME);
1841         Player *player = m_env->getPlayer(peer_id);
1842         assert(player);
1843
1844         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_MOVE_PLAYER, 0, peer_id);
1845         *pkt << player->getPosition() << player->getPitch() << player->getYaw();
1846
1847         {
1848                 v3f pos = player->getPosition();
1849                 f32 pitch = player->getPitch();
1850                 f32 yaw = player->getYaw();
1851                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
1852                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
1853                                 <<" pitch="<<pitch
1854                                 <<" yaw="<<yaw
1855                                 <<std::endl;
1856         }
1857
1858         Send(pkt);
1859 }
1860
1861 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1862 {
1863         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1864                 peer_id);
1865
1866         *pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1867                         << animation_frames[3] << animation_speed;
1868
1869         Send(pkt);
1870 }
1871
1872 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1873 {
1874         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_EYE_OFFSET, 0, peer_id);
1875         *pkt << first << third;
1876         Send(pkt);
1877 }
1878 void Server::SendPlayerPrivileges(u16 peer_id)
1879 {
1880         Player *player = m_env->getPlayer(peer_id);
1881         assert(player);
1882         if(player->peer_id == PEER_ID_INEXISTENT)
1883                 return;
1884
1885         std::set<std::string> privs;
1886         m_script->getAuth(player->getName(), NULL, &privs);
1887
1888         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_PRIVILEGES, 0, peer_id);
1889         *pkt << (u16) privs.size();
1890
1891         for(std::set<std::string>::const_iterator i = privs.begin();
1892                         i != privs.end(); i++) {
1893                 *pkt << (*i);
1894         }
1895
1896         Send(pkt);
1897 }
1898
1899 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1900 {
1901         Player *player = m_env->getPlayer(peer_id);
1902         assert(player);
1903         if(player->peer_id == PEER_ID_INEXISTENT)
1904                 return;
1905
1906         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1907         pkt->putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1908         Send(pkt);
1909 }
1910
1911 s32 Server::playSound(const SimpleSoundSpec &spec,
1912                 const ServerSoundParams &params)
1913 {
1914         // Find out initial position of sound
1915         bool pos_exists = false;
1916         v3f pos = params.getPos(m_env, &pos_exists);
1917         // If position is not found while it should be, cancel sound
1918         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1919                 return -1;
1920
1921         // Filter destination clients
1922         std::vector<u16> dst_clients;
1923         if(params.to_player != "")
1924         {
1925                 Player *player = m_env->getPlayer(params.to_player.c_str());
1926                 if(!player){
1927                         infostream<<"Server::playSound: Player \""<<params.to_player
1928                                         <<"\" not found"<<std::endl;
1929                         return -1;
1930                 }
1931                 if(player->peer_id == PEER_ID_INEXISTENT){
1932                         infostream<<"Server::playSound: Player \""<<params.to_player
1933                                         <<"\" not connected"<<std::endl;
1934                         return -1;
1935                 }
1936                 dst_clients.push_back(player->peer_id);
1937         }
1938         else {
1939                 std::vector<u16> clients = m_clients.getClientIDs();
1940
1941                 for(std::vector<u16>::iterator
1942                                 i = clients.begin(); i != clients.end(); ++i) {
1943                         Player *player = m_env->getPlayer(*i);
1944                         if(!player)
1945                                 continue;
1946
1947                         if(pos_exists) {
1948                                 if(player->getPosition().getDistanceFrom(pos) >
1949                                                 params.max_hear_distance)
1950                                         continue;
1951                         }
1952                         dst_clients.push_back(*i);
1953                 }
1954         }
1955
1956         if(dst_clients.empty())
1957                 return -1;
1958
1959         // Create the sound
1960         s32 id = m_next_sound_id++;
1961         // The sound will exist as a reference in m_playing_sounds
1962         m_playing_sounds[id] = ServerPlayingSound();
1963         ServerPlayingSound &psound = m_playing_sounds[id];
1964         psound.params = params;
1965
1966         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_PLAY_SOUND, 0);
1967         *pkt << id << spec.name << (float) (spec.gain * params.gain)
1968                         << (u8) params.type << pos << params.object << params.loop;
1969
1970         for(std::vector<u16>::iterator i = dst_clients.begin();
1971                         i != dst_clients.end(); i++) {
1972                 psound.clients.insert(*i);
1973                 m_clients.send(*i, 0, pkt, true, false);
1974         }
1975         delete pkt;
1976         return id;
1977 }
1978 void Server::stopSound(s32 handle)
1979 {
1980         // Get sound reference
1981         std::map<s32, ServerPlayingSound>::iterator i =
1982                         m_playing_sounds.find(handle);
1983         if(i == m_playing_sounds.end())
1984                 return;
1985         ServerPlayingSound &psound = i->second;
1986
1987         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_STOP_SOUND, 4);
1988         *pkt << handle;
1989
1990         for(std::set<u16>::iterator i = psound.clients.begin();
1991                         i != psound.clients.end(); i++) {
1992                 // Send as reliable
1993                 m_clients.send(*i, 0, pkt, true, false);
1994         }
1995         delete pkt;
1996         // Remove sound reference
1997         m_playing_sounds.erase(i);
1998 }
1999
2000 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2001         std::vector<u16> *far_players, float far_d_nodes)
2002 {
2003         float maxd = far_d_nodes*BS;
2004         v3f p_f = intToFloat(p, BS);
2005
2006         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_REMOVENODE, 6);
2007         *pkt << p;
2008
2009         std::vector<u16> clients = m_clients.getClientIDs();
2010         for(std::vector<u16>::iterator i = clients.begin();
2011                 i != clients.end(); ++i) {
2012                 if (far_players) {
2013                         // Get player
2014                         if(Player *player = m_env->getPlayer(*i)) {
2015                                 // If player is far away, only set modified blocks not sent
2016                                 v3f player_pos = player->getPosition();
2017                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2018                                         far_players->push_back(*i);
2019                                         continue;
2020                                 }
2021                         }
2022                 }
2023
2024                 // Send as reliable
2025                 m_clients.send(*i, 0, pkt, true, false);
2026         }
2027         // This loop needs the deletion of the packet here
2028         delete pkt;
2029 }
2030
2031 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2032                 std::vector<u16> *far_players, float far_d_nodes,
2033                 bool remove_metadata)
2034 {
2035         float maxd = far_d_nodes*BS;
2036         v3f p_f = intToFloat(p, BS);
2037
2038         std::vector<u16> clients = m_clients.getClientIDs();
2039         for(std::vector<u16>::iterator i = clients.begin();
2040                         i != clients.end(); ++i) {
2041
2042                 if(far_players) {
2043                         // Get player
2044                         if(Player *player = m_env->getPlayer(*i)) {
2045                                 // If player is far away, only set modified blocks not sent
2046                                 v3f player_pos = player->getPosition();
2047                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2048                                         far_players->push_back(*i);
2049                                         continue;
2050                                 }
2051                         }
2052                 }
2053
2054                 NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2055                 m_clients.Lock();
2056                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2057                 if (client != 0) {
2058                         *pkt << p << n.param0 << n.param1 << n.param2
2059                                         << (u8) (remove_metadata ? 0 : 1);
2060
2061                         if (!remove_metadata) {
2062                                 if (client->net_proto_version <= 21) {
2063                                         // Old clients always clear metadata; fix it
2064                                         // by sending the full block again.
2065                                         client->SetBlockNotSent(p);
2066                                 }
2067                         }
2068                 }
2069                 m_clients.Unlock();
2070
2071                 // Send as reliable
2072                 if (pkt->getSize() > 0)
2073                         m_clients.send(*i, 0, pkt, true);
2074         }
2075 }
2076
2077 void Server::setBlockNotSent(v3s16 p)
2078 {
2079         std::vector<u16> clients = m_clients.getClientIDs();
2080         m_clients.Lock();
2081         for(std::vector<u16>::iterator i = clients.begin();
2082                 i != clients.end(); ++i) {
2083                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2084                 client->SetBlockNotSent(p);
2085         }
2086         m_clients.Unlock();
2087 }
2088
2089 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2090 {
2091         DSTACK(__FUNCTION_NAME);
2092
2093         v3s16 p = block->getPos();
2094
2095         /*
2096                 Create a packet with the block in the right format
2097         */
2098
2099         std::ostringstream os(std::ios_base::binary);
2100         block->serialize(os, ver, false);
2101         block->serializeNetworkSpecific(os, net_proto_version);
2102         std::string s = os.str();
2103
2104         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_BLOCKDATA,
2105                 2 + 2 + 2 + 2 + s.size(), peer_id);
2106
2107         *pkt << p;
2108         pkt->putRawString(s.c_str(), s.size());
2109         Send(pkt);
2110 }
2111
2112 void Server::SendBlocks(float dtime)
2113 {
2114         DSTACK(__FUNCTION_NAME);
2115
2116         JMutexAutoLock envlock(m_env_mutex);
2117         //TODO check if one big lock could be faster then multiple small ones
2118
2119         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2120
2121         std::vector<PrioritySortedBlockTransfer> queue;
2122
2123         s32 total_sending = 0;
2124
2125         {
2126                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2127
2128                 std::vector<u16> clients = m_clients.getClientIDs();
2129
2130                 m_clients.Lock();
2131                 for(std::vector<u16>::iterator i = clients.begin();
2132                         i != clients.end(); ++i) {
2133                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2134
2135                         if (client == NULL)
2136                                 continue;
2137
2138                         total_sending += client->SendingCount();
2139                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2140                 }
2141                 m_clients.Unlock();
2142         }
2143
2144         // Sort.
2145         // Lowest priority number comes first.
2146         // Lowest is most important.
2147         std::sort(queue.begin(), queue.end());
2148
2149         m_clients.Lock();
2150         for(u32 i=0; i<queue.size(); i++)
2151         {
2152                 //TODO: Calculate limit dynamically
2153                 if(total_sending >= g_settings->getS32
2154                                 ("max_simultaneous_block_sends_server_total"))
2155                         break;
2156
2157                 PrioritySortedBlockTransfer q = queue[i];
2158
2159                 MapBlock *block = NULL;
2160                 try
2161                 {
2162                         block = m_env->getMap().getBlockNoCreate(q.pos);
2163                 }
2164                 catch(InvalidPositionException &e)
2165                 {
2166                         continue;
2167                 }
2168
2169                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2170
2171                 if(!client)
2172                         continue;
2173
2174                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2175
2176                 client->SentBlock(q.pos);
2177                 total_sending++;
2178         }
2179         m_clients.Unlock();
2180 }
2181
2182 void Server::fillMediaCache()
2183 {
2184         DSTACK(__FUNCTION_NAME);
2185
2186         infostream<<"Server: Calculating media file checksums"<<std::endl;
2187
2188         // Collect all media file paths
2189         std::vector<std::string> paths;
2190         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2191                         i != m_mods.end(); i++) {
2192                 const ModSpec &mod = *i;
2193                 paths.push_back(mod.path + DIR_DELIM + "textures");
2194                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2195                 paths.push_back(mod.path + DIR_DELIM + "media");
2196                 paths.push_back(mod.path + DIR_DELIM + "models");
2197         }
2198         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2199
2200         // Collect media file information from paths into cache
2201         for(std::vector<std::string>::iterator i = paths.begin();
2202                         i != paths.end(); i++) {
2203                 std::string mediapath = *i;
2204                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2205                 for (u32 j = 0; j < dirlist.size(); j++) {
2206                         if (dirlist[j].dir) // Ignode dirs
2207                                 continue;
2208                         std::string filename = dirlist[j].name;
2209                         // If name contains illegal characters, ignore the file
2210                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2211                                 infostream<<"Server: ignoring illegal file name: \""
2212                                                 << filename << "\"" << std::endl;
2213                                 continue;
2214                         }
2215                         // If name is not in a supported format, ignore it
2216                         const char *supported_ext[] = {
2217                                 ".png", ".jpg", ".bmp", ".tga",
2218                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2219                                 ".ogg",
2220                                 ".x", ".b3d", ".md2", ".obj",
2221                                 NULL
2222                         };
2223                         if (removeStringEnd(filename, supported_ext) == ""){
2224                                 infostream << "Server: ignoring unsupported file extension: \""
2225                                                 << filename << "\"" << std::endl;
2226                                 continue;
2227                         }
2228                         // Ok, attempt to load the file and add to cache
2229                         std::string filepath = mediapath + DIR_DELIM + filename;
2230                         // Read data
2231                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2232                         if (!fis.good()) {
2233                                 errorstream << "Server::fillMediaCache(): Could not open \""
2234                                                 << filename << "\" for reading" << std::endl;
2235                                 continue;
2236                         }
2237                         std::ostringstream tmp_os(std::ios_base::binary);
2238                         bool bad = false;
2239                         for(;;) {
2240                                 char buf[1024];
2241                                 fis.read(buf, 1024);
2242                                 std::streamsize len = fis.gcount();
2243                                 tmp_os.write(buf, len);
2244                                 if (fis.eof())
2245                                         break;
2246                                 if (!fis.good()) {
2247                                         bad = true;
2248                                         break;
2249                                 }
2250                         }
2251                         if(bad) {
2252                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2253                                                 << filename << "\"" << std::endl;
2254                                 continue;
2255                         }
2256                         if(tmp_os.str().length() == 0) {
2257                                 errorstream << "Server::fillMediaCache(): Empty file \""
2258                                                 << filepath << "\"" << std::endl;
2259                                 continue;
2260                         }
2261
2262                         SHA1 sha1;
2263                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2264
2265                         unsigned char *digest = sha1.getDigest();
2266                         std::string sha1_base64 = base64_encode(digest, 20);
2267                         std::string sha1_hex = hex_encode((char*)digest, 20);
2268                         free(digest);
2269
2270                         // Put in list
2271                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2272                         verbosestream << "Server: " << sha1_hex << " is " << filename
2273                                         << std::endl;
2274                 }
2275         }
2276 }
2277
2278 struct SendableMediaAnnouncement
2279 {
2280         std::string name;
2281         std::string sha1_digest;
2282
2283         SendableMediaAnnouncement(const std::string &name_="",
2284                                   const std::string &sha1_digest_=""):
2285                 name(name_),
2286                 sha1_digest(sha1_digest_)
2287         {}
2288 };
2289
2290 void Server::sendMediaAnnouncement(u16 peer_id)
2291 {
2292         DSTACK(__FUNCTION_NAME);
2293
2294         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
2295                         <<std::endl;
2296
2297         std::vector<SendableMediaAnnouncement> file_announcements;
2298
2299         for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
2300                         i != m_media.end(); i++){
2301                 // Put in list
2302                 file_announcements.push_back(
2303                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
2304         }
2305
2306         // Make packet
2307         std::ostringstream os(std::ios_base::binary);
2308
2309         /*
2310                 u32 number of files
2311                 for each texture {
2312                         u16 length of name
2313                         string name
2314                         u16 length of sha1_digest
2315                         string sha1_digest
2316                 }
2317         */
2318
2319         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2320         *pkt << (u16) file_announcements.size();
2321
2322         for (std::vector<SendableMediaAnnouncement>::iterator
2323                         j = file_announcements.begin();
2324                         j != file_announcements.end(); ++j) {
2325                 *pkt << j->name << j->sha1_digest;
2326         }
2327
2328         *pkt << g_settings->get("remote_media");
2329         Send(pkt);
2330 }
2331
2332 struct SendableMedia
2333 {
2334         std::string name;
2335         std::string path;
2336         std::string data;
2337
2338         SendableMedia(const std::string &name_="", const std::string &path_="",
2339                       const std::string &data_=""):
2340                 name(name_),
2341                 path(path_),
2342                 data(data_)
2343         {}
2344 };
2345
2346 void Server::sendRequestedMedia(u16 peer_id,
2347                 const std::vector<std::string> &tosend)
2348 {
2349         DSTACK(__FUNCTION_NAME);
2350
2351         verbosestream<<"Server::sendRequestedMedia(): "
2352                         <<"Sending files to client"<<std::endl;
2353
2354         /* Read files */
2355
2356         // Put 5kB in one bunch (this is not accurate)
2357         u32 bytes_per_bunch = 5000;
2358
2359         std::vector< std::vector<SendableMedia> > file_bunches;
2360         file_bunches.push_back(std::vector<SendableMedia>());
2361
2362         u32 file_size_bunch_total = 0;
2363
2364         for(std::vector<std::string>::const_iterator i = tosend.begin();
2365                         i != tosend.end(); ++i) {
2366                 const std::string &name = *i;
2367
2368                 if(m_media.find(name) == m_media.end()) {
2369                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2370                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2371                         continue;
2372                 }
2373
2374                 //TODO get path + name
2375                 std::string tpath = m_media[name].path;
2376
2377                 // Read data
2378                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2379                 if(fis.good() == false){
2380                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2381                                         <<tpath<<"\" for reading"<<std::endl;
2382                         continue;
2383                 }
2384                 std::ostringstream tmp_os(std::ios_base::binary);
2385                 bool bad = false;
2386                 for(;;) {
2387                         char buf[1024];
2388                         fis.read(buf, 1024);
2389                         std::streamsize len = fis.gcount();
2390                         tmp_os.write(buf, len);
2391                         file_size_bunch_total += len;
2392                         if(fis.eof())
2393                                 break;
2394                         if(!fis.good()) {
2395                                 bad = true;
2396                                 break;
2397                         }
2398                 }
2399                 if(bad) {
2400                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2401                                         <<name<<"\""<<std::endl;
2402                         continue;
2403                 }
2404                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2405                                 <<tname<<"\""<<std::endl;*/
2406                 // Put in list
2407                 file_bunches[file_bunches.size()-1].push_back(
2408                                 SendableMedia(name, tpath, tmp_os.str()));
2409
2410                 // Start next bunch if got enough data
2411                 if(file_size_bunch_total >= bytes_per_bunch) {
2412                         file_bunches.push_back(std::vector<SendableMedia>());
2413                         file_size_bunch_total = 0;
2414                 }
2415
2416         }
2417
2418         /* Create and send packets */
2419
2420         u16 num_bunches = file_bunches.size();
2421         for(u16 i = 0; i < num_bunches; i++) {
2422                 /*
2423                         u16 command
2424                         u16 total number of texture bunches
2425                         u16 index of this bunch
2426                         u32 number of files in this bunch
2427                         for each file {
2428                                 u16 length of name
2429                                 string name
2430                                 u32 length of data
2431                                 data
2432                         }
2433                 */
2434
2435                 NetworkPacket* pkt = new NetworkPacket(TOCLIENT_MEDIA, 0, peer_id);
2436                 *pkt << num_bunches << i << (u32) file_bunches[i].size();
2437
2438                 for(std::vector<SendableMedia>::iterator
2439                                 j = file_bunches[i].begin();
2440                                 j != file_bunches[i].end(); ++j) {
2441                         *pkt << j->name;
2442                         pkt->putLongString(j->data);
2443                 }
2444
2445                 verbosestream << "Server::sendRequestedMedia(): bunch "
2446                                 << i << "/" << num_bunches
2447                                 << " files=" << file_bunches[i].size()
2448                                 << " size="  << pkt->getSize() << std::endl;
2449                 Send(pkt);
2450         }
2451 }
2452
2453 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2454 {
2455         if(m_detached_inventories.count(name) == 0) {
2456                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2457                 return;
2458         }
2459         Inventory *inv = m_detached_inventories[name];
2460         std::ostringstream os(std::ios_base::binary);
2461
2462         os << serializeString(name);
2463         inv->serialize(os);
2464
2465         // Make data buffer
2466         std::string s = os.str();
2467
2468         NetworkPacket* pkt = new NetworkPacket(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2469         pkt->putRawString(s.c_str(), s.size());
2470
2471         if (peer_id != PEER_ID_INEXISTENT) {
2472                 Send(pkt);
2473         }
2474         else {
2475                 m_clients.sendToAll(0, pkt, true);
2476         }
2477 }
2478
2479 void Server::sendDetachedInventories(u16 peer_id)
2480 {
2481         DSTACK(__FUNCTION_NAME);
2482
2483         for(std::map<std::string, Inventory*>::iterator
2484                         i = m_detached_inventories.begin();
2485                         i != m_detached_inventories.end(); i++) {
2486                 const std::string &name = i->first;
2487                 //Inventory *inv = i->second;
2488                 sendDetachedInventory(name, peer_id);
2489         }
2490 }
2491
2492 /*
2493         Something random
2494 */
2495
2496 void Server::DiePlayer(u16 peer_id)
2497 {
2498         DSTACK(__FUNCTION_NAME);
2499
2500         PlayerSAO *playersao = getPlayerSAO(peer_id);
2501         assert(playersao);
2502
2503         infostream << "Server::DiePlayer(): Player "
2504                         << playersao->getPlayer()->getName()
2505                         << " dies" << std::endl;
2506
2507         playersao->setHP(0);
2508
2509         // Trigger scripted stuff
2510         m_script->on_dieplayer(playersao);
2511
2512         SendPlayerHP(peer_id);
2513         SendDeathscreen(peer_id, false, v3f(0,0,0));
2514 }
2515
2516 void Server::RespawnPlayer(u16 peer_id)
2517 {
2518         DSTACK(__FUNCTION_NAME);
2519
2520         PlayerSAO *playersao = getPlayerSAO(peer_id);
2521         assert(playersao);
2522
2523         infostream << "Server::RespawnPlayer(): Player "
2524                         << playersao->getPlayer()->getName()
2525                         << " respawns" << std::endl;
2526
2527         playersao->setHP(PLAYER_MAX_HP);
2528         playersao->setBreath(PLAYER_MAX_BREATH);
2529
2530         SendPlayerHP(peer_id);
2531         SendPlayerBreath(peer_id);
2532
2533         bool repositioned = m_script->on_respawnplayer(playersao);
2534         if(!repositioned){
2535                 v3f pos = findSpawnPos(m_env->getServerMap());
2536                 // setPos will send the new position to client
2537                 playersao->setPos(pos);
2538         }
2539 }
2540
2541 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::wstring &custom_reason)
2542 {
2543         DSTACK(__FUNCTION_NAME);
2544
2545         SendAccessDenied(peer_id, reason, custom_reason);
2546         m_clients.event(peer_id, CSE_SetDenied);
2547         m_con.DisconnectPeer(peer_id);
2548 }
2549
2550 // 13/03/15: remove this function when protocol version 25 will become
2551 // the minimum version for MT users, maybe in 1 year
2552 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2553 {
2554         DSTACK(__FUNCTION_NAME);
2555
2556         SendAccessDenied_Legacy(peer_id, reason);
2557         m_clients.event(peer_id, CSE_SetDenied);
2558         m_con.DisconnectPeer(peer_id);
2559 }
2560
2561 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2562 {
2563         DSTACK(__FUNCTION_NAME);
2564         std::wstring message;
2565         {
2566                 /*
2567                         Clear references to playing sounds
2568                 */
2569                 for(std::map<s32, ServerPlayingSound>::iterator
2570                                 i = m_playing_sounds.begin();
2571                                 i != m_playing_sounds.end();)
2572                 {
2573                         ServerPlayingSound &psound = i->second;
2574                         psound.clients.erase(peer_id);
2575                         if(psound.clients.empty())
2576                                 m_playing_sounds.erase(i++);
2577                         else
2578                                 i++;
2579                 }
2580
2581                 Player *player = m_env->getPlayer(peer_id);
2582
2583                 // Collect information about leaving in chat
2584                 {
2585                         if(player != NULL && reason != CDR_DENY)
2586                         {
2587                                 std::wstring name = narrow_to_wide(player->getName());
2588                                 message += L"*** ";
2589                                 message += name;
2590                                 message += L" left the game.";
2591                                 if(reason == CDR_TIMEOUT)
2592                                         message += L" (timed out)";
2593                         }
2594                 }
2595
2596                 /* Run scripts and remove from environment */
2597                 {
2598                         if(player != NULL)
2599                         {
2600                                 PlayerSAO *playersao = player->getPlayerSAO();
2601                                 assert(playersao);
2602
2603                                 m_script->on_leaveplayer(playersao);
2604
2605                                 playersao->disconnected();
2606                         }
2607                 }
2608
2609                 /*
2610                         Print out action
2611                 */
2612                 {
2613                         if(player != NULL && reason != CDR_DENY) {
2614                                 std::ostringstream os(std::ios_base::binary);
2615                                 std::vector<u16> clients = m_clients.getClientIDs();
2616
2617                                 for(std::vector<u16>::iterator i = clients.begin();
2618                                         i != clients.end(); ++i) {
2619                                         // Get player
2620                                         Player *player = m_env->getPlayer(*i);
2621                                         if(!player)
2622                                                 continue;
2623
2624                                         // Get name of player
2625                                         os << player->getName() << " ";
2626                                 }
2627
2628                                 actionstream << player->getName() << " "
2629                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2630                                                 << " List of players: " << os.str() << std::endl;
2631                         }
2632                 }
2633                 {
2634                         JMutexAutoLock env_lock(m_env_mutex);
2635                         m_clients.DeleteClient(peer_id);
2636                 }
2637         }
2638
2639         // Send leave chat message to all remaining clients
2640         if(message.length() != 0)
2641                 SendChatMessage(PEER_ID_INEXISTENT,message);
2642 }
2643
2644 void Server::UpdateCrafting(Player* player)
2645 {
2646         DSTACK(__FUNCTION_NAME);
2647
2648         // Get a preview for crafting
2649         ItemStack preview;
2650         InventoryLocation loc;
2651         loc.setPlayer(player->getName());
2652         getCraftingResult(&player->inventory, preview, false, this);
2653         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
2654
2655         // Put the new preview in
2656         InventoryList *plist = player->inventory.getList("craftpreview");
2657         sanity_check(plist);
2658         sanity_check(plist->getSize() >= 1);
2659         plist->changeItem(0, preview);
2660 }
2661
2662 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2663 {
2664         RemoteClient *client = getClientNoEx(peer_id,state_min);
2665         if(!client)
2666                 throw ClientNotFoundException("Client not found");
2667
2668         return client;
2669 }
2670 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2671 {
2672         return m_clients.getClientNoEx(peer_id, state_min);
2673 }
2674
2675 std::string Server::getPlayerName(u16 peer_id)
2676 {
2677         Player *player = m_env->getPlayer(peer_id);
2678         if(player == NULL)
2679                 return "[id="+itos(peer_id)+"]";
2680         return player->getName();
2681 }
2682
2683 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2684 {
2685         Player *player = m_env->getPlayer(peer_id);
2686         if(player == NULL)
2687                 return NULL;
2688         return player->getPlayerSAO();
2689 }
2690
2691 std::wstring Server::getStatusString()
2692 {
2693         std::wostringstream os(std::ios_base::binary);
2694         os<<L"# Server: ";
2695         // Version
2696         os<<L"version="<<narrow_to_wide(minetest_version_simple);
2697         // Uptime
2698         os<<L", uptime="<<m_uptime.get();
2699         // Max lag estimate
2700         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2701         // Information about clients
2702         bool first = true;
2703         os<<L", clients={";
2704         std::vector<u16> clients = m_clients.getClientIDs();
2705         for(std::vector<u16>::iterator i = clients.begin();
2706                 i != clients.end(); ++i) {
2707                 // Get player
2708                 Player *player = m_env->getPlayer(*i);
2709                 // Get name of player
2710                 std::wstring name = L"unknown";
2711                 if(player != NULL)
2712                         name = narrow_to_wide(player->getName());
2713                 // Add name to information string
2714                 if(!first)
2715                         os << L", ";
2716                 else
2717                         first = false;
2718                 os << name;
2719         }
2720         os << L"}";
2721         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2722                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2723         if(g_settings->get("motd") != "")
2724                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2725         return os.str();
2726 }
2727
2728 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2729 {
2730         std::set<std::string> privs;
2731         m_script->getAuth(name, NULL, &privs);
2732         return privs;
2733 }
2734
2735 bool Server::checkPriv(const std::string &name, const std::string &priv)
2736 {
2737         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2738         return (privs.count(priv) != 0);
2739 }
2740
2741 void Server::reportPrivsModified(const std::string &name)
2742 {
2743         if(name == "") {
2744                 std::vector<u16> clients = m_clients.getClientIDs();
2745                 for(std::vector<u16>::iterator i = clients.begin();
2746                                 i != clients.end(); ++i) {
2747                         Player *player = m_env->getPlayer(*i);
2748                         reportPrivsModified(player->getName());
2749                 }
2750         } else {
2751                 Player *player = m_env->getPlayer(name.c_str());
2752                 if(!player)
2753                         return;
2754                 SendPlayerPrivileges(player->peer_id);
2755                 PlayerSAO *sao = player->getPlayerSAO();
2756                 if(!sao)
2757                         return;
2758                 sao->updatePrivileges(
2759                                 getPlayerEffectivePrivs(name),
2760                                 isSingleplayer());
2761         }
2762 }
2763
2764 void Server::reportInventoryFormspecModified(const std::string &name)
2765 {
2766         Player *player = m_env->getPlayer(name.c_str());
2767         if(!player)
2768                 return;
2769         SendPlayerInventoryFormspec(player->peer_id);
2770 }
2771
2772 void Server::setIpBanned(const std::string &ip, const std::string &name)
2773 {
2774         m_banmanager->add(ip, name);
2775 }
2776
2777 void Server::unsetIpBanned(const std::string &ip_or_name)
2778 {
2779         m_banmanager->remove(ip_or_name);
2780 }
2781
2782 std::string Server::getBanDescription(const std::string &ip_or_name)
2783 {
2784         return m_banmanager->getBanDescription(ip_or_name);
2785 }
2786
2787 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2788 {
2789         Player *player = m_env->getPlayer(name);
2790         if(!player)
2791                 return;
2792
2793         if (player->peer_id == PEER_ID_INEXISTENT)
2794                 return;
2795
2796         SendChatMessage(player->peer_id, msg);
2797 }
2798
2799 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
2800 {
2801         Player *player = m_env->getPlayer(playername);
2802
2803         if(!player)
2804         {
2805                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
2806                 return false;
2807         }
2808
2809         SendShowFormspecMessage(player->peer_id, formspec, formname);
2810         return true;
2811 }
2812
2813 u32 Server::hudAdd(Player *player, HudElement *form) {
2814         if (!player)
2815                 return -1;
2816
2817         u32 id = player->addHud(form);
2818
2819         SendHUDAdd(player->peer_id, id, form);
2820
2821         return id;
2822 }
2823
2824 bool Server::hudRemove(Player *player, u32 id) {
2825         if (!player)
2826                 return false;
2827
2828         HudElement* todel = player->removeHud(id);
2829
2830         if (!todel)
2831                 return false;
2832
2833         delete todel;
2834
2835         SendHUDRemove(player->peer_id, id);
2836         return true;
2837 }
2838
2839 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
2840         if (!player)
2841                 return false;
2842
2843         SendHUDChange(player->peer_id, id, stat, data);
2844         return true;
2845 }
2846
2847 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
2848         if (!player)
2849                 return false;
2850
2851         SendHUDSetFlags(player->peer_id, flags, mask);
2852         player->hud_flags = flags;
2853
2854         PlayerSAO* playersao = player->getPlayerSAO();
2855
2856         if (playersao == NULL)
2857                 return false;
2858
2859         m_script->player_event(playersao, "hud_changed");
2860         return true;
2861 }
2862
2863 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
2864         if (!player)
2865                 return false;
2866         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
2867                 return false;
2868
2869         std::ostringstream os(std::ios::binary);
2870         writeS32(os, hotbar_itemcount);
2871         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
2872         return true;
2873 }
2874
2875 void Server::hudSetHotbarImage(Player *player, std::string name) {
2876         if (!player)
2877                 return;
2878
2879         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
2880 }
2881
2882 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
2883         if (!player)
2884                 return;
2885
2886         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
2887 }
2888
2889 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
2890 {
2891         if (!player)
2892                 return false;
2893
2894         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
2895         return true;
2896 }
2897
2898 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
2899 {
2900         if (!player)
2901                 return false;
2902
2903         SendEyeOffset(player->peer_id, first, third);
2904         return true;
2905 }
2906
2907 bool Server::setSky(Player *player, const video::SColor &bgcolor,
2908                 const std::string &type, const std::vector<std::string> &params)
2909 {
2910         if (!player)
2911                 return false;
2912
2913         SendSetSky(player->peer_id, bgcolor, type, params);
2914         return true;
2915 }
2916
2917 bool Server::overrideDayNightRatio(Player *player, bool do_override,
2918                 float ratio)
2919 {
2920         if (!player)
2921                 return false;
2922
2923         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
2924         return true;
2925 }
2926
2927 void Server::notifyPlayers(const std::wstring &msg)
2928 {
2929         SendChatMessage(PEER_ID_INEXISTENT,msg);
2930 }
2931
2932 void Server::spawnParticle(const char *playername, v3f pos,
2933                 v3f velocity, v3f acceleration,
2934                 float expirationtime, float size, bool
2935                 collisiondetection, bool vertical, std::string texture)
2936 {
2937         Player *player = m_env->getPlayer(playername);
2938         if(!player)
2939                 return;
2940         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
2941                         expirationtime, size, collisiondetection, vertical, texture);
2942 }
2943
2944 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
2945                 float expirationtime, float size,
2946                 bool collisiondetection, bool vertical, std::string texture)
2947 {
2948         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
2949                         expirationtime, size, collisiondetection, vertical, texture);
2950 }
2951
2952 u32 Server::addParticleSpawner(const char *playername,
2953                 u16 amount, float spawntime,
2954                 v3f minpos, v3f maxpos,
2955                 v3f minvel, v3f maxvel,
2956                 v3f minacc, v3f maxacc,
2957                 float minexptime, float maxexptime,
2958                 float minsize, float maxsize,
2959                 bool collisiondetection, bool vertical, std::string texture)
2960 {
2961         Player *player = m_env->getPlayer(playername);
2962         if(!player)
2963                 return -1;
2964
2965         u32 id = 0;
2966         for(;;) // look for unused particlespawner id
2967         {
2968                 id++;
2969                 if (std::find(m_particlespawner_ids.begin(),
2970                                 m_particlespawner_ids.end(), id)
2971                                 == m_particlespawner_ids.end())
2972                 {
2973                         m_particlespawner_ids.push_back(id);
2974                         break;
2975                 }
2976         }
2977
2978         SendAddParticleSpawner(player->peer_id, amount, spawntime,
2979                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
2980                 minexptime, maxexptime, minsize, maxsize,
2981                 collisiondetection, vertical, texture, id);
2982
2983         return id;
2984 }
2985
2986 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
2987                 v3f minpos, v3f maxpos,
2988                 v3f minvel, v3f maxvel,
2989                 v3f minacc, v3f maxacc,
2990                 float minexptime, float maxexptime,
2991                 float minsize, float maxsize,
2992                 bool collisiondetection, bool vertical, std::string texture)
2993 {
2994         u32 id = 0;
2995         for(;;) // look for unused particlespawner id
2996         {
2997                 id++;
2998                 if (std::find(m_particlespawner_ids.begin(),
2999                                 m_particlespawner_ids.end(), id)
3000                                 == m_particlespawner_ids.end())
3001                 {
3002                         m_particlespawner_ids.push_back(id);
3003                         break;
3004                 }
3005         }
3006
3007         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
3008                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3009                 minexptime, maxexptime, minsize, maxsize,
3010                 collisiondetection, vertical, texture, id);
3011
3012         return id;
3013 }
3014
3015 void Server::deleteParticleSpawner(const char *playername, u32 id)
3016 {
3017         Player *player = m_env->getPlayer(playername);
3018         if(!player)
3019                 return;
3020
3021         m_particlespawner_ids.erase(
3022                         std::remove(m_particlespawner_ids.begin(),
3023                         m_particlespawner_ids.end(), id),
3024                         m_particlespawner_ids.end());
3025         SendDeleteParticleSpawner(player->peer_id, id);
3026 }
3027
3028 void Server::deleteParticleSpawnerAll(u32 id)
3029 {
3030         m_particlespawner_ids.erase(
3031                         std::remove(m_particlespawner_ids.begin(),
3032                         m_particlespawner_ids.end(), id),
3033                         m_particlespawner_ids.end());
3034         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3035 }
3036
3037 Inventory* Server::createDetachedInventory(const std::string &name)
3038 {
3039         if(m_detached_inventories.count(name) > 0){
3040                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3041                 delete m_detached_inventories[name];
3042         } else {
3043                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3044         }
3045         Inventory *inv = new Inventory(m_itemdef);
3046         sanity_check(inv);
3047         m_detached_inventories[name] = inv;
3048         //TODO find a better way to do this
3049         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3050         return inv;
3051 }
3052
3053 class BoolScopeSet
3054 {
3055 public:
3056         BoolScopeSet(bool *dst, bool val):
3057                 m_dst(dst)
3058         {
3059                 m_orig_state = *m_dst;
3060                 *m_dst = val;
3061         }
3062         ~BoolScopeSet()
3063         {
3064                 *m_dst = m_orig_state;
3065         }
3066 private:
3067         bool *m_dst;
3068         bool m_orig_state;
3069 };
3070
3071 // actions: time-reversed list
3072 // Return value: success/failure
3073 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3074                 std::list<std::string> *log)
3075 {
3076         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3077         ServerMap *map = (ServerMap*)(&m_env->getMap());
3078
3079         // Fail if no actions to handle
3080         if(actions.empty()){
3081                 log->push_back("Nothing to do.");
3082                 return false;
3083         }
3084
3085         int num_tried = 0;
3086         int num_failed = 0;
3087
3088         for(std::list<RollbackAction>::const_iterator
3089                         i = actions.begin();
3090                         i != actions.end(); i++)
3091         {
3092                 const RollbackAction &action = *i;
3093                 num_tried++;
3094                 bool success = action.applyRevert(map, this, this);
3095                 if(!success){
3096                         num_failed++;
3097                         std::ostringstream os;
3098                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3099                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3100                         if(log)
3101                                 log->push_back(os.str());
3102                 }else{
3103                         std::ostringstream os;
3104                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3105                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3106                         if(log)
3107                                 log->push_back(os.str());
3108                 }
3109         }
3110
3111         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3112                         <<" failed"<<std::endl;
3113
3114         // Call it done if less than half failed
3115         return num_failed <= num_tried/2;
3116 }
3117
3118 // IGameDef interface
3119 // Under envlock
3120 IItemDefManager* Server::getItemDefManager()
3121 {
3122         return m_itemdef;
3123 }
3124 INodeDefManager* Server::getNodeDefManager()
3125 {
3126         return m_nodedef;
3127 }
3128 ICraftDefManager* Server::getCraftDefManager()
3129 {
3130         return m_craftdef;
3131 }
3132 ITextureSource* Server::getTextureSource()
3133 {
3134         return NULL;
3135 }
3136 IShaderSource* Server::getShaderSource()
3137 {
3138         return NULL;
3139 }
3140 scene::ISceneManager* Server::getSceneManager()
3141 {
3142         return NULL;
3143 }
3144
3145 u16 Server::allocateUnknownNodeId(const std::string &name)
3146 {
3147         return m_nodedef->allocateDummy(name);
3148 }
3149 ISoundManager* Server::getSoundManager()
3150 {
3151         return &dummySoundManager;
3152 }
3153 MtEventManager* Server::getEventManager()
3154 {
3155         return m_event;
3156 }
3157
3158 IWritableItemDefManager* Server::getWritableItemDefManager()
3159 {
3160         return m_itemdef;
3161 }
3162 IWritableNodeDefManager* Server::getWritableNodeDefManager()
3163 {
3164         return m_nodedef;
3165 }
3166 IWritableCraftDefManager* Server::getWritableCraftDefManager()
3167 {
3168         return m_craftdef;
3169 }
3170
3171 const ModSpec* Server::getModSpec(const std::string &modname)
3172 {
3173         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3174                         i != m_mods.end(); i++){
3175                 const ModSpec &mod = *i;
3176                 if(mod.name == modname)
3177                         return &mod;
3178         }
3179         return NULL;
3180 }
3181 void Server::getModNames(std::vector<std::string> &modlist)
3182 {
3183         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++) {
3184                 modlist.push_back(i->name);
3185         }
3186 }
3187 std::string Server::getBuiltinLuaPath()
3188 {
3189         return porting::path_share + DIR_DELIM + "builtin";
3190 }
3191
3192 v3f findSpawnPos(ServerMap &map)
3193 {
3194         //return v3f(50,50,50)*BS;
3195
3196         v3s16 nodepos;
3197
3198 #if 0
3199         nodepos = v2s16(0,0);
3200         groundheight = 20;
3201 #endif
3202
3203 #if 1
3204         s16 water_level = map.getWaterLevel();
3205
3206         // Try to find a good place a few times
3207         for(s32 i=0; i<1000; i++)
3208         {
3209                 s32 range = 1 + i;
3210                 // We're going to try to throw the player to this position
3211                 v2s16 nodepos2d = v2s16(
3212                                 -range + (myrand() % (range * 2)),
3213                                 -range + (myrand() % (range * 2)));
3214
3215                 // Get ground height at point
3216                 s16 groundheight = map.findGroundLevel(nodepos2d);
3217                 if (groundheight <= water_level) // Don't go underwater
3218                         continue;
3219                 if (groundheight > water_level + 6) // Don't go to high places
3220                         continue;
3221
3222                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
3223                 bool is_good = false;
3224                 s32 air_count = 0;
3225                 for (s32 i = 0; i < 10; i++) {
3226                         v3s16 blockpos = getNodeBlockPos(nodepos);
3227                         map.emergeBlock(blockpos, true);
3228                         content_t c = map.getNodeNoEx(nodepos).getContent();
3229                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3230                                 air_count++;
3231                                 if (air_count >= 2){
3232                                         is_good = true;
3233                                         break;
3234                                 }
3235                         }
3236                         nodepos.Y++;
3237                 }
3238                 if(is_good){
3239                         // Found a good place
3240                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
3241                         break;
3242                 }
3243         }
3244 #endif
3245
3246         return intToFloat(nodepos, BS);
3247 }
3248
3249 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
3250 {
3251         bool newplayer = false;
3252
3253         /*
3254                 Try to get an existing player
3255         */
3256         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3257
3258         // If player is already connected, cancel
3259         if(player != NULL && player->peer_id != 0)
3260         {
3261                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3262                 return NULL;
3263         }
3264
3265         /*
3266                 If player with the wanted peer_id already exists, cancel.
3267         */
3268         if(m_env->getPlayer(peer_id) != NULL)
3269         {
3270                 infostream<<"emergePlayer(): Player with wrong name but same"
3271                                 " peer_id already exists"<<std::endl;
3272                 return NULL;
3273         }
3274
3275         // Load player if it isn't already loaded
3276         if (!player) {
3277                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3278         }
3279
3280         // Create player if it doesn't exist
3281         if (!player) {
3282                 newplayer = true;
3283                 player = new RemotePlayer(this, name);
3284                 // Set player position
3285                 infostream<<"Server: Finding spawn place for player \""
3286                                 <<name<<"\""<<std::endl;
3287                 v3f pos = findSpawnPos(m_env->getServerMap());
3288                 player->setPosition(pos);
3289
3290                 // Make sure the player is saved
3291                 player->setModified(true);
3292
3293                 // Add player to environment
3294                 m_env->addPlayer(player);
3295         }
3296
3297         // Create a new player active object
3298         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3299                         getPlayerEffectivePrivs(player->getName()),
3300                         isSingleplayer());
3301
3302         /* Clean up old HUD elements from previous sessions */
3303         player->clearHud();
3304
3305         /* Add object to environment */
3306         m_env->addActiveObject(playersao);
3307
3308         /* Run scripts */
3309         if (newplayer) {
3310                 m_script->on_newplayer(playersao);
3311         }
3312
3313         return playersao;
3314 }
3315
3316 void dedicated_server_loop(Server &server, bool &kill)
3317 {
3318         DSTACK(__FUNCTION_NAME);
3319
3320         verbosestream<<"dedicated_server_loop()"<<std::endl;
3321
3322         IntervalLimiter m_profiler_interval;
3323
3324         for(;;)
3325         {
3326                 float steplen = g_settings->getFloat("dedicated_server_step");
3327                 // This is kind of a hack but can be done like this
3328                 // because server.step() is very light
3329                 {
3330                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3331                         sleep_ms((int)(steplen*1000.0));
3332                 }
3333                 server.step(steplen);
3334
3335                 if(server.getShutdownRequested() || kill)
3336                 {
3337                         infostream<<"Dedicated server quitting"<<std::endl;
3338 #if USE_CURL
3339                         if(g_settings->getBool("server_announce"))
3340                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3341 #endif
3342                         break;
3343                 }
3344
3345                 /*
3346                         Profiler
3347                 */
3348                 float profiler_print_interval =
3349                                 g_settings->getFloat("profiler_print_interval");
3350                 if(profiler_print_interval != 0)
3351                 {
3352                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3353                         {
3354                                 infostream<<"Profiler:"<<std::endl;
3355                                 g_profiler->print(infostream);
3356                                 g_profiler->clear();
3357                         }
3358                 }
3359         }
3360 }
3361
3362