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