]> git.lizzy.rs Git - minetest.git/blob - src/server.cpp
Gracefully handle PacketErrors
[minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "jthread/jmutexautolock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_game.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_abm.h"
51 #include "content_sao.h"
52 #include "mods.h"
53 #include "sound.h" // dummySoundManager
54 #include "event_manager.h"
55 #include "serverlist.h"
56 #include "util/string.h"
57 #include "util/mathconstants.h"
58 #include "rollback.h"
59 #include "util/serialize.h"
60 #include "util/thread.h"
61 #include "defaultsettings.h"
62 #include "util/base64.h"
63 #include "util/sha1.h"
64 #include "util/hex.h"
65
66 class ClientNotFoundException : public BaseException
67 {
68 public:
69         ClientNotFoundException(const char *s):
70                 BaseException(s)
71         {}
72 };
73
74 class ServerThread : public JThread
75 {
76         Server *m_server;
77
78 public:
79
80         ServerThread(Server *server):
81                 JThread(),
82                 m_server(server)
83         {
84         }
85
86         void * Thread();
87 };
88
89 void * ServerThread::Thread()
90 {
91         log_register_thread("ServerThread");
92
93         DSTACK(__FUNCTION_NAME);
94         BEGIN_DEBUG_EXCEPTION_HANDLER
95
96         m_server->AsyncRunStep(true);
97
98         ThreadStarted();
99
100         porting::setThreadName("ServerThread");
101
102         while(!StopRequested())
103         {
104                 try{
105                         //TimeTaker timer("AsyncRunStep() + Receive()");
106
107                         m_server->AsyncRunStep();
108
109                         m_server->Receive();
110
111                 }
112                 catch(con::NoIncomingDataException &e)
113                 {
114                 }
115                 catch(con::PeerNotFoundException &e)
116                 {
117                         infostream<<"Server: PeerNotFoundException"<<std::endl;
118                 }
119                 catch(ClientNotFoundException &e)
120                 {
121                 }
122                 catch(con::ConnectionBindFailed &e)
123                 {
124                         m_server->setAsyncFatalError(e.what());
125                 }
126                 catch(LuaError &e)
127                 {
128                         m_server->setAsyncFatalError(e.what());
129                 }
130         }
131
132         END_DEBUG_EXCEPTION_HANDLER(errorstream)
133
134         return NULL;
135 }
136
137 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
138 {
139         if(pos_exists) *pos_exists = false;
140         switch(type){
141         case SSP_LOCAL:
142                 return v3f(0,0,0);
143         case SSP_POSITIONAL:
144                 if(pos_exists) *pos_exists = true;
145                 return pos;
146         case SSP_OBJECT: {
147                 if(object == 0)
148                         return v3f(0,0,0);
149                 ServerActiveObject *sao = env->getActiveObject(object);
150                 if(!sao)
151                         return v3f(0,0,0);
152                 if(pos_exists) *pos_exists = true;
153                 return sao->getBasePosition(); }
154         }
155         return v3f(0,0,0);
156 }
157
158
159
160 /*
161         Server
162 */
163
164 Server::Server(
165                 const std::string &path_world,
166                 const SubgameSpec &gamespec,
167                 bool simple_singleplayer_mode,
168                 bool ipv6
169         ):
170         m_path_world(path_world),
171         m_gamespec(gamespec),
172         m_simple_singleplayer_mode(simple_singleplayer_mode),
173         m_async_fatal_error(""),
174         m_env(NULL),
175         m_con(PROTOCOL_ID,
176                         512,
177                         CONNECTION_TIMEOUT,
178                         ipv6,
179                         this),
180         m_banmanager(NULL),
181         m_rollback(NULL),
182         m_enable_rollback_recording(false),
183         m_emerge(NULL),
184         m_script(NULL),
185         m_itemdef(createItemDefManager()),
186         m_nodedef(createNodeDefManager()),
187         m_craftdef(createCraftDefManager()),
188         m_event(new EventManager()),
189         m_thread(NULL),
190         m_time_of_day_send_timer(0),
191         m_uptime(0),
192         m_clients(&m_con),
193         m_shutdown_requested(false),
194         m_ignore_map_edit_events(false),
195         m_ignore_map_edit_events_peer_id(0),
196         m_next_sound_id(0)
197
198 {
199         m_liquid_transform_timer = 0.0;
200         m_liquid_transform_every = 1.0;
201         m_print_info_timer = 0.0;
202         m_masterserver_timer = 0.0;
203         m_objectdata_timer = 0.0;
204         m_emergethread_trigger_timer = 0.0;
205         m_savemap_timer = 0.0;
206
207         m_step_dtime = 0.0;
208         m_lag = g_settings->getFloat("dedicated_server_step");
209
210         if(path_world == "")
211                 throw ServerError("Supplied empty world path");
212
213         if(!gamespec.isValid())
214                 throw ServerError("Supplied invalid gamespec");
215
216         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
217         if(m_simple_singleplayer_mode)
218                 infostream<<" in simple singleplayer mode"<<std::endl;
219         else
220                 infostream<<std::endl;
221         infostream<<"- world:  "<<m_path_world<<std::endl;
222         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
223
224         // Create world if it doesn't exist
225         if(!loadGameConfAndInitWorld(m_path_world, m_gamespec))
226                 throw ServerError("Failed to initialize world");
227
228         // Create server thread
229         m_thread = new ServerThread(this);
230
231         // Create emerge manager
232         m_emerge = new EmergeManager(this);
233
234         // Create ban manager
235         std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
236         m_banmanager = new BanManager(ban_path);
237
238         ModConfiguration modconf(m_path_world);
239         m_mods = modconf.getMods();
240         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
241         // complain about mods with unsatisfied dependencies
242         if(!modconf.isConsistent())
243         {
244                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
245                         it != unsatisfied_mods.end(); ++it)
246                 {
247                         ModSpec mod = *it;
248                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
249                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
250                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
251                                 errorstream << " \"" << *dep_it << "\"";
252                         errorstream << std::endl;
253                 }
254         }
255
256         Settings worldmt_settings;
257         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
258         worldmt_settings.readConfigFile(worldmt.c_str());
259         std::vector<std::string> names = worldmt_settings.getNames();
260         std::set<std::string> load_mod_names;
261         for(std::vector<std::string>::iterator it = names.begin();
262                 it != names.end(); ++it)
263         {
264                 std::string name = *it;
265                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
266                         load_mod_names.insert(name.substr(9));
267         }
268         // complain about mods declared to be loaded, but not found
269         for(std::vector<ModSpec>::iterator it = m_mods.begin();
270                         it != m_mods.end(); ++it)
271                 load_mod_names.erase((*it).name);
272         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
273                         it != unsatisfied_mods.end(); ++it)
274                 load_mod_names.erase((*it).name);
275         if(!load_mod_names.empty())
276         {
277                 errorstream << "The following mods could not be found:";
278                 for(std::set<std::string>::iterator it = load_mod_names.begin();
279                         it != load_mod_names.end(); ++it)
280                         errorstream << " \"" << (*it) << "\"";
281                 errorstream << std::endl;
282         }
283
284         // Lock environment
285         JMutexAutoLock envlock(m_env_mutex);
286
287         // Load mapgen params from Settings
288         m_emerge->loadMapgenParams();
289
290         // Create the Map (loads map_meta.txt, overriding configured mapgen params)
291         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
292
293         // Initialize scripting
294         infostream<<"Server: Initializing Lua"<<std::endl;
295
296         m_script = new GameScripting(this);
297
298         std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
299
300         if (!m_script->loadScript(scriptpath))
301                 throw ModError("Failed to load and run " + scriptpath);
302
303         // Print 'em
304         infostream<<"Server: Loading mods: ";
305         for(std::vector<ModSpec>::iterator i = m_mods.begin();
306                         i != m_mods.end(); i++){
307                 const ModSpec &mod = *i;
308                 infostream<<mod.name<<" ";
309         }
310         infostream<<std::endl;
311         // Load and run "mod" scripts
312         for(std::vector<ModSpec>::iterator i = m_mods.begin();
313                         i != m_mods.end(); i++){
314                 const ModSpec &mod = *i;
315                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
316                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
317                                 <<scriptpath<<"\"]"<<std::endl;
318                 bool success = m_script->loadMod(scriptpath, mod.name);
319                 if(!success){
320                         errorstream<<"Server: Failed to load and run "
321                                         <<scriptpath<<std::endl;
322                         throw ModError("Failed to load and run "+scriptpath);
323                 }
324         }
325
326         // Read Textures and calculate sha1 sums
327         fillMediaCache();
328
329         // Apply item aliases in the node definition manager
330         m_nodedef->updateAliases(m_itemdef);
331
332         m_nodedef->setNodeRegistrationStatus(true);
333
334         // Perform pending node name resolutions
335         m_nodedef->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         } catch (SendFailedException &e) {
1231                 errorstream << "Server::ProcessData(): SendFailedException: "
1232                                 << "what=" << e.what()
1233                                 << std::endl;
1234         } catch (PacketError &e) {
1235                 actionstream << "Server::ProcessData(): PacketError: "
1236                                 << "what=" << e.what()
1237                                 << std::endl;
1238         }
1239 }
1240
1241 void Server::setTimeOfDay(u32 time)
1242 {
1243         m_env->setTimeOfDay(time);
1244         m_time_of_day_send_timer = 0;
1245 }
1246
1247 void Server::onMapEditEvent(MapEditEvent *event)
1248 {
1249         if(m_ignore_map_edit_events)
1250                 return;
1251         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1252                 return;
1253         MapEditEvent *e = event->clone();
1254         m_unsent_map_edit_queue.push(e);
1255 }
1256
1257 Inventory* Server::getInventory(const InventoryLocation &loc)
1258 {
1259         switch (loc.type) {
1260         case InventoryLocation::UNDEFINED:
1261         case InventoryLocation::CURRENT_PLAYER:
1262                 break;
1263         case InventoryLocation::PLAYER:
1264         {
1265                 Player *player = m_env->getPlayer(loc.name.c_str());
1266                 if(!player)
1267                         return NULL;
1268                 PlayerSAO *playersao = player->getPlayerSAO();
1269                 if(!playersao)
1270                         return NULL;
1271                 return playersao->getInventory();
1272         }
1273                 break;
1274         case InventoryLocation::NODEMETA:
1275         {
1276                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1277                 if(!meta)
1278                         return NULL;
1279                 return meta->getInventory();
1280         }
1281                 break;
1282         case InventoryLocation::DETACHED:
1283         {
1284                 if(m_detached_inventories.count(loc.name) == 0)
1285                         return NULL;
1286                 return m_detached_inventories[loc.name];
1287         }
1288                 break;
1289         default:
1290                 sanity_check(false); // abort
1291                 break;
1292         }
1293         return NULL;
1294 }
1295 void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
1296 {
1297         switch(loc.type){
1298         case InventoryLocation::UNDEFINED:
1299                 break;
1300         case InventoryLocation::PLAYER:
1301         {
1302                 if (!playerSend)
1303                         return;
1304
1305                 Player *player = m_env->getPlayer(loc.name.c_str());
1306                 if(!player)
1307                         return;
1308                 PlayerSAO *playersao = player->getPlayerSAO();
1309                 if(!playersao)
1310                         return;
1311
1312                 SendInventory(playersao);
1313         }
1314                 break;
1315         case InventoryLocation::NODEMETA:
1316         {
1317                 v3s16 blockpos = getNodeBlockPos(loc.p);
1318
1319                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1320                 if(block)
1321                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1322
1323                 setBlockNotSent(blockpos);
1324         }
1325                 break;
1326         case InventoryLocation::DETACHED:
1327         {
1328                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1329         }
1330                 break;
1331         default:
1332                 sanity_check(false); // abort
1333                 break;
1334         }
1335 }
1336
1337 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1338 {
1339         std::vector<u16> clients = m_clients.getClientIDs();
1340         m_clients.Lock();
1341         // Set the modified blocks unsent for all the clients
1342         for (std::vector<u16>::iterator i = clients.begin();
1343                  i != clients.end(); ++i) {
1344                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1345                                 client->SetBlocksNotSent(block);
1346         }
1347         m_clients.Unlock();
1348 }
1349
1350 void Server::peerAdded(con::Peer *peer)
1351 {
1352         DSTACK(__FUNCTION_NAME);
1353         verbosestream<<"Server::peerAdded(): peer->id="
1354                         <<peer->id<<std::endl;
1355
1356         con::PeerChange c;
1357         c.type = con::PEER_ADDED;
1358         c.peer_id = peer->id;
1359         c.timeout = false;
1360         m_peer_change_queue.push(c);
1361 }
1362
1363 void Server::deletingPeer(con::Peer *peer, bool timeout)
1364 {
1365         DSTACK(__FUNCTION_NAME);
1366         verbosestream<<"Server::deletingPeer(): peer->id="
1367                         <<peer->id<<", timeout="<<timeout<<std::endl;
1368
1369         m_clients.event(peer->id, CSE_Disconnect);
1370         con::PeerChange c;
1371         c.type = con::PEER_REMOVED;
1372         c.peer_id = peer->id;
1373         c.timeout = timeout;
1374         m_peer_change_queue.push(c);
1375 }
1376
1377 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1378 {
1379         *retval = m_con.getPeerStat(peer_id,type);
1380         if (*retval == -1) return false;
1381         return true;
1382 }
1383
1384 bool Server::getClientInfo(
1385                 u16          peer_id,
1386                 ClientState* state,
1387                 u32*         uptime,
1388                 u8*          ser_vers,
1389                 u16*         prot_vers,
1390                 u8*          major,
1391                 u8*          minor,
1392                 u8*          patch,
1393                 std::string* vers_string
1394         )
1395 {
1396         *state = m_clients.getClientState(peer_id);
1397         m_clients.Lock();
1398         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1399
1400         if (client == NULL) {
1401                 m_clients.Unlock();
1402                 return false;
1403         }
1404
1405         *uptime = client->uptime();
1406         *ser_vers = client->serialization_version;
1407         *prot_vers = client->net_proto_version;
1408
1409         *major = client->getMajor();
1410         *minor = client->getMinor();
1411         *patch = client->getPatch();
1412         *vers_string = client->getPatch();
1413
1414         m_clients.Unlock();
1415
1416         return true;
1417 }
1418
1419 void Server::handlePeerChanges()
1420 {
1421         while(m_peer_change_queue.size() > 0)
1422         {
1423                 con::PeerChange c = m_peer_change_queue.front();
1424                 m_peer_change_queue.pop();
1425
1426                 verbosestream<<"Server: Handling peer change: "
1427                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1428                                 <<std::endl;
1429
1430                 switch(c.type)
1431                 {
1432                 case con::PEER_ADDED:
1433                         m_clients.CreateClient(c.peer_id);
1434                         break;
1435
1436                 case con::PEER_REMOVED:
1437                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1438                         break;
1439
1440                 default:
1441                         FATAL_ERROR("Invalid peer change event received!");
1442                         break;
1443                 }
1444         }
1445 }
1446
1447 void Server::Send(NetworkPacket* pkt)
1448 {
1449         m_clients.send(pkt->getPeerId(),
1450                 clientCommandFactoryTable[pkt->getCommand()].channel,
1451                 pkt,
1452                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1453 }
1454
1455 void Server::SendMovement(u16 peer_id)
1456 {
1457         DSTACK(__FUNCTION_NAME);
1458         std::ostringstream os(std::ios_base::binary);
1459
1460         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1461
1462         pkt << g_settings->getFloat("movement_acceleration_default");
1463         pkt << g_settings->getFloat("movement_acceleration_air");
1464         pkt << g_settings->getFloat("movement_acceleration_fast");
1465         pkt << g_settings->getFloat("movement_speed_walk");
1466         pkt << g_settings->getFloat("movement_speed_crouch");
1467         pkt << g_settings->getFloat("movement_speed_fast");
1468         pkt << g_settings->getFloat("movement_speed_climb");
1469         pkt << g_settings->getFloat("movement_speed_jump");
1470         pkt << g_settings->getFloat("movement_liquid_fluidity");
1471         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1472         pkt << g_settings->getFloat("movement_liquid_sink");
1473         pkt << g_settings->getFloat("movement_gravity");
1474
1475         Send(&pkt);
1476 }
1477
1478 void Server::SendHP(u16 peer_id, u8 hp)
1479 {
1480         DSTACK(__FUNCTION_NAME);
1481
1482         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1483         pkt << hp;
1484         Send(&pkt);
1485 }
1486
1487 void Server::SendBreath(u16 peer_id, u16 breath)
1488 {
1489         DSTACK(__FUNCTION_NAME);
1490
1491         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1492         pkt << (u16) breath;
1493         Send(&pkt);
1494 }
1495
1496 void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
1497 {
1498         DSTACK(__FUNCTION_NAME);
1499
1500         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1501         pkt << (u8) reason;
1502
1503         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING) {
1504                 pkt << custom_reason;
1505         }
1506         Send(&pkt);
1507 }
1508
1509 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1510 {
1511         DSTACK(__FUNCTION_NAME);
1512
1513         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1514         pkt << reason;
1515         Send(&pkt);
1516 }
1517
1518 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1519                 v3f camera_point_target)
1520 {
1521         DSTACK(__FUNCTION_NAME);
1522
1523         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1524         pkt << set_camera_point_target << camera_point_target;
1525         Send(&pkt);
1526 }
1527
1528 void Server::SendItemDef(u16 peer_id,
1529                 IItemDefManager *itemdef, u16 protocol_version)
1530 {
1531         DSTACK(__FUNCTION_NAME);
1532
1533         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1534
1535         /*
1536                 u16 command
1537                 u32 length of the next item
1538                 zlib-compressed serialized ItemDefManager
1539         */
1540         std::ostringstream tmp_os(std::ios::binary);
1541         itemdef->serialize(tmp_os, protocol_version);
1542         std::ostringstream tmp_os2(std::ios::binary);
1543         compressZlib(tmp_os.str(), tmp_os2);
1544         pkt.putLongString(tmp_os2.str());
1545
1546         // Make data buffer
1547         verbosestream << "Server: Sending item definitions to id(" << peer_id
1548                         << "): size=" << pkt.getSize() << std::endl;
1549
1550         Send(&pkt);
1551 }
1552
1553 void Server::SendNodeDef(u16 peer_id,
1554                 INodeDefManager *nodedef, u16 protocol_version)
1555 {
1556         DSTACK(__FUNCTION_NAME);
1557
1558         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1559
1560         /*
1561                 u16 command
1562                 u32 length of the next item
1563                 zlib-compressed serialized NodeDefManager
1564         */
1565         std::ostringstream tmp_os(std::ios::binary);
1566         nodedef->serialize(tmp_os, protocol_version);
1567         std::ostringstream tmp_os2(std::ios::binary);
1568         compressZlib(tmp_os.str(), tmp_os2);
1569
1570         pkt.putLongString(tmp_os2.str());
1571
1572         // Make data buffer
1573         verbosestream << "Server: Sending node definitions to id(" << peer_id
1574                         << "): size=" << pkt.getSize() << std::endl;
1575
1576         Send(&pkt);
1577 }
1578
1579 /*
1580         Non-static send methods
1581 */
1582
1583 void Server::SendInventory(PlayerSAO* playerSAO)
1584 {
1585         DSTACK(__FUNCTION_NAME);
1586
1587         UpdateCrafting(playerSAO->getPlayer());
1588
1589         /*
1590                 Serialize it
1591         */
1592
1593         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1594
1595         std::ostringstream os;
1596         playerSAO->getInventory()->serialize(os);
1597
1598         std::string s = os.str();
1599
1600         pkt.putRawString(s.c_str(), s.size());
1601         Send(&pkt);
1602 }
1603
1604 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
1605 {
1606         DSTACK(__FUNCTION_NAME);
1607
1608         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1609         pkt << message;
1610
1611         if (peer_id != PEER_ID_INEXISTENT) {
1612                 Send(&pkt);
1613         }
1614         else {
1615                 m_clients.sendToAll(0, &pkt, true);
1616         }
1617 }
1618
1619 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1620                                      const std::string &formname)
1621 {
1622         DSTACK(__FUNCTION_NAME);
1623
1624         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1625
1626         pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1627         pkt << formname;
1628
1629         Send(&pkt);
1630 }
1631
1632 // Spawns a particle on peer with peer_id
1633 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
1634                                 float expirationtime, float size, bool collisiondetection,
1635                                 bool vertical, std::string texture)
1636 {
1637         DSTACK(__FUNCTION_NAME);
1638
1639         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1640
1641         pkt << pos << velocity << acceleration << expirationtime
1642                         << size << collisiondetection;
1643         pkt.putLongString(texture);
1644         pkt << vertical;
1645
1646         if (peer_id != PEER_ID_INEXISTENT) {
1647                 Send(&pkt);
1648         }
1649         else {
1650                 m_clients.sendToAll(0, &pkt, true);
1651         }
1652 }
1653
1654 // Adds a ParticleSpawner on peer with peer_id
1655 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
1656         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1657         float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
1658 {
1659         DSTACK(__FUNCTION_NAME);
1660
1661         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1662
1663         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1664                         << minacc << maxacc << minexptime << maxexptime << minsize
1665                         << maxsize << collisiondetection;
1666
1667         pkt.putLongString(texture);
1668
1669         pkt << id << vertical;
1670
1671         if (peer_id != PEER_ID_INEXISTENT) {
1672                 Send(&pkt);
1673         }
1674         else {
1675                 m_clients.sendToAll(0, &pkt, true);
1676         }
1677 }
1678
1679 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1680 {
1681         DSTACK(__FUNCTION_NAME);
1682
1683         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1684
1685         // Ugly error in this packet
1686         pkt << (u16) id;
1687
1688         if (peer_id != PEER_ID_INEXISTENT) {
1689                 Send(&pkt);
1690         }
1691         else {
1692                 m_clients.sendToAll(0, &pkt, true);
1693         }
1694
1695 }
1696
1697 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1698 {
1699         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1700
1701         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1702                         << form->text << form->number << form->item << form->dir
1703                         << form->align << form->offset << form->world_pos << form->size;
1704
1705         Send(&pkt);
1706 }
1707
1708 void Server::SendHUDRemove(u16 peer_id, u32 id)
1709 {
1710         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1711         pkt << id;
1712         Send(&pkt);
1713 }
1714
1715 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1716 {
1717         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1718         pkt << id << (u8) stat;
1719
1720         switch (stat) {
1721                 case HUD_STAT_POS:
1722                 case HUD_STAT_SCALE:
1723                 case HUD_STAT_ALIGN:
1724                 case HUD_STAT_OFFSET:
1725                         pkt << *(v2f *) value;
1726                         break;
1727                 case HUD_STAT_NAME:
1728                 case HUD_STAT_TEXT:
1729                         pkt << *(std::string *) value;
1730                         break;
1731                 case HUD_STAT_WORLD_POS:
1732                         pkt << *(v3f *) value;
1733                         break;
1734                 case HUD_STAT_SIZE:
1735                         pkt << *(v2s32 *) value;
1736                         break;
1737                 case HUD_STAT_NUMBER:
1738                 case HUD_STAT_ITEM:
1739                 case HUD_STAT_DIR:
1740                 default:
1741                         pkt << *(u32 *) value;
1742                         break;
1743         }
1744
1745         Send(&pkt);
1746 }
1747
1748 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1749 {
1750         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1751
1752         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1753
1754         pkt << flags << mask;
1755
1756         Send(&pkt);
1757 }
1758
1759 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1760 {
1761         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1762         pkt << param << value;
1763         Send(&pkt);
1764 }
1765
1766 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1767                 const std::string &type, const std::vector<std::string> &params)
1768 {
1769         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1770         pkt << bgcolor << type << (u16) params.size();
1771
1772         for(size_t i=0; i<params.size(); i++)
1773                 pkt << params[i];
1774
1775         Send(&pkt);
1776 }
1777
1778 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1779                 float ratio)
1780 {
1781         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1782                         1 + 2, peer_id);
1783
1784         pkt << do_override << (u16) (ratio * 65535);
1785
1786         Send(&pkt);
1787 }
1788
1789 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1790 {
1791         DSTACK(__FUNCTION_NAME);
1792
1793         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1794         pkt << time << time_speed;
1795
1796         if (peer_id == PEER_ID_INEXISTENT) {
1797                 m_clients.sendToAll(0, &pkt, true);
1798         }
1799         else {
1800                 Send(&pkt);
1801         }
1802 }
1803
1804 void Server::SendPlayerHP(u16 peer_id)
1805 {
1806         DSTACK(__FUNCTION_NAME);
1807         PlayerSAO *playersao = getPlayerSAO(peer_id);
1808         // In some rare case, if the player is disconnected
1809         // while Lua call l_punch, for example, this can be NULL
1810         if (!playersao)
1811                 return;
1812
1813         SendHP(peer_id, playersao->getHP());
1814         m_script->player_event(playersao,"health_changed");
1815
1816         // Send to other clients
1817         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1818         ActiveObjectMessage aom(playersao->getId(), true, str);
1819         playersao->m_messages_out.push(aom);
1820 }
1821
1822 void Server::SendPlayerBreath(u16 peer_id)
1823 {
1824         DSTACK(__FUNCTION_NAME);
1825         PlayerSAO *playersao = getPlayerSAO(peer_id);
1826         assert(playersao);
1827
1828         m_script->player_event(playersao, "breath_changed");
1829         SendBreath(peer_id, playersao->getBreath());
1830 }
1831
1832 void Server::SendMovePlayer(u16 peer_id)
1833 {
1834         DSTACK(__FUNCTION_NAME);
1835         Player *player = m_env->getPlayer(peer_id);
1836         assert(player);
1837
1838         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1839         pkt << player->getPosition() << player->getPitch() << player->getYaw();
1840
1841         {
1842                 v3f pos = player->getPosition();
1843                 f32 pitch = player->getPitch();
1844                 f32 yaw = player->getYaw();
1845                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1846                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1847                                 << " pitch=" << pitch
1848                                 << " yaw=" << yaw
1849                                 << std::endl;
1850         }
1851
1852         Send(&pkt);
1853 }
1854
1855 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1856 {
1857         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1858                 peer_id);
1859
1860         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1861                         << animation_frames[3] << animation_speed;
1862
1863         Send(&pkt);
1864 }
1865
1866 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1867 {
1868         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1869         pkt << first << third;
1870         Send(&pkt);
1871 }
1872 void Server::SendPlayerPrivileges(u16 peer_id)
1873 {
1874         Player *player = m_env->getPlayer(peer_id);
1875         assert(player);
1876         if(player->peer_id == PEER_ID_INEXISTENT)
1877                 return;
1878
1879         std::set<std::string> privs;
1880         m_script->getAuth(player->getName(), NULL, &privs);
1881
1882         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1883         pkt << (u16) privs.size();
1884
1885         for(std::set<std::string>::const_iterator i = privs.begin();
1886                         i != privs.end(); i++) {
1887                 pkt << (*i);
1888         }
1889
1890         Send(&pkt);
1891 }
1892
1893 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1894 {
1895         Player *player = m_env->getPlayer(peer_id);
1896         assert(player);
1897         if(player->peer_id == PEER_ID_INEXISTENT)
1898                 return;
1899
1900         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1901         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1902         Send(&pkt);
1903 }
1904
1905 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
1906 {
1907         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1908         pkt.putRawString(datas.c_str(), datas.size());
1909         Send(&pkt);
1910         return pkt.getSize();
1911 }
1912
1913 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
1914 {
1915         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1916                         datas.size(), peer_id);
1917
1918         pkt.putRawString(datas.c_str(), datas.size());
1919
1920         m_clients.send(pkt.getPeerId(),
1921                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1922                         &pkt, reliable);
1923
1924 }
1925
1926 s32 Server::playSound(const SimpleSoundSpec &spec,
1927                 const ServerSoundParams &params)
1928 {
1929         // Find out initial position of sound
1930         bool pos_exists = false;
1931         v3f pos = params.getPos(m_env, &pos_exists);
1932         // If position is not found while it should be, cancel sound
1933         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1934                 return -1;
1935
1936         // Filter destination clients
1937         std::vector<u16> dst_clients;
1938         if(params.to_player != "")
1939         {
1940                 Player *player = m_env->getPlayer(params.to_player.c_str());
1941                 if(!player){
1942                         infostream<<"Server::playSound: Player \""<<params.to_player
1943                                         <<"\" not found"<<std::endl;
1944                         return -1;
1945                 }
1946                 if(player->peer_id == PEER_ID_INEXISTENT){
1947                         infostream<<"Server::playSound: Player \""<<params.to_player
1948                                         <<"\" not connected"<<std::endl;
1949                         return -1;
1950                 }
1951                 dst_clients.push_back(player->peer_id);
1952         }
1953         else {
1954                 std::vector<u16> clients = m_clients.getClientIDs();
1955
1956                 for(std::vector<u16>::iterator
1957                                 i = clients.begin(); i != clients.end(); ++i) {
1958                         Player *player = m_env->getPlayer(*i);
1959                         if(!player)
1960                                 continue;
1961
1962                         if(pos_exists) {
1963                                 if(player->getPosition().getDistanceFrom(pos) >
1964                                                 params.max_hear_distance)
1965                                         continue;
1966                         }
1967                         dst_clients.push_back(*i);
1968                 }
1969         }
1970
1971         if(dst_clients.empty())
1972                 return -1;
1973
1974         // Create the sound
1975         s32 id = m_next_sound_id++;
1976         // The sound will exist as a reference in m_playing_sounds
1977         m_playing_sounds[id] = ServerPlayingSound();
1978         ServerPlayingSound &psound = m_playing_sounds[id];
1979         psound.params = params;
1980
1981         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
1982         pkt << id << spec.name << (float) (spec.gain * params.gain)
1983                         << (u8) params.type << pos << params.object << params.loop;
1984
1985         for(std::vector<u16>::iterator i = dst_clients.begin();
1986                         i != dst_clients.end(); i++) {
1987                 psound.clients.insert(*i);
1988                 m_clients.send(*i, 0, &pkt, true);
1989         }
1990         return id;
1991 }
1992 void Server::stopSound(s32 handle)
1993 {
1994         // Get sound reference
1995         std::map<s32, ServerPlayingSound>::iterator i =
1996                         m_playing_sounds.find(handle);
1997         if(i == m_playing_sounds.end())
1998                 return;
1999         ServerPlayingSound &psound = i->second;
2000
2001         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2002         pkt << handle;
2003
2004         for(std::set<u16>::iterator i = psound.clients.begin();
2005                         i != psound.clients.end(); i++) {
2006                 // Send as reliable
2007                 m_clients.send(*i, 0, &pkt, true);
2008         }
2009         // Remove sound reference
2010         m_playing_sounds.erase(i);
2011 }
2012
2013 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2014         std::vector<u16> *far_players, float far_d_nodes)
2015 {
2016         float maxd = far_d_nodes*BS;
2017         v3f p_f = intToFloat(p, BS);
2018
2019         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2020         pkt << p;
2021
2022         std::vector<u16> clients = m_clients.getClientIDs();
2023         for(std::vector<u16>::iterator i = clients.begin();
2024                 i != clients.end(); ++i) {
2025                 if (far_players) {
2026                         // Get player
2027                         if(Player *player = m_env->getPlayer(*i)) {
2028                                 // If player is far away, only set modified blocks not sent
2029                                 v3f player_pos = player->getPosition();
2030                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2031                                         far_players->push_back(*i);
2032                                         continue;
2033                                 }
2034                         }
2035                 }
2036
2037                 // Send as reliable
2038                 m_clients.send(*i, 0, &pkt, true);
2039         }
2040 }
2041
2042 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2043                 std::vector<u16> *far_players, float far_d_nodes,
2044                 bool remove_metadata)
2045 {
2046         float maxd = far_d_nodes*BS;
2047         v3f p_f = intToFloat(p, BS);
2048
2049         std::vector<u16> clients = m_clients.getClientIDs();
2050         for(std::vector<u16>::iterator i = clients.begin();
2051                         i != clients.end(); ++i) {
2052
2053                 if(far_players) {
2054                         // Get player
2055                         if(Player *player = m_env->getPlayer(*i)) {
2056                                 // If player is far away, only set modified blocks not sent
2057                                 v3f player_pos = player->getPosition();
2058                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2059                                         far_players->push_back(*i);
2060                                         continue;
2061                                 }
2062                         }
2063                 }
2064
2065                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2066                 m_clients.Lock();
2067                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2068                 if (client != 0) {
2069                         pkt << p << n.param0 << n.param1 << n.param2
2070                                         << (u8) (remove_metadata ? 0 : 1);
2071
2072                         if (!remove_metadata) {
2073                                 if (client->net_proto_version <= 21) {
2074                                         // Old clients always clear metadata; fix it
2075                                         // by sending the full block again.
2076                                         client->SetBlockNotSent(p);
2077                                 }
2078                         }
2079                 }
2080                 m_clients.Unlock();
2081
2082                 // Send as reliable
2083                 if (pkt.getSize() > 0)
2084                         m_clients.send(*i, 0, &pkt, true);
2085         }
2086 }
2087
2088 void Server::setBlockNotSent(v3s16 p)
2089 {
2090         std::vector<u16> clients = m_clients.getClientIDs();
2091         m_clients.Lock();
2092         for(std::vector<u16>::iterator i = clients.begin();
2093                 i != clients.end(); ++i) {
2094                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2095                 client->SetBlockNotSent(p);
2096         }
2097         m_clients.Unlock();
2098 }
2099
2100 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2101 {
2102         DSTACK(__FUNCTION_NAME);
2103
2104         v3s16 p = block->getPos();
2105
2106         /*
2107                 Create a packet with the block in the right format
2108         */
2109
2110         std::ostringstream os(std::ios_base::binary);
2111         block->serialize(os, ver, false);
2112         block->serializeNetworkSpecific(os, net_proto_version);
2113         std::string s = os.str();
2114
2115         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2116
2117         pkt << p;
2118         pkt.putRawString(s.c_str(), s.size());
2119         Send(&pkt);
2120 }
2121
2122 void Server::SendBlocks(float dtime)
2123 {
2124         DSTACK(__FUNCTION_NAME);
2125
2126         JMutexAutoLock envlock(m_env_mutex);
2127         //TODO check if one big lock could be faster then multiple small ones
2128
2129         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2130
2131         std::vector<PrioritySortedBlockTransfer> queue;
2132
2133         s32 total_sending = 0;
2134
2135         {
2136                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2137
2138                 std::vector<u16> clients = m_clients.getClientIDs();
2139
2140                 m_clients.Lock();
2141                 for(std::vector<u16>::iterator i = clients.begin();
2142                         i != clients.end(); ++i) {
2143                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2144
2145                         if (client == NULL)
2146                                 continue;
2147
2148                         total_sending += client->SendingCount();
2149                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2150                 }
2151                 m_clients.Unlock();
2152         }
2153
2154         // Sort.
2155         // Lowest priority number comes first.
2156         // Lowest is most important.
2157         std::sort(queue.begin(), queue.end());
2158
2159         m_clients.Lock();
2160         for(u32 i=0; i<queue.size(); i++)
2161         {
2162                 //TODO: Calculate limit dynamically
2163                 if(total_sending >= g_settings->getS32
2164                                 ("max_simultaneous_block_sends_server_total"))
2165                         break;
2166
2167                 PrioritySortedBlockTransfer q = queue[i];
2168
2169                 MapBlock *block = NULL;
2170                 try
2171                 {
2172                         block = m_env->getMap().getBlockNoCreate(q.pos);
2173                 }
2174                 catch(InvalidPositionException &e)
2175                 {
2176                         continue;
2177                 }
2178
2179                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2180
2181                 if(!client)
2182                         continue;
2183
2184                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2185
2186                 client->SentBlock(q.pos);
2187                 total_sending++;
2188         }
2189         m_clients.Unlock();
2190 }
2191
2192 void Server::fillMediaCache()
2193 {
2194         DSTACK(__FUNCTION_NAME);
2195
2196         infostream<<"Server: Calculating media file checksums"<<std::endl;
2197
2198         // Collect all media file paths
2199         std::vector<std::string> paths;
2200         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2201                         i != m_mods.end(); i++) {
2202                 const ModSpec &mod = *i;
2203                 paths.push_back(mod.path + DIR_DELIM + "textures");
2204                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2205                 paths.push_back(mod.path + DIR_DELIM + "media");
2206                 paths.push_back(mod.path + DIR_DELIM + "models");
2207         }
2208         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2209
2210         // Collect media file information from paths into cache
2211         for(std::vector<std::string>::iterator i = paths.begin();
2212                         i != paths.end(); i++) {
2213                 std::string mediapath = *i;
2214                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2215                 for (u32 j = 0; j < dirlist.size(); j++) {
2216                         if (dirlist[j].dir) // Ignode dirs
2217                                 continue;
2218                         std::string filename = dirlist[j].name;
2219                         // If name contains illegal characters, ignore the file
2220                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2221                                 infostream<<"Server: ignoring illegal file name: \""
2222                                                 << filename << "\"" << std::endl;
2223                                 continue;
2224                         }
2225                         // If name is not in a supported format, ignore it
2226                         const char *supported_ext[] = {
2227                                 ".png", ".jpg", ".bmp", ".tga",
2228                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2229                                 ".ogg",
2230                                 ".x", ".b3d", ".md2", ".obj",
2231                                 NULL
2232                         };
2233                         if (removeStringEnd(filename, supported_ext) == ""){
2234                                 infostream << "Server: ignoring unsupported file extension: \""
2235                                                 << filename << "\"" << std::endl;
2236                                 continue;
2237                         }
2238                         // Ok, attempt to load the file and add to cache
2239                         std::string filepath = mediapath + DIR_DELIM + filename;
2240                         // Read data
2241                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2242                         if (!fis.good()) {
2243                                 errorstream << "Server::fillMediaCache(): Could not open \""
2244                                                 << filename << "\" for reading" << std::endl;
2245                                 continue;
2246                         }
2247                         std::ostringstream tmp_os(std::ios_base::binary);
2248                         bool bad = false;
2249                         for(;;) {
2250                                 char buf[1024];
2251                                 fis.read(buf, 1024);
2252                                 std::streamsize len = fis.gcount();
2253                                 tmp_os.write(buf, len);
2254                                 if (fis.eof())
2255                                         break;
2256                                 if (!fis.good()) {
2257                                         bad = true;
2258                                         break;
2259                                 }
2260                         }
2261                         if(bad) {
2262                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2263                                                 << filename << "\"" << std::endl;
2264                                 continue;
2265                         }
2266                         if(tmp_os.str().length() == 0) {
2267                                 errorstream << "Server::fillMediaCache(): Empty file \""
2268                                                 << filepath << "\"" << std::endl;
2269                                 continue;
2270                         }
2271
2272                         SHA1 sha1;
2273                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2274
2275                         unsigned char *digest = sha1.getDigest();
2276                         std::string sha1_base64 = base64_encode(digest, 20);
2277                         std::string sha1_hex = hex_encode((char*)digest, 20);
2278                         free(digest);
2279
2280                         // Put in list
2281                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2282                         verbosestream << "Server: " << sha1_hex << " is " << filename
2283                                         << std::endl;
2284                 }
2285         }
2286 }
2287
2288 struct SendableMediaAnnouncement
2289 {
2290         std::string name;
2291         std::string sha1_digest;
2292
2293         SendableMediaAnnouncement(const std::string &name_="",
2294                                   const std::string &sha1_digest_=""):
2295                 name(name_),
2296                 sha1_digest(sha1_digest_)
2297         {}
2298 };
2299
2300 void Server::sendMediaAnnouncement(u16 peer_id)
2301 {
2302         DSTACK(__FUNCTION_NAME);
2303
2304         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
2305                         <<std::endl;
2306
2307         std::vector<SendableMediaAnnouncement> file_announcements;
2308
2309         for (std::map<std::string, MediaInfo>::iterator i = m_media.begin();
2310                         i != m_media.end(); i++){
2311                 // Put in list
2312                 file_announcements.push_back(
2313                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
2314         }
2315
2316         // Make packet
2317         std::ostringstream os(std::ios_base::binary);
2318
2319         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2320         pkt << (u16) file_announcements.size();
2321
2322         for (std::vector<SendableMediaAnnouncement>::iterator
2323                         j = file_announcements.begin();
2324                         j != file_announcements.end(); ++j) {
2325                 pkt << j->name << j->sha1_digest;
2326         }
2327
2328         pkt << g_settings->get("remote_media");
2329         Send(&pkt);
2330 }
2331
2332 struct SendableMedia
2333 {
2334         std::string name;
2335         std::string path;
2336         std::string data;
2337
2338         SendableMedia(const std::string &name_="", const std::string &path_="",
2339                       const std::string &data_=""):
2340                 name(name_),
2341                 path(path_),
2342                 data(data_)
2343         {}
2344 };
2345
2346 void Server::sendRequestedMedia(u16 peer_id,
2347                 const std::vector<std::string> &tosend)
2348 {
2349         DSTACK(__FUNCTION_NAME);
2350
2351         verbosestream<<"Server::sendRequestedMedia(): "
2352                         <<"Sending files to client"<<std::endl;
2353
2354         /* Read files */
2355
2356         // Put 5kB in one bunch (this is not accurate)
2357         u32 bytes_per_bunch = 5000;
2358
2359         std::vector< std::vector<SendableMedia> > file_bunches;
2360         file_bunches.push_back(std::vector<SendableMedia>());
2361
2362         u32 file_size_bunch_total = 0;
2363
2364         for(std::vector<std::string>::const_iterator i = tosend.begin();
2365                         i != tosend.end(); ++i) {
2366                 const std::string &name = *i;
2367
2368                 if(m_media.find(name) == m_media.end()) {
2369                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2370                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2371                         continue;
2372                 }
2373
2374                 //TODO get path + name
2375                 std::string tpath = m_media[name].path;
2376
2377                 // Read data
2378                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2379                 if(fis.good() == false){
2380                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2381                                         <<tpath<<"\" for reading"<<std::endl;
2382                         continue;
2383                 }
2384                 std::ostringstream tmp_os(std::ios_base::binary);
2385                 bool bad = false;
2386                 for(;;) {
2387                         char buf[1024];
2388                         fis.read(buf, 1024);
2389                         std::streamsize len = fis.gcount();
2390                         tmp_os.write(buf, len);
2391                         file_size_bunch_total += len;
2392                         if(fis.eof())
2393                                 break;
2394                         if(!fis.good()) {
2395                                 bad = true;
2396                                 break;
2397                         }
2398                 }
2399                 if(bad) {
2400                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2401                                         <<name<<"\""<<std::endl;
2402                         continue;
2403                 }
2404                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2405                                 <<tname<<"\""<<std::endl;*/
2406                 // Put in list
2407                 file_bunches[file_bunches.size()-1].push_back(
2408                                 SendableMedia(name, tpath, tmp_os.str()));
2409
2410                 // Start next bunch if got enough data
2411                 if(file_size_bunch_total >= bytes_per_bunch) {
2412                         file_bunches.push_back(std::vector<SendableMedia>());
2413                         file_size_bunch_total = 0;
2414                 }
2415
2416         }
2417
2418         /* Create and send packets */
2419
2420         u16 num_bunches = file_bunches.size();
2421         for(u16 i = 0; i < num_bunches; i++) {
2422                 /*
2423                         u16 command
2424                         u16 total number of texture bunches
2425                         u16 index of this bunch
2426                         u32 number of files in this bunch
2427                         for each file {
2428                                 u16 length of name
2429                                 string name
2430                                 u32 length of data
2431                                 data
2432                         }
2433                 */
2434
2435                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2436                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2437
2438                 for(std::vector<SendableMedia>::iterator
2439                                 j = file_bunches[i].begin();
2440                                 j != file_bunches[i].end(); ++j) {
2441                         pkt << j->name;
2442                         pkt.putLongString(j->data);
2443                 }
2444
2445                 verbosestream << "Server::sendRequestedMedia(): bunch "
2446                                 << i << "/" << num_bunches
2447                                 << " files=" << file_bunches[i].size()
2448                                 << " size="  << pkt.getSize() << std::endl;
2449                 Send(&pkt);
2450         }
2451 }
2452
2453 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2454 {
2455         if(m_detached_inventories.count(name) == 0) {
2456                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2457                 return;
2458         }
2459         Inventory *inv = m_detached_inventories[name];
2460         std::ostringstream os(std::ios_base::binary);
2461
2462         os << serializeString(name);
2463         inv->serialize(os);
2464
2465         // Make data buffer
2466         std::string s = os.str();
2467
2468         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2469         pkt.putRawString(s.c_str(), s.size());
2470
2471         if (peer_id != PEER_ID_INEXISTENT) {
2472                 Send(&pkt);
2473         }
2474         else {
2475                 m_clients.sendToAll(0, &pkt, true);
2476         }
2477 }
2478
2479 void Server::sendDetachedInventories(u16 peer_id)
2480 {
2481         DSTACK(__FUNCTION_NAME);
2482
2483         for(std::map<std::string, Inventory*>::iterator
2484                         i = m_detached_inventories.begin();
2485                         i != m_detached_inventories.end(); i++) {
2486                 const std::string &name = i->first;
2487                 //Inventory *inv = i->second;
2488                 sendDetachedInventory(name, peer_id);
2489         }
2490 }
2491
2492 /*
2493         Something random
2494 */
2495
2496 void Server::DiePlayer(u16 peer_id)
2497 {
2498         DSTACK(__FUNCTION_NAME);
2499
2500         PlayerSAO *playersao = getPlayerSAO(peer_id);
2501         assert(playersao);
2502
2503         infostream << "Server::DiePlayer(): Player "
2504                         << playersao->getPlayer()->getName()
2505                         << " dies" << std::endl;
2506
2507         playersao->setHP(0);
2508
2509         // Trigger scripted stuff
2510         m_script->on_dieplayer(playersao);
2511
2512         SendPlayerHP(peer_id);
2513         SendDeathscreen(peer_id, false, v3f(0,0,0));
2514 }
2515
2516 void Server::RespawnPlayer(u16 peer_id)
2517 {
2518         DSTACK(__FUNCTION_NAME);
2519
2520         PlayerSAO *playersao = getPlayerSAO(peer_id);
2521         assert(playersao);
2522
2523         infostream << "Server::RespawnPlayer(): Player "
2524                         << playersao->getPlayer()->getName()
2525                         << " respawns" << std::endl;
2526
2527         playersao->setHP(PLAYER_MAX_HP);
2528         playersao->setBreath(PLAYER_MAX_BREATH);
2529
2530         SendPlayerHP(peer_id);
2531         SendPlayerBreath(peer_id);
2532
2533         bool repositioned = m_script->on_respawnplayer(playersao);
2534         if(!repositioned){
2535                 v3f pos = findSpawnPos();
2536                 // setPos will send the new position to client
2537                 playersao->setPos(pos);
2538         }
2539 }
2540
2541 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2542 {
2543         DSTACK(__FUNCTION_NAME);
2544
2545         SendAccessDenied(peer_id, reason, custom_reason);
2546         m_clients.event(peer_id, CSE_SetDenied);
2547         m_con.DisconnectPeer(peer_id);
2548 }
2549
2550 // 13/03/15: remove this function when protocol version 25 will become
2551 // the minimum version for MT users, maybe in 1 year
2552 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2553 {
2554         DSTACK(__FUNCTION_NAME);
2555
2556         SendAccessDenied_Legacy(peer_id, reason);
2557         m_clients.event(peer_id, CSE_SetDenied);
2558         m_con.DisconnectPeer(peer_id);
2559 }
2560
2561 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2562 {
2563         DSTACK(__FUNCTION_NAME);
2564         std::wstring message;
2565         {
2566                 /*
2567                         Clear references to playing sounds
2568                 */
2569                 for(std::map<s32, ServerPlayingSound>::iterator
2570                                 i = m_playing_sounds.begin();
2571                                 i != m_playing_sounds.end();)
2572                 {
2573                         ServerPlayingSound &psound = i->second;
2574                         psound.clients.erase(peer_id);
2575                         if(psound.clients.empty())
2576                                 m_playing_sounds.erase(i++);
2577                         else
2578                                 i++;
2579                 }
2580
2581                 Player *player = m_env->getPlayer(peer_id);
2582
2583                 // Collect information about leaving in chat
2584                 {
2585                         if(player != NULL && reason != CDR_DENY)
2586                         {
2587                                 std::wstring name = narrow_to_wide(player->getName());
2588                                 message += L"*** ";
2589                                 message += name;
2590                                 message += L" left the game.";
2591                                 if(reason == CDR_TIMEOUT)
2592                                         message += L" (timed out)";
2593                         }
2594                 }
2595
2596                 /* Run scripts and remove from environment */
2597                 {
2598                         if(player != NULL)
2599                         {
2600                                 PlayerSAO *playersao = player->getPlayerSAO();
2601                                 assert(playersao);
2602
2603                                 m_script->on_leaveplayer(playersao);
2604
2605                                 playersao->disconnected();
2606                         }
2607                 }
2608
2609                 /*
2610                         Print out action
2611                 */
2612                 {
2613                         if(player != NULL && reason != CDR_DENY) {
2614                                 std::ostringstream os(std::ios_base::binary);
2615                                 std::vector<u16> clients = m_clients.getClientIDs();
2616
2617                                 for(std::vector<u16>::iterator i = clients.begin();
2618                                         i != clients.end(); ++i) {
2619                                         // Get player
2620                                         Player *player = m_env->getPlayer(*i);
2621                                         if(!player)
2622                                                 continue;
2623
2624                                         // Get name of player
2625                                         os << player->getName() << " ";
2626                                 }
2627
2628                                 actionstream << player->getName() << " "
2629                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2630                                                 << " List of players: " << os.str() << std::endl;
2631                         }
2632                 }
2633                 {
2634                         JMutexAutoLock env_lock(m_env_mutex);
2635                         m_clients.DeleteClient(peer_id);
2636                 }
2637         }
2638
2639         // Send leave chat message to all remaining clients
2640         if(message.length() != 0)
2641                 SendChatMessage(PEER_ID_INEXISTENT,message);
2642 }
2643
2644 void Server::UpdateCrafting(Player* player)
2645 {
2646         DSTACK(__FUNCTION_NAME);
2647
2648         // Get a preview for crafting
2649         ItemStack preview;
2650         InventoryLocation loc;
2651         loc.setPlayer(player->getName());
2652         getCraftingResult(&player->inventory, preview, false, this);
2653         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
2654
2655         // Put the new preview in
2656         InventoryList *plist = player->inventory.getList("craftpreview");
2657         sanity_check(plist);
2658         sanity_check(plist->getSize() >= 1);
2659         plist->changeItem(0, preview);
2660 }
2661
2662 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2663 {
2664         RemoteClient *client = getClientNoEx(peer_id,state_min);
2665         if(!client)
2666                 throw ClientNotFoundException("Client not found");
2667
2668         return client;
2669 }
2670 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2671 {
2672         return m_clients.getClientNoEx(peer_id, state_min);
2673 }
2674
2675 std::string Server::getPlayerName(u16 peer_id)
2676 {
2677         Player *player = m_env->getPlayer(peer_id);
2678         if(player == NULL)
2679                 return "[id="+itos(peer_id)+"]";
2680         return player->getName();
2681 }
2682
2683 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2684 {
2685         Player *player = m_env->getPlayer(peer_id);
2686         if(player == NULL)
2687                 return NULL;
2688         return player->getPlayerSAO();
2689 }
2690
2691 std::wstring Server::getStatusString()
2692 {
2693         std::wostringstream os(std::ios_base::binary);
2694         os<<L"# Server: ";
2695         // Version
2696         os<<L"version="<<narrow_to_wide(g_version_string);
2697         // Uptime
2698         os<<L", uptime="<<m_uptime.get();
2699         // Max lag estimate
2700         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2701         // Information about clients
2702         bool first = true;
2703         os<<L", clients={";
2704         std::vector<u16> clients = m_clients.getClientIDs();
2705         for(std::vector<u16>::iterator i = clients.begin();
2706                 i != clients.end(); ++i) {
2707                 // Get player
2708                 Player *player = m_env->getPlayer(*i);
2709                 // Get name of player
2710                 std::wstring name = L"unknown";
2711                 if(player != NULL)
2712                         name = narrow_to_wide(player->getName());
2713                 // Add name to information string
2714                 if(!first)
2715                         os << L", ";
2716                 else
2717                         first = false;
2718                 os << name;
2719         }
2720         os << L"}";
2721         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2722                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2723         if(g_settings->get("motd") != "")
2724                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2725         return os.str();
2726 }
2727
2728 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2729 {
2730         std::set<std::string> privs;
2731         m_script->getAuth(name, NULL, &privs);
2732         return privs;
2733 }
2734
2735 bool Server::checkPriv(const std::string &name, const std::string &priv)
2736 {
2737         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2738         return (privs.count(priv) != 0);
2739 }
2740
2741 void Server::reportPrivsModified(const std::string &name)
2742 {
2743         if(name == "") {
2744                 std::vector<u16> clients = m_clients.getClientIDs();
2745                 for(std::vector<u16>::iterator i = clients.begin();
2746                                 i != clients.end(); ++i) {
2747                         Player *player = m_env->getPlayer(*i);
2748                         reportPrivsModified(player->getName());
2749                 }
2750         } else {
2751                 Player *player = m_env->getPlayer(name.c_str());
2752                 if(!player)
2753                         return;
2754                 SendPlayerPrivileges(player->peer_id);
2755                 PlayerSAO *sao = player->getPlayerSAO();
2756                 if(!sao)
2757                         return;
2758                 sao->updatePrivileges(
2759                                 getPlayerEffectivePrivs(name),
2760                                 isSingleplayer());
2761         }
2762 }
2763
2764 void Server::reportInventoryFormspecModified(const std::string &name)
2765 {
2766         Player *player = m_env->getPlayer(name.c_str());
2767         if(!player)
2768                 return;
2769         SendPlayerInventoryFormspec(player->peer_id);
2770 }
2771
2772 void Server::setIpBanned(const std::string &ip, const std::string &name)
2773 {
2774         m_banmanager->add(ip, name);
2775 }
2776
2777 void Server::unsetIpBanned(const std::string &ip_or_name)
2778 {
2779         m_banmanager->remove(ip_or_name);
2780 }
2781
2782 std::string Server::getBanDescription(const std::string &ip_or_name)
2783 {
2784         return m_banmanager->getBanDescription(ip_or_name);
2785 }
2786
2787 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2788 {
2789         Player *player = m_env->getPlayer(name);
2790         if(!player)
2791                 return;
2792
2793         if (player->peer_id == PEER_ID_INEXISTENT)
2794                 return;
2795
2796         SendChatMessage(player->peer_id, msg);
2797 }
2798
2799 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
2800 {
2801         Player *player = m_env->getPlayer(playername);
2802
2803         if(!player)
2804         {
2805                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
2806                 return false;
2807         }
2808
2809         SendShowFormspecMessage(player->peer_id, formspec, formname);
2810         return true;
2811 }
2812
2813 u32 Server::hudAdd(Player *player, HudElement *form) {
2814         if (!player)
2815                 return -1;
2816
2817         u32 id = player->addHud(form);
2818
2819         SendHUDAdd(player->peer_id, id, form);
2820
2821         return id;
2822 }
2823
2824 bool Server::hudRemove(Player *player, u32 id) {
2825         if (!player)
2826                 return false;
2827
2828         HudElement* todel = player->removeHud(id);
2829
2830         if (!todel)
2831                 return false;
2832
2833         delete todel;
2834
2835         SendHUDRemove(player->peer_id, id);
2836         return true;
2837 }
2838
2839 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
2840         if (!player)
2841                 return false;
2842
2843         SendHUDChange(player->peer_id, id, stat, data);
2844         return true;
2845 }
2846
2847 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
2848         if (!player)
2849                 return false;
2850
2851         SendHUDSetFlags(player->peer_id, flags, mask);
2852         player->hud_flags = flags;
2853
2854         PlayerSAO* playersao = player->getPlayerSAO();
2855
2856         if (playersao == NULL)
2857                 return false;
2858
2859         m_script->player_event(playersao, "hud_changed");
2860         return true;
2861 }
2862
2863 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
2864         if (!player)
2865                 return false;
2866         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
2867                 return false;
2868
2869         std::ostringstream os(std::ios::binary);
2870         writeS32(os, hotbar_itemcount);
2871         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
2872         return true;
2873 }
2874
2875 void Server::hudSetHotbarImage(Player *player, std::string name) {
2876         if (!player)
2877                 return;
2878
2879         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
2880 }
2881
2882 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
2883         if (!player)
2884                 return;
2885
2886         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
2887 }
2888
2889 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
2890 {
2891         if (!player)
2892                 return false;
2893
2894         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
2895         return true;
2896 }
2897
2898 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
2899 {
2900         if (!player)
2901                 return false;
2902
2903         SendEyeOffset(player->peer_id, first, third);
2904         return true;
2905 }
2906
2907 bool Server::setSky(Player *player, const video::SColor &bgcolor,
2908                 const std::string &type, const std::vector<std::string> &params)
2909 {
2910         if (!player)
2911                 return false;
2912
2913         SendSetSky(player->peer_id, bgcolor, type, params);
2914         return true;
2915 }
2916
2917 bool Server::overrideDayNightRatio(Player *player, bool do_override,
2918                 float ratio)
2919 {
2920         if (!player)
2921                 return false;
2922
2923         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
2924         return true;
2925 }
2926
2927 void Server::notifyPlayers(const std::wstring &msg)
2928 {
2929         SendChatMessage(PEER_ID_INEXISTENT,msg);
2930 }
2931
2932 void Server::spawnParticle(const char *playername, v3f pos,
2933                 v3f velocity, v3f acceleration,
2934                 float expirationtime, float size, bool
2935                 collisiondetection, bool vertical, std::string texture)
2936 {
2937         Player *player = m_env->getPlayer(playername);
2938         if(!player)
2939                 return;
2940         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
2941                         expirationtime, size, collisiondetection, vertical, texture);
2942 }
2943
2944 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
2945                 float expirationtime, float size,
2946                 bool collisiondetection, bool vertical, std::string texture)
2947 {
2948         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
2949                         expirationtime, size, collisiondetection, vertical, texture);
2950 }
2951
2952 u32 Server::addParticleSpawner(const char *playername,
2953                 u16 amount, float spawntime,
2954                 v3f minpos, v3f maxpos,
2955                 v3f minvel, v3f maxvel,
2956                 v3f minacc, v3f maxacc,
2957                 float minexptime, float maxexptime,
2958                 float minsize, float maxsize,
2959                 bool collisiondetection, bool vertical, std::string texture)
2960 {
2961         Player *player = m_env->getPlayer(playername);
2962         if(!player)
2963                 return -1;
2964
2965         u32 id = 0;
2966         for(;;) // look for unused particlespawner id
2967         {
2968                 id++;
2969                 if (std::find(m_particlespawner_ids.begin(),
2970                                 m_particlespawner_ids.end(), id)
2971                                 == m_particlespawner_ids.end())
2972                 {
2973                         m_particlespawner_ids.push_back(id);
2974                         break;
2975                 }
2976         }
2977
2978         SendAddParticleSpawner(player->peer_id, amount, spawntime,
2979                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
2980                 minexptime, maxexptime, minsize, maxsize,
2981                 collisiondetection, vertical, texture, id);
2982
2983         return id;
2984 }
2985
2986 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
2987                 v3f minpos, v3f maxpos,
2988                 v3f minvel, v3f maxvel,
2989                 v3f minacc, v3f maxacc,
2990                 float minexptime, float maxexptime,
2991                 float minsize, float maxsize,
2992                 bool collisiondetection, bool vertical, std::string texture)
2993 {
2994         u32 id = 0;
2995         for(;;) // look for unused particlespawner id
2996         {
2997                 id++;
2998                 if (std::find(m_particlespawner_ids.begin(),
2999                                 m_particlespawner_ids.end(), id)
3000                                 == m_particlespawner_ids.end())
3001                 {
3002                         m_particlespawner_ids.push_back(id);
3003                         break;
3004                 }
3005         }
3006
3007         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
3008                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3009                 minexptime, maxexptime, minsize, maxsize,
3010                 collisiondetection, vertical, texture, id);
3011
3012         return id;
3013 }
3014
3015 void Server::deleteParticleSpawner(const char *playername, u32 id)
3016 {
3017         Player *player = m_env->getPlayer(playername);
3018         if(!player)
3019                 return;
3020
3021         m_particlespawner_ids.erase(
3022                         std::remove(m_particlespawner_ids.begin(),
3023                         m_particlespawner_ids.end(), id),
3024                         m_particlespawner_ids.end());
3025         SendDeleteParticleSpawner(player->peer_id, id);
3026 }
3027
3028 void Server::deleteParticleSpawnerAll(u32 id)
3029 {
3030         m_particlespawner_ids.erase(
3031                         std::remove(m_particlespawner_ids.begin(),
3032                         m_particlespawner_ids.end(), id),
3033                         m_particlespawner_ids.end());
3034         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3035 }
3036
3037 Inventory* Server::createDetachedInventory(const std::string &name)
3038 {
3039         if(m_detached_inventories.count(name) > 0){
3040                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3041                 delete m_detached_inventories[name];
3042         } else {
3043                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3044         }
3045         Inventory *inv = new Inventory(m_itemdef);
3046         sanity_check(inv);
3047         m_detached_inventories[name] = inv;
3048         //TODO find a better way to do this
3049         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3050         return inv;
3051 }
3052
3053 class BoolScopeSet
3054 {
3055 public:
3056         BoolScopeSet(bool *dst, bool val):
3057                 m_dst(dst)
3058         {
3059                 m_orig_state = *m_dst;
3060                 *m_dst = val;
3061         }
3062         ~BoolScopeSet()
3063         {
3064                 *m_dst = m_orig_state;
3065         }
3066 private:
3067         bool *m_dst;
3068         bool m_orig_state;
3069 };
3070
3071 // actions: time-reversed list
3072 // Return value: success/failure
3073 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3074                 std::list<std::string> *log)
3075 {
3076         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3077         ServerMap *map = (ServerMap*)(&m_env->getMap());
3078
3079         // Fail if no actions to handle
3080         if(actions.empty()){
3081                 log->push_back("Nothing to do.");
3082                 return false;
3083         }
3084
3085         int num_tried = 0;
3086         int num_failed = 0;
3087
3088         for(std::list<RollbackAction>::const_iterator
3089                         i = actions.begin();
3090                         i != actions.end(); i++)
3091         {
3092                 const RollbackAction &action = *i;
3093                 num_tried++;
3094                 bool success = action.applyRevert(map, this, this);
3095                 if(!success){
3096                         num_failed++;
3097                         std::ostringstream os;
3098                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3099                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3100                         if(log)
3101                                 log->push_back(os.str());
3102                 }else{
3103                         std::ostringstream os;
3104                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3105                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3106                         if(log)
3107                                 log->push_back(os.str());
3108                 }
3109         }
3110
3111         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3112                         <<" failed"<<std::endl;
3113
3114         // Call it done if less than half failed
3115         return num_failed <= num_tried/2;
3116 }
3117
3118 // IGameDef interface
3119 // Under envlock
3120 IItemDefManager* Server::getItemDefManager()
3121 {
3122         return m_itemdef;
3123 }
3124 INodeDefManager* Server::getNodeDefManager()
3125 {
3126         return m_nodedef;
3127 }
3128 ICraftDefManager* Server::getCraftDefManager()
3129 {
3130         return m_craftdef;
3131 }
3132 ITextureSource* Server::getTextureSource()
3133 {
3134         return NULL;
3135 }
3136 IShaderSource* Server::getShaderSource()
3137 {
3138         return NULL;
3139 }
3140 scene::ISceneManager* Server::getSceneManager()
3141 {
3142         return NULL;
3143 }
3144
3145 u16 Server::allocateUnknownNodeId(const std::string &name)
3146 {
3147         return m_nodedef->allocateDummy(name);
3148 }
3149 ISoundManager* Server::getSoundManager()
3150 {
3151         return &dummySoundManager;
3152 }
3153 MtEventManager* Server::getEventManager()
3154 {
3155         return m_event;
3156 }
3157
3158 IWritableItemDefManager* Server::getWritableItemDefManager()
3159 {
3160         return m_itemdef;
3161 }
3162 IWritableNodeDefManager* Server::getWritableNodeDefManager()
3163 {
3164         return m_nodedef;
3165 }
3166 IWritableCraftDefManager* Server::getWritableCraftDefManager()
3167 {
3168         return m_craftdef;
3169 }
3170
3171 const ModSpec* Server::getModSpec(const std::string &modname)
3172 {
3173         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3174                         i != m_mods.end(); i++){
3175                 const ModSpec &mod = *i;
3176                 if(mod.name == modname)
3177                         return &mod;
3178         }
3179         return NULL;
3180 }
3181 void Server::getModNames(std::vector<std::string> &modlist)
3182 {
3183         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++) {
3184                 modlist.push_back(i->name);
3185         }
3186 }
3187 std::string Server::getBuiltinLuaPath()
3188 {
3189         return porting::path_share + DIR_DELIM + "builtin";
3190 }
3191
3192 v3f Server::findSpawnPos()
3193 {
3194         ServerMap &map = m_env->getServerMap();
3195         v3f nodeposf;
3196         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3197                 return nodeposf * BS;
3198         }
3199
3200         // Default position is static_spawnpoint
3201         // We will return it if we don't found a good place
3202         v3s16 nodepos(nodeposf.X, nodeposf.Y, nodeposf.Z);
3203
3204         s16 water_level = map.getWaterLevel();
3205
3206         bool is_good = false;
3207
3208         // Try to find a good place a few times
3209         for(s32 i = 0; i < 1000 && !is_good; i++) {
3210                 s32 range = 1 + i;
3211                 // We're going to try to throw the player to this position
3212                 v2s16 nodepos2d = v2s16(
3213                                 -range + (myrand() % (range * 2)),
3214                                 -range + (myrand() % (range * 2)));
3215
3216                 // Get ground height at point
3217                 s16 groundheight = map.findGroundLevel(nodepos2d);
3218                 if (groundheight <= water_level) // Don't go underwater
3219                         continue;
3220                 if (groundheight > water_level + 6) // Don't go to high places
3221                         continue;
3222
3223                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
3224
3225                 s32 air_count = 0;
3226                 for (s32 i = 0; i < 10; i++) {
3227                         v3s16 blockpos = getNodeBlockPos(nodepos);
3228                         map.emergeBlock(blockpos, true);
3229                         content_t c = map.getNodeNoEx(nodepos).getContent();
3230                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3231                                 air_count++;
3232                                 if (air_count >= 2){
3233                                         is_good = true;
3234                                         break;
3235                                 }
3236                         }
3237                         nodepos.Y++;
3238                 }
3239         }
3240
3241         return intToFloat(nodepos, BS);
3242 }
3243
3244 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
3245 {
3246         bool newplayer = false;
3247
3248         /*
3249                 Try to get an existing player
3250         */
3251         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3252
3253         // If player is already connected, cancel
3254         if(player != NULL && player->peer_id != 0)
3255         {
3256                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3257                 return NULL;
3258         }
3259
3260         /*
3261                 If player with the wanted peer_id already exists, cancel.
3262         */
3263         if(m_env->getPlayer(peer_id) != NULL)
3264         {
3265                 infostream<<"emergePlayer(): Player with wrong name but same"
3266                                 " peer_id already exists"<<std::endl;
3267                 return NULL;
3268         }
3269
3270         // Load player if it isn't already loaded
3271         if (!player) {
3272                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3273         }
3274
3275         // Create player if it doesn't exist
3276         if (!player) {
3277                 newplayer = true;
3278                 player = new RemotePlayer(this, name);
3279                 // Set player position
3280                 infostream<<"Server: Finding spawn place for player \""
3281                                 <<name<<"\""<<std::endl;
3282                 v3f pos = findSpawnPos();
3283                 player->setPosition(pos);
3284
3285                 // Make sure the player is saved
3286                 player->setModified(true);
3287
3288                 // Add player to environment
3289                 m_env->addPlayer(player);
3290         }
3291
3292         // Create a new player active object
3293         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3294                         getPlayerEffectivePrivs(player->getName()),
3295                         isSingleplayer());
3296
3297         /* Clean up old HUD elements from previous sessions */
3298         player->clearHud();
3299
3300         /* Add object to environment */
3301         m_env->addActiveObject(playersao);
3302
3303         /* Run scripts */
3304         if (newplayer) {
3305                 m_script->on_newplayer(playersao);
3306         }
3307
3308         return playersao;
3309 }
3310
3311 void dedicated_server_loop(Server &server, bool &kill)
3312 {
3313         DSTACK(__FUNCTION_NAME);
3314
3315         verbosestream<<"dedicated_server_loop()"<<std::endl;
3316
3317         IntervalLimiter m_profiler_interval;
3318
3319         for(;;)
3320         {
3321                 float steplen = g_settings->getFloat("dedicated_server_step");
3322                 // This is kind of a hack but can be done like this
3323                 // because server.step() is very light
3324                 {
3325                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3326                         sleep_ms((int)(steplen*1000.0));
3327                 }
3328                 server.step(steplen);
3329
3330                 if(server.getShutdownRequested() || kill)
3331                 {
3332                         infostream<<"Dedicated server quitting"<<std::endl;
3333 #if USE_CURL
3334                         if(g_settings->getBool("server_announce"))
3335                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3336 #endif
3337                         break;
3338                 }
3339
3340                 /*
3341                         Profiler
3342                 */
3343                 float profiler_print_interval =
3344                                 g_settings->getFloat("profiler_print_interval");
3345                 if(profiler_print_interval != 0)
3346                 {
3347                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3348                         {
3349                                 infostream<<"Profiler:"<<std::endl;
3350                                 g_profiler->print(infostream);
3351                                 g_profiler->clear();
3352                         }
3353                 }
3354         }
3355 }
3356
3357