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