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