Particles: Add option to remove particles on collision
[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 "threading/mutex_auto_lock.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 Thread
75 {
76 public:
77
78         ServerThread(Server *server):
79                 Thread("Server"),
80                 m_server(server)
81         {}
82
83         void *run();
84
85 private:
86         Server *m_server;
87 };
88
89 void *ServerThread::run()
90 {
91         DSTACK(FUNCTION_NAME);
92         BEGIN_DEBUG_EXCEPTION_HANDLER
93
94         m_server->AsyncRunStep(true);
95
96         while (!stopRequested()) {
97                 try {
98                         //TimeTaker timer("AsyncRunStep() + Receive()");
99
100                         m_server->AsyncRunStep();
101
102                         m_server->Receive();
103
104                 } catch (con::NoIncomingDataException &e) {
105                 } catch (con::PeerNotFoundException &e) {
106                         infostream<<"Server: PeerNotFoundException"<<std::endl;
107                 } catch (ClientNotFoundException &e) {
108                 } catch (con::ConnectionBindFailed &e) {
109                         m_server->setAsyncFatalError(e.what());
110                 } catch (LuaError &e) {
111                         m_server->setAsyncFatalError("Lua: " + std::string(e.what()));
112                 }
113         }
114
115         END_DEBUG_EXCEPTION_HANDLER
116
117         return NULL;
118 }
119
120 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
121 {
122         if(pos_exists) *pos_exists = false;
123         switch(type){
124         case SSP_LOCAL:
125                 return v3f(0,0,0);
126         case SSP_POSITIONAL:
127                 if(pos_exists) *pos_exists = true;
128                 return pos;
129         case SSP_OBJECT: {
130                 if(object == 0)
131                         return v3f(0,0,0);
132                 ServerActiveObject *sao = env->getActiveObject(object);
133                 if(!sao)
134                         return v3f(0,0,0);
135                 if(pos_exists) *pos_exists = true;
136                 return sao->getBasePosition(); }
137         }
138         return v3f(0,0,0);
139 }
140
141
142
143 /*
144         Server
145 */
146
147 Server::Server(
148                 const std::string &path_world,
149                 const SubgameSpec &gamespec,
150                 bool simple_singleplayer_mode,
151                 bool ipv6,
152                 ChatInterface *iface
153         ):
154         m_path_world(path_world),
155         m_gamespec(gamespec),
156         m_simple_singleplayer_mode(simple_singleplayer_mode),
157         m_async_fatal_error(""),
158         m_env(NULL),
159         m_con(PROTOCOL_ID,
160                         512,
161                         CONNECTION_TIMEOUT,
162                         ipv6,
163                         this),
164         m_banmanager(NULL),
165         m_rollback(NULL),
166         m_enable_rollback_recording(false),
167         m_emerge(NULL),
168         m_script(NULL),
169         m_itemdef(createItemDefManager()),
170         m_nodedef(createNodeDefManager()),
171         m_craftdef(createCraftDefManager()),
172         m_event(new EventManager()),
173         m_thread(NULL),
174         m_time_of_day_send_timer(0),
175         m_uptime(0),
176         m_clients(&m_con),
177         m_shutdown_requested(false),
178         m_shutdown_ask_reconnect(false),
179         m_admin_chat(iface),
180         m_ignore_map_edit_events(false),
181         m_ignore_map_edit_events_peer_id(0),
182         m_next_sound_id(0)
183
184 {
185         m_liquid_transform_timer = 0.0;
186         m_liquid_transform_every = 1.0;
187         m_print_info_timer = 0.0;
188         m_masterserver_timer = 0.0;
189         m_objectdata_timer = 0.0;
190         m_emergethread_trigger_timer = 0.0;
191         m_savemap_timer = 0.0;
192
193         m_step_dtime = 0.0;
194         m_lag = g_settings->getFloat("dedicated_server_step");
195
196         if(path_world == "")
197                 throw ServerError("Supplied empty world path");
198
199         if(!gamespec.isValid())
200                 throw ServerError("Supplied invalid gamespec");
201
202         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
203         if(m_simple_singleplayer_mode)
204                 infostream<<" in simple singleplayer mode"<<std::endl;
205         else
206                 infostream<<std::endl;
207         infostream<<"- world:  "<<m_path_world<<std::endl;
208         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
209
210         // Create world if it doesn't exist
211         if(!loadGameConfAndInitWorld(m_path_world, m_gamespec))
212                 throw ServerError("Failed to initialize world");
213
214         // Create server thread
215         m_thread = new ServerThread(this);
216
217         // Create emerge manager
218         m_emerge = new EmergeManager(this);
219
220         // Create ban manager
221         std::string ban_path = m_path_world + DIR_DELIM "ipban.txt";
222         m_banmanager = new BanManager(ban_path);
223
224         ModConfiguration modconf(m_path_world);
225         m_mods = modconf.getMods();
226         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
227         // complain about mods with unsatisfied dependencies
228         if(!modconf.isConsistent()) {
229                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
230                         it != unsatisfied_mods.end(); ++it) {
231                         ModSpec mod = *it;
232                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
233                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
234                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
235                                 errorstream << " \"" << *dep_it << "\"";
236                         errorstream << std::endl;
237                 }
238         }
239
240         Settings worldmt_settings;
241         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
242         worldmt_settings.readConfigFile(worldmt.c_str());
243         std::vector<std::string> names = worldmt_settings.getNames();
244         std::set<std::string> load_mod_names;
245         for(std::vector<std::string>::iterator it = names.begin();
246                 it != names.end(); ++it) {
247                 std::string name = *it;
248                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
249                         load_mod_names.insert(name.substr(9));
250         }
251         // complain about mods declared to be loaded, but not found
252         for(std::vector<ModSpec>::iterator it = m_mods.begin();
253                         it != m_mods.end(); ++it)
254                 load_mod_names.erase((*it).name);
255         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
256                         it != unsatisfied_mods.end(); ++it)
257                 load_mod_names.erase((*it).name);
258         if(!load_mod_names.empty()) {
259                 errorstream << "The following mods could not be found:";
260                 for(std::set<std::string>::iterator it = load_mod_names.begin();
261                         it != load_mod_names.end(); ++it)
262                         errorstream << " \"" << (*it) << "\"";
263                 errorstream << std::endl;
264         }
265
266         //lock environment
267         MutexAutoLock envlock(m_env_mutex);
268
269         // Load mapgen params from Settings
270         m_emerge->loadMapgenParams();
271
272         // Create the Map (loads map_meta.txt, overriding configured mapgen params)
273         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
274
275         // Initialize scripting
276         infostream<<"Server: Initializing Lua"<<std::endl;
277
278         m_script = new GameScripting(this);
279
280         std::string script_path = getBuiltinLuaPath() + DIR_DELIM "init.lua";
281
282         m_script->loadMod(script_path, BUILTIN_MOD_NAME);
283
284         // Print mods
285         infostream << "Server: Loading mods: ";
286         for(std::vector<ModSpec>::iterator i = m_mods.begin();
287                         i != m_mods.end(); ++i) {
288                 const ModSpec &mod = *i;
289                 infostream << mod.name << " ";
290         }
291         infostream << std::endl;
292         // Load and run "mod" scripts
293         for (std::vector<ModSpec>::iterator it = m_mods.begin();
294                         it != m_mods.end(); ++it) {
295                 const ModSpec &mod = *it;
296                 if (!string_allowed(mod.name, MODNAME_ALLOWED_CHARS)) {
297                         throw ModError("Error loading mod \"" + mod.name +
298                                 "\": Mod name does not follow naming conventions: "
299                                 "Only chararacters [a-z0-9_] are allowed.");
300                 }
301                 std::string script_path = mod.path + DIR_DELIM + "init.lua";
302                 infostream << "  [" << padStringRight(mod.name, 12) << "] [\""
303                                 << script_path << "\"]" << std::endl;
304                 m_script->loadMod(script_path, mod.name);
305         }
306
307         // Read Textures and calculate sha1 sums
308         fillMediaCache();
309
310         // Apply item aliases in the node definition manager
311         m_nodedef->updateAliases(m_itemdef);
312
313         // Apply texture overrides from texturepack/override.txt
314         std::string texture_path = g_settings->get("texture_path");
315         if (texture_path != "" && fs::IsDir(texture_path))
316                 m_nodedef->applyTextureOverrides(texture_path + DIR_DELIM + "override.txt");
317
318         m_nodedef->setNodeRegistrationStatus(true);
319
320         // Perform pending node name resolutions
321         m_nodedef->runNodeResolveCallbacks();
322
323         // unmap node names for connected nodeboxes
324         m_nodedef->mapNodeboxConnections();
325
326         // init the recipe hashes to speed up crafting
327         m_craftdef->initHashes(this);
328
329         // Initialize Environment
330         m_env = new ServerEnvironment(servermap, m_script, this, m_path_world);
331
332         m_clients.setEnv(m_env);
333
334         // Initialize mapgens
335         m_emerge->initMapgens();
336
337         m_enable_rollback_recording = g_settings->getBool("enable_rollback_recording");
338         if (m_enable_rollback_recording) {
339                 // Create rollback manager
340                 m_rollback = new RollbackManager(m_path_world, this);
341         }
342
343         // Give environment reference to scripting api
344         m_script->initializeEnvironment(m_env);
345
346         // Register us to receive map edit events
347         servermap->addEventReceiver(this);
348
349         // If file exists, load environment metadata
350         if (fs::PathExists(m_path_world + DIR_DELIM "env_meta.txt")) {
351                 infostream << "Server: Loading environment metadata" << std::endl;
352                 m_env->loadMeta();
353         } else {
354                 m_env->loadDefaultMeta();
355         }
356
357         // Add some test ActiveBlockModifiers to environment
358         add_legacy_abms(m_env, m_nodedef);
359
360         m_liquid_transform_every = g_settings->getFloat("liquid_update");
361 }
362
363 Server::~Server()
364 {
365         infostream<<"Server destructing"<<std::endl;
366
367         // Send shutdown message
368         SendChatMessage(PEER_ID_INEXISTENT, L"*** Server shutting down");
369
370         {
371                 MutexAutoLock envlock(m_env_mutex);
372
373                 // Execute script shutdown hooks
374                 m_script->on_shutdown();
375
376                 infostream << "Server: Saving players" << std::endl;
377                 m_env->saveLoadedPlayers();
378
379                 infostream << "Server: Kicking players" << std::endl;
380                 std::string kick_msg;
381                 bool reconnect = false;
382                 if (getShutdownRequested()) {
383                         reconnect = m_shutdown_ask_reconnect;
384                         kick_msg = m_shutdown_msg;
385                 }
386                 if (kick_msg == "") {
387                         kick_msg = g_settings->get("kick_msg_shutdown");
388                 }
389                 m_env->kickAllPlayers(SERVER_ACCESSDENIED_SHUTDOWN,
390                         kick_msg, reconnect);
391
392                 infostream << "Server: Saving environment metadata" << std::endl;
393                 m_env->saveMeta();
394         }
395
396         // Stop threads
397         stop();
398         delete m_thread;
399
400         // stop all emerge threads before deleting players that may have
401         // requested blocks to be emerged
402         m_emerge->stopThreads();
403
404         // Delete things in the reverse order of creation
405         delete m_env;
406
407         // N.B. the EmergeManager should be deleted after the Environment since Map
408         // depends on EmergeManager to write its current params to the map meta
409         delete m_emerge;
410         delete m_rollback;
411         delete m_banmanager;
412         delete m_event;
413         delete m_itemdef;
414         delete m_nodedef;
415         delete m_craftdef;
416
417         // Deinitialize scripting
418         infostream<<"Server: Deinitializing scripting"<<std::endl;
419         delete m_script;
420
421         // Delete detached inventories
422         for (std::map<std::string, Inventory*>::iterator
423                         i = m_detached_inventories.begin();
424                         i != m_detached_inventories.end(); ++i) {
425                 delete i->second;
426         }
427 }
428
429 void Server::start(Address bind_addr)
430 {
431         DSTACK(FUNCTION_NAME);
432
433         m_bind_addr = bind_addr;
434
435         infostream<<"Starting server on "
436                         << bind_addr.serializeString() <<"..."<<std::endl;
437
438         // Stop thread if already running
439         m_thread->stop();
440
441         // Initialize connection
442         m_con.SetTimeoutMs(30);
443         m_con.Serve(bind_addr);
444
445         // Start thread
446         m_thread->start();
447
448         // ASCII art for the win!
449         actionstream
450         <<"        .__               __                   __   "<<std::endl
451         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
452         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
453         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
454         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
455         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
456         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
457         actionstream<<"Server for gameid=\""<<m_gamespec.id
458                         <<"\" listening on "<<bind_addr.serializeString()<<":"
459                         <<bind_addr.getPort() << "."<<std::endl;
460 }
461
462 void Server::stop()
463 {
464         DSTACK(FUNCTION_NAME);
465
466         infostream<<"Server: Stopping and waiting threads"<<std::endl;
467
468         // Stop threads (set run=false first so both start stopping)
469         m_thread->stop();
470         //m_emergethread.setRun(false);
471         m_thread->wait();
472         //m_emergethread.stop();
473
474         infostream<<"Server: Threads stopped"<<std::endl;
475 }
476
477 void Server::step(float dtime)
478 {
479         DSTACK(FUNCTION_NAME);
480         // Limit a bit
481         if (dtime > 2.0)
482                 dtime = 2.0;
483         {
484                 MutexAutoLock lock(m_step_dtime_mutex);
485                 m_step_dtime += dtime;
486         }
487         // Throw if fatal error occurred in thread
488         std::string async_err = m_async_fatal_error.get();
489         if (!async_err.empty()) {
490                 if (!m_simple_singleplayer_mode) {
491                         m_env->kickAllPlayers(SERVER_ACCESSDENIED_CRASH,
492                                 g_settings->get("kick_msg_crash"),
493                                 g_settings->getBool("ask_reconnect_on_crash"));
494                 }
495                 throw ServerError(async_err);
496         }
497 }
498
499 void Server::AsyncRunStep(bool initial_step)
500 {
501         DSTACK(FUNCTION_NAME);
502
503         g_profiler->add("Server::AsyncRunStep (num)", 1);
504
505         float dtime;
506         {
507                 MutexAutoLock lock1(m_step_dtime_mutex);
508                 dtime = m_step_dtime;
509         }
510
511         {
512                 // Send blocks to clients
513                 SendBlocks(dtime);
514         }
515
516         if((dtime < 0.001) && (initial_step == false))
517                 return;
518
519         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
520
521         //infostream<<"Server steps "<<dtime<<std::endl;
522         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
523
524         {
525                 MutexAutoLock lock1(m_step_dtime_mutex);
526                 m_step_dtime -= dtime;
527         }
528
529         /*
530                 Update uptime
531         */
532         {
533                 m_uptime.set(m_uptime.get() + dtime);
534         }
535
536         handlePeerChanges();
537
538         /*
539                 Update time of day and overall game time
540         */
541         m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
542
543         /*
544                 Send to clients at constant intervals
545         */
546
547         m_time_of_day_send_timer -= dtime;
548         if(m_time_of_day_send_timer < 0.0) {
549                 m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
550                 u16 time = m_env->getTimeOfDay();
551                 float time_speed = g_settings->getFloat("time_speed");
552                 SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
553         }
554
555         {
556                 MutexAutoLock lock(m_env_mutex);
557                 // Figure out and report maximum lag to environment
558                 float max_lag = m_env->getMaxLagEstimate();
559                 max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
560                 if(dtime > max_lag){
561                         if(dtime > 0.1 && dtime > max_lag * 2.0)
562                                 infostream<<"Server: Maximum lag peaked to "<<dtime
563                                                 <<" s"<<std::endl;
564                         max_lag = dtime;
565                 }
566                 m_env->reportMaxLagEstimate(max_lag);
567                 // Step environment
568                 ScopeProfiler sp(g_profiler, "SEnv step");
569                 ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
570                 m_env->step(dtime);
571         }
572
573         static const float map_timer_and_unload_dtime = 2.92;
574         if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
575         {
576                 MutexAutoLock lock(m_env_mutex);
577                 // Run Map's timers and unload unused data
578                 ScopeProfiler sp(g_profiler, "Server: map timer and unload");
579                 m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
580                         g_settings->getFloat("server_unload_unused_data_timeout"),
581                         U32_MAX);
582         }
583
584         /*
585                 Listen to the admin chat, if available
586         */
587         if (m_admin_chat) {
588                 if (!m_admin_chat->command_queue.empty()) {
589                         MutexAutoLock lock(m_env_mutex);
590                         while (!m_admin_chat->command_queue.empty()) {
591                                 ChatEvent *evt = m_admin_chat->command_queue.pop_frontNoEx();
592                                 handleChatInterfaceEvent(evt);
593                                 delete evt;
594                         }
595                 }
596                 m_admin_chat->outgoing_queue.push_back(
597                         new ChatEventTimeInfo(m_env->getGameTime(), m_env->getTimeOfDay()));
598         }
599
600         /*
601                 Do background stuff
602         */
603
604         /* Transform liquids */
605         m_liquid_transform_timer += dtime;
606         if(m_liquid_transform_timer >= m_liquid_transform_every)
607         {
608                 m_liquid_transform_timer -= m_liquid_transform_every;
609
610                 MutexAutoLock lock(m_env_mutex);
611
612                 ScopeProfiler sp(g_profiler, "Server: liquid transform");
613
614                 std::map<v3s16, MapBlock*> modified_blocks;
615                 m_env->getMap().transformLiquids(modified_blocks);
616 #if 0
617                 /*
618                         Update lighting
619                 */
620                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
621                 ServerMap &map = ((ServerMap&)m_env->getMap());
622                 map.updateLighting(modified_blocks, lighting_modified_blocks);
623
624                 // Add blocks modified by lighting to modified_blocks
625                 for(core::map<v3s16, MapBlock*>::Iterator
626                                 i = lighting_modified_blocks.getIterator();
627                                 i.atEnd() == false; i++)
628                 {
629                         MapBlock *block = i.getNode()->getValue();
630                         modified_blocks.insert(block->getPos(), block);
631                 }
632 #endif
633                 /*
634                         Set the modified blocks unsent for all the clients
635                 */
636                 if(!modified_blocks.empty())
637                 {
638                         SetBlocksNotSent(modified_blocks);
639                 }
640         }
641         m_clients.step(dtime);
642
643         m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
644 #if USE_CURL
645         // send masterserver announce
646         {
647                 float &counter = m_masterserver_timer;
648                 if(!isSingleplayer() && (!counter || counter >= 300.0) &&
649                                 g_settings->getBool("server_announce"))
650                 {
651                         ServerList::sendAnnounce(counter ? "update" : "start",
652                                         m_bind_addr.getPort(),
653                                         m_clients.getPlayerNames(),
654                                         m_uptime.get(),
655                                         m_env->getGameTime(),
656                                         m_lag,
657                                         m_gamespec.id,
658                                         m_emerge->params.mg_name,
659                                         m_mods);
660                         counter = 0.01;
661                 }
662                 counter += dtime;
663         }
664 #endif
665
666         /*
667                 Check added and deleted active objects
668         */
669         {
670                 //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
671                 MutexAutoLock envlock(m_env_mutex);
672
673                 m_clients.lock();
674                 std::map<u16, RemoteClient*> clients = m_clients.getClientList();
675                 ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
676
677                 // Radius inside which objects are active
678                 static const s16 radius =
679                         g_settings->getS16("active_object_send_range_blocks") * MAP_BLOCKSIZE;
680
681                 // Radius inside which players are active
682                 static const bool is_transfer_limited =
683                         g_settings->exists("unlimited_player_transfer_distance") &&
684                         !g_settings->getBool("unlimited_player_transfer_distance");
685                 static const s16 player_transfer_dist = g_settings->getS16("player_transfer_distance") * MAP_BLOCKSIZE;
686                 s16 player_radius = player_transfer_dist;
687                 if (player_radius == 0 && is_transfer_limited)
688                         player_radius = radius;
689
690                 for (std::map<u16, RemoteClient*>::iterator
691                         i = clients.begin();
692                         i != clients.end(); ++i) {
693                         RemoteClient *client = i->second;
694
695                         // If definitions and textures have not been sent, don't
696                         // send objects either
697                         if (client->getState() < CS_DefinitionsSent)
698                                 continue;
699
700                         Player *player = m_env->getPlayer(client->peer_id);
701                         if(player == NULL) {
702                                 // This can happen if the client timeouts somehow
703                                 /*warningstream<<FUNCTION_NAME<<": Client "
704                                                 <<client->peer_id
705                                                 <<" has no associated player"<<std::endl;*/
706                                 continue;
707                         }
708
709                         std::queue<u16> removed_objects;
710                         std::queue<u16> added_objects;
711                         m_env->getRemovedActiveObjects(player, radius, player_radius,
712                                         client->m_known_objects, removed_objects);
713                         m_env->getAddedActiveObjects(player, radius, player_radius,
714                                         client->m_known_objects, added_objects);
715
716                         // Ignore if nothing happened
717                         if (removed_objects.empty() && added_objects.empty()) {
718                                 continue;
719                         }
720
721                         std::string data_buffer;
722
723                         char buf[4];
724
725                         // Handle removed objects
726                         writeU16((u8*)buf, removed_objects.size());
727                         data_buffer.append(buf, 2);
728                         while (!removed_objects.empty()) {
729                                 // Get object
730                                 u16 id = removed_objects.front();
731                                 ServerActiveObject* obj = m_env->getActiveObject(id);
732
733                                 // Add to data buffer for sending
734                                 writeU16((u8*)buf, id);
735                                 data_buffer.append(buf, 2);
736
737                                 // Remove from known objects
738                                 client->m_known_objects.erase(id);
739
740                                 if(obj && obj->m_known_by_count > 0)
741                                         obj->m_known_by_count--;
742                                 removed_objects.pop();
743                         }
744
745                         // Handle added objects
746                         writeU16((u8*)buf, added_objects.size());
747                         data_buffer.append(buf, 2);
748                         while (!added_objects.empty()) {
749                                 // Get object
750                                 u16 id = added_objects.front();
751                                 ServerActiveObject* obj = m_env->getActiveObject(id);
752
753                                 // Get object type
754                                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
755                                 if(obj == NULL)
756                                         warningstream<<FUNCTION_NAME
757                                                         <<": NULL object"<<std::endl;
758                                 else
759                                         type = obj->getSendType();
760
761                                 // Add to data buffer for sending
762                                 writeU16((u8*)buf, id);
763                                 data_buffer.append(buf, 2);
764                                 writeU8((u8*)buf, type);
765                                 data_buffer.append(buf, 1);
766
767                                 if(obj)
768                                         data_buffer.append(serializeLongString(
769                                                         obj->getClientInitializationData(client->net_proto_version)));
770                                 else
771                                         data_buffer.append(serializeLongString(""));
772
773                                 // Add to known objects
774                                 client->m_known_objects.insert(id);
775
776                                 if(obj)
777                                         obj->m_known_by_count++;
778
779                                 added_objects.pop();
780                         }
781
782                         u32 pktSize = SendActiveObjectRemoveAdd(client->peer_id, data_buffer);
783                         verbosestream << "Server: Sent object remove/add: "
784                                         << removed_objects.size() << " removed, "
785                                         << added_objects.size() << " added, "
786                                         << "packet size is " << pktSize << std::endl;
787                 }
788                 m_clients.unlock();
789         }
790
791         /*
792                 Send object messages
793         */
794         {
795                 MutexAutoLock envlock(m_env_mutex);
796                 ScopeProfiler sp(g_profiler, "Server: sending object messages");
797
798                 // Key = object id
799                 // Value = data sent by object
800                 std::map<u16, std::vector<ActiveObjectMessage>* > buffered_messages;
801
802                 // Get active object messages from environment
803                 for(;;) {
804                         ActiveObjectMessage aom = m_env->getActiveObjectMessage();
805                         if (aom.id == 0)
806                                 break;
807
808                         std::vector<ActiveObjectMessage>* message_list = NULL;
809                         std::map<u16, std::vector<ActiveObjectMessage>* >::iterator n;
810                         n = buffered_messages.find(aom.id);
811                         if (n == buffered_messages.end()) {
812                                 message_list = new std::vector<ActiveObjectMessage>;
813                                 buffered_messages[aom.id] = message_list;
814                         }
815                         else {
816                                 message_list = n->second;
817                         }
818                         message_list->push_back(aom);
819                 }
820
821                 m_clients.lock();
822                 std::map<u16, RemoteClient*> clients = m_clients.getClientList();
823                 // Route data to every client
824                 for (std::map<u16, RemoteClient*>::iterator
825                         i = clients.begin();
826                         i != clients.end(); ++i) {
827                         RemoteClient *client = i->second;
828                         std::string reliable_data;
829                         std::string unreliable_data;
830                         // Go through all objects in message buffer
831                         for (std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
832                                         j = buffered_messages.begin();
833                                         j != buffered_messages.end(); ++j) {
834                                 // If object is not known by client, skip it
835                                 u16 id = j->first;
836                                 if (client->m_known_objects.find(id) == client->m_known_objects.end())
837                                         continue;
838
839                                 // Get message list of object
840                                 std::vector<ActiveObjectMessage>* list = j->second;
841                                 // Go through every message
842                                 for (std::vector<ActiveObjectMessage>::iterator
843                                                 k = list->begin(); k != list->end(); ++k) {
844                                         // Compose the full new data with header
845                                         ActiveObjectMessage aom = *k;
846                                         std::string new_data;
847                                         // Add object id
848                                         char buf[2];
849                                         writeU16((u8*)&buf[0], aom.id);
850                                         new_data.append(buf, 2);
851                                         // Add data
852                                         new_data += serializeString(aom.datastring);
853                                         // Add data to buffer
854                                         if(aom.reliable)
855                                                 reliable_data += new_data;
856                                         else
857                                                 unreliable_data += new_data;
858                                 }
859                         }
860                         /*
861                                 reliable_data and unreliable_data are now ready.
862                                 Send them.
863                         */
864                         if(reliable_data.size() > 0) {
865                                 SendActiveObjectMessages(client->peer_id, reliable_data);
866                         }
867
868                         if(unreliable_data.size() > 0) {
869                                 SendActiveObjectMessages(client->peer_id, unreliable_data, false);
870                         }
871                 }
872                 m_clients.unlock();
873
874                 // Clear buffered_messages
875                 for(std::map<u16, std::vector<ActiveObjectMessage>* >::iterator
876                                 i = buffered_messages.begin();
877                                 i != buffered_messages.end(); ++i) {
878                         delete i->second;
879                 }
880         }
881
882         /*
883                 Send queued-for-sending map edit events.
884         */
885         {
886                 // We will be accessing the environment
887                 MutexAutoLock lock(m_env_mutex);
888
889                 // Don't send too many at a time
890                 //u32 count = 0;
891
892                 // Single change sending is disabled if queue size is not small
893                 bool disable_single_change_sending = false;
894                 if(m_unsent_map_edit_queue.size() >= 4)
895                         disable_single_change_sending = true;
896
897                 int event_count = m_unsent_map_edit_queue.size();
898
899                 // We'll log the amount of each
900                 Profiler prof;
901
902                 while(m_unsent_map_edit_queue.size() != 0)
903                 {
904                         MapEditEvent* event = m_unsent_map_edit_queue.front();
905                         m_unsent_map_edit_queue.pop();
906
907                         // Players far away from the change are stored here.
908                         // Instead of sending the changes, MapBlocks are set not sent
909                         // for them.
910                         std::vector<u16> far_players;
911
912                         switch (event->type) {
913                         case MEET_ADDNODE:
914                         case MEET_SWAPNODE:
915                                 prof.add("MEET_ADDNODE", 1);
916                                 sendAddNode(event->p, event->n, event->already_known_by_peer,
917                                                 &far_players, disable_single_change_sending ? 5 : 30,
918                                                 event->type == MEET_ADDNODE);
919                                 break;
920                         case MEET_REMOVENODE:
921                                 prof.add("MEET_REMOVENODE", 1);
922                                 sendRemoveNode(event->p, event->already_known_by_peer,
923                                                 &far_players, disable_single_change_sending ? 5 : 30);
924                                 break;
925                         case MEET_BLOCK_NODE_METADATA_CHANGED:
926                                 infostream << "Server: MEET_BLOCK_NODE_METADATA_CHANGED" << std::endl;
927                                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
928                                                 setBlockNotSent(event->p);
929                                 break;
930                         case MEET_OTHER:
931                                 infostream << "Server: MEET_OTHER" << std::endl;
932                                 prof.add("MEET_OTHER", 1);
933                                 for(std::set<v3s16>::iterator
934                                                 i = event->modified_blocks.begin();
935                                                 i != event->modified_blocks.end(); ++i) {
936                                         setBlockNotSent(*i);
937                                 }
938                                 break;
939                         default:
940                                 prof.add("unknown", 1);
941                                 warningstream << "Server: Unknown MapEditEvent "
942                                                 << ((u32)event->type) << std::endl;
943                                 break;
944                         }
945
946                         /*
947                                 Set blocks not sent to far players
948                         */
949                         if(!far_players.empty()) {
950                                 // Convert list format to that wanted by SetBlocksNotSent
951                                 std::map<v3s16, MapBlock*> modified_blocks2;
952                                 for(std::set<v3s16>::iterator
953                                                 i = event->modified_blocks.begin();
954                                                 i != event->modified_blocks.end(); ++i) {
955                                         modified_blocks2[*i] =
956                                                         m_env->getMap().getBlockNoCreateNoEx(*i);
957                                 }
958
959                                 // Set blocks not sent
960                                 for(std::vector<u16>::iterator
961                                                 i = far_players.begin();
962                                                 i != far_players.end(); ++i) {
963                                         if(RemoteClient *client = getClient(*i))
964                                                 client->SetBlocksNotSent(modified_blocks2);
965                                 }
966                         }
967
968                         delete event;
969
970                         /*// Don't send too many at a time
971                         count++;
972                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
973                                 break;*/
974                 }
975
976                 if(event_count >= 5){
977                         infostream<<"Server: MapEditEvents:"<<std::endl;
978                         prof.print(infostream);
979                 } else if(event_count != 0){
980                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
981                         prof.print(verbosestream);
982                 }
983
984         }
985
986         /*
987                 Trigger emergethread (it somehow gets to a non-triggered but
988                 bysy state sometimes)
989         */
990         {
991                 float &counter = m_emergethread_trigger_timer;
992                 counter += dtime;
993                 if (counter >= 2.0) {
994                         counter = 0.0;
995
996                         m_emerge->startThreads();
997                 }
998         }
999
1000         // Save map, players and auth stuff
1001         {
1002                 float &counter = m_savemap_timer;
1003                 counter += dtime;
1004                 static const float save_interval =
1005                         g_settings->getFloat("server_map_save_interval");
1006                 if (counter >= save_interval) {
1007                         counter = 0.0;
1008                         MutexAutoLock lock(m_env_mutex);
1009
1010                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1011
1012                         // Save ban file
1013                         if (m_banmanager->isModified()) {
1014                                 m_banmanager->save();
1015                         }
1016
1017                         // Save changed parts of map
1018                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1019
1020                         // Save players
1021                         m_env->saveLoadedPlayers();
1022
1023                         // Save environment metadata
1024                         m_env->saveMeta();
1025                 }
1026         }
1027 }
1028
1029 void Server::Receive()
1030 {
1031         DSTACK(FUNCTION_NAME);
1032         SharedBuffer<u8> data;
1033         u16 peer_id;
1034         try {
1035                 NetworkPacket pkt;
1036                 m_con.Receive(&pkt);
1037                 peer_id = pkt.getPeerId();
1038                 ProcessData(&pkt);
1039         }
1040         catch(con::InvalidIncomingDataException &e) {
1041                 infostream<<"Server::Receive(): "
1042                                 "InvalidIncomingDataException: what()="
1043                                 <<e.what()<<std::endl;
1044         }
1045         catch(SerializationError &e) {
1046                 infostream<<"Server::Receive(): "
1047                                 "SerializationError: what()="
1048                                 <<e.what()<<std::endl;
1049         }
1050         catch(ClientStateError &e) {
1051                 errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1052                 DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect."
1053                                 L"Try reconnecting or updating your client");
1054         }
1055         catch(con::PeerNotFoundException &e) {
1056                 // Do nothing
1057         }
1058 }
1059
1060 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1061 {
1062         std::string playername = "";
1063         PlayerSAO *playersao = NULL;
1064         m_clients.lock();
1065         try {
1066                 RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
1067                 if (client != NULL) {
1068                         playername = client->getName();
1069                         playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
1070                 }
1071         } catch (std::exception &e) {
1072                 m_clients.unlock();
1073                 throw;
1074         }
1075         m_clients.unlock();
1076
1077         RemotePlayer *player =
1078                 static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
1079
1080         // If failed, cancel
1081         if ((playersao == NULL) || (player == NULL)) {
1082                 if (player && player->peer_id != 0) {
1083                         actionstream << "Server: Failed to emerge player \"" << playername
1084                                         << "\" (player allocated to an another client)" << std::endl;
1085                         DenyAccess_Legacy(peer_id, L"Another client is connected with this "
1086                                         L"name. If your client closed unexpectedly, try again in "
1087                                         L"a minute.");
1088                 } else {
1089                         errorstream << "Server: " << playername << ": Failed to emerge player"
1090                                         << std::endl;
1091                         DenyAccess_Legacy(peer_id, L"Could not allocate player.");
1092                 }
1093                 return NULL;
1094         }
1095
1096         /*
1097                 Send complete position information
1098         */
1099         SendMovePlayer(peer_id);
1100
1101         // Send privileges
1102         SendPlayerPrivileges(peer_id);
1103
1104         // Send inventory formspec
1105         SendPlayerInventoryFormspec(peer_id);
1106
1107         // Send inventory
1108         SendInventory(playersao);
1109
1110         // Send HP
1111         SendPlayerHPOrDie(playersao);
1112
1113         // Send Breath
1114         SendPlayerBreath(peer_id);
1115
1116         // Show death screen if necessary
1117         if(player->isDead())
1118                 SendDeathscreen(peer_id, false, v3f(0,0,0));
1119
1120         // Note things in chat if not in simple singleplayer mode
1121         if(!m_simple_singleplayer_mode) {
1122                 // Send information about server to player in chat
1123                 SendChatMessage(peer_id, getStatusString());
1124
1125                 // Send information about joining in chat
1126                 {
1127                         std::string name = "unknown";
1128                         Player *player = m_env->getPlayer(peer_id);
1129                         if(player != NULL)
1130                                 name = player->getName();
1131
1132                         std::wstring message;
1133                         message += L"*** ";
1134                         message += narrow_to_wide(name);
1135                         message += L" joined the game.";
1136                         SendChatMessage(PEER_ID_INEXISTENT,message);
1137                         if (m_admin_chat)
1138                                 m_admin_chat->outgoing_queue.push_back(
1139                                         new ChatEventNick(CET_NICK_ADD, name));
1140                 }
1141         }
1142         Address addr = getPeerAddress(player->peer_id);
1143         std::string ip_str = addr.serializeString();
1144         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1145         /*
1146                 Print out action
1147         */
1148         {
1149                 std::vector<std::string> names = m_clients.getPlayerNames();
1150
1151                 actionstream<<player->getName() <<" joins game. List of players: ";
1152
1153                 for (std::vector<std::string>::iterator i = names.begin();
1154                                 i != names.end(); ++i) {
1155                         actionstream << *i << " ";
1156                 }
1157
1158                 actionstream << player->getName() <<std::endl;
1159         }
1160         return playersao;
1161 }
1162
1163 inline void Server::handleCommand(NetworkPacket* pkt)
1164 {
1165         const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
1166         (this->*opHandle.handler)(pkt);
1167 }
1168
1169 void Server::ProcessData(NetworkPacket *pkt)
1170 {
1171         DSTACK(FUNCTION_NAME);
1172         // Environment is locked first.
1173         MutexAutoLock envlock(m_env_mutex);
1174
1175         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1176         u32 peer_id = pkt->getPeerId();
1177
1178         try {
1179                 Address address = getPeerAddress(peer_id);
1180                 std::string addr_s = address.serializeString();
1181
1182                 if(m_banmanager->isIpBanned(addr_s)) {
1183                         std::string ban_name = m_banmanager->getBanName(addr_s);
1184                         infostream << "Server: A banned client tried to connect from "
1185                                         << addr_s << "; banned name was "
1186                                         << ban_name << std::endl;
1187                         // This actually doesn't seem to transfer to the client
1188                         DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
1189                                         + utf8_to_wide(ban_name));
1190                         return;
1191                 }
1192         }
1193         catch(con::PeerNotFoundException &e) {
1194                 /*
1195                  * no peer for this packet found
1196                  * most common reason is peer timeout, e.g. peer didn't
1197                  * respond for some time, your server was overloaded or
1198                  * things like that.
1199                  */
1200                 infostream << "Server::ProcessData(): Canceling: peer "
1201                                 << peer_id << " not found" << std::endl;
1202                 return;
1203         }
1204
1205         try {
1206                 ToServerCommand command = (ToServerCommand) pkt->getCommand();
1207
1208                 // Command must be handled into ToServerCommandHandler
1209                 if (command >= TOSERVER_NUM_MSG_TYPES) {
1210                         infostream << "Server: Ignoring unknown command "
1211                                          << command << std::endl;
1212                         return;
1213                 }
1214
1215                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1216                         handleCommand(pkt);
1217                         return;
1218                 }
1219
1220                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1221
1222                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1223                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1224                                         " serialization format invalid or not initialized."
1225                                         " Skipping incoming command=" << command << std::endl;
1226                         return;
1227                 }
1228
1229                 /* Handle commands related to client startup */
1230                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1231                         handleCommand(pkt);
1232                         return;
1233                 }
1234
1235                 if (m_clients.getClientState(peer_id) < CS_Active) {
1236                         if (command == TOSERVER_PLAYERPOS) return;
1237
1238                         errorstream << "Got packet command: " << command << " for peer id "
1239                                         << peer_id << " but client isn't active yet. Dropping packet "
1240                                         << std::endl;
1241                         return;
1242                 }
1243
1244                 handleCommand(pkt);
1245         } catch (SendFailedException &e) {
1246                 errorstream << "Server::ProcessData(): SendFailedException: "
1247                                 << "what=" << e.what()
1248                                 << std::endl;
1249         } catch (PacketError &e) {
1250                 actionstream << "Server::ProcessData(): PacketError: "
1251                                 << "what=" << e.what()
1252                                 << std::endl;
1253         }
1254 }
1255
1256 void Server::setTimeOfDay(u32 time)
1257 {
1258         m_env->setTimeOfDay(time);
1259         m_time_of_day_send_timer = 0;
1260 }
1261
1262 void Server::onMapEditEvent(MapEditEvent *event)
1263 {
1264         if(m_ignore_map_edit_events)
1265                 return;
1266         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1267                 return;
1268         MapEditEvent *e = event->clone();
1269         m_unsent_map_edit_queue.push(e);
1270 }
1271
1272 Inventory* Server::getInventory(const InventoryLocation &loc)
1273 {
1274         switch (loc.type) {
1275         case InventoryLocation::UNDEFINED:
1276         case InventoryLocation::CURRENT_PLAYER:
1277                 break;
1278         case InventoryLocation::PLAYER:
1279         {
1280                 Player *player = m_env->getPlayer(loc.name.c_str());
1281                 if(!player)
1282                         return NULL;
1283                 PlayerSAO *playersao = player->getPlayerSAO();
1284                 if(!playersao)
1285                         return NULL;
1286                 return playersao->getInventory();
1287         }
1288                 break;
1289         case InventoryLocation::NODEMETA:
1290         {
1291                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1292                 if(!meta)
1293                         return NULL;
1294                 return meta->getInventory();
1295         }
1296                 break;
1297         case InventoryLocation::DETACHED:
1298         {
1299                 if(m_detached_inventories.count(loc.name) == 0)
1300                         return NULL;
1301                 return m_detached_inventories[loc.name];
1302         }
1303                 break;
1304         default:
1305                 sanity_check(false); // abort
1306                 break;
1307         }
1308         return NULL;
1309 }
1310 void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
1311 {
1312         switch(loc.type){
1313         case InventoryLocation::UNDEFINED:
1314                 break;
1315         case InventoryLocation::PLAYER:
1316         {
1317                 if (!playerSend)
1318                         return;
1319
1320                 Player *player = m_env->getPlayer(loc.name.c_str());
1321                 if(!player)
1322                         return;
1323                 PlayerSAO *playersao = player->getPlayerSAO();
1324                 if(!playersao)
1325                         return;
1326
1327                 SendInventory(playersao);
1328         }
1329                 break;
1330         case InventoryLocation::NODEMETA:
1331         {
1332                 v3s16 blockpos = getNodeBlockPos(loc.p);
1333
1334                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1335                 if(block)
1336                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1337
1338                 setBlockNotSent(blockpos);
1339         }
1340                 break;
1341         case InventoryLocation::DETACHED:
1342         {
1343                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1344         }
1345                 break;
1346         default:
1347                 sanity_check(false); // abort
1348                 break;
1349         }
1350 }
1351
1352 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1353 {
1354         std::vector<u16> clients = m_clients.getClientIDs();
1355         m_clients.lock();
1356         // Set the modified blocks unsent for all the clients
1357         for (std::vector<u16>::iterator i = clients.begin();
1358                  i != clients.end(); ++i) {
1359                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1360                                 client->SetBlocksNotSent(block);
1361         }
1362         m_clients.unlock();
1363 }
1364
1365 void Server::peerAdded(con::Peer *peer)
1366 {
1367         DSTACK(FUNCTION_NAME);
1368         verbosestream<<"Server::peerAdded(): peer->id="
1369                         <<peer->id<<std::endl;
1370
1371         con::PeerChange c;
1372         c.type = con::PEER_ADDED;
1373         c.peer_id = peer->id;
1374         c.timeout = false;
1375         m_peer_change_queue.push(c);
1376 }
1377
1378 void Server::deletingPeer(con::Peer *peer, bool timeout)
1379 {
1380         DSTACK(FUNCTION_NAME);
1381         verbosestream<<"Server::deletingPeer(): peer->id="
1382                         <<peer->id<<", timeout="<<timeout<<std::endl;
1383
1384         m_clients.event(peer->id, CSE_Disconnect);
1385         con::PeerChange c;
1386         c.type = con::PEER_REMOVED;
1387         c.peer_id = peer->id;
1388         c.timeout = timeout;
1389         m_peer_change_queue.push(c);
1390 }
1391
1392 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1393 {
1394         *retval = m_con.getPeerStat(peer_id,type);
1395         if (*retval == -1) return false;
1396         return true;
1397 }
1398
1399 bool Server::getClientInfo(
1400                 u16          peer_id,
1401                 ClientState* state,
1402                 u32*         uptime,
1403                 u8*          ser_vers,
1404                 u16*         prot_vers,
1405                 u8*          major,
1406                 u8*          minor,
1407                 u8*          patch,
1408                 std::string* vers_string
1409         )
1410 {
1411         *state = m_clients.getClientState(peer_id);
1412         m_clients.lock();
1413         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1414
1415         if (client == NULL) {
1416                 m_clients.unlock();
1417                 return false;
1418         }
1419
1420         *uptime = client->uptime();
1421         *ser_vers = client->serialization_version;
1422         *prot_vers = client->net_proto_version;
1423
1424         *major = client->getMajor();
1425         *minor = client->getMinor();
1426         *patch = client->getPatch();
1427         *vers_string = client->getPatch();
1428
1429         m_clients.unlock();
1430
1431         return true;
1432 }
1433
1434 void Server::handlePeerChanges()
1435 {
1436         while(m_peer_change_queue.size() > 0)
1437         {
1438                 con::PeerChange c = m_peer_change_queue.front();
1439                 m_peer_change_queue.pop();
1440
1441                 verbosestream<<"Server: Handling peer change: "
1442                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1443                                 <<std::endl;
1444
1445                 switch(c.type)
1446                 {
1447                 case con::PEER_ADDED:
1448                         m_clients.CreateClient(c.peer_id);
1449                         break;
1450
1451                 case con::PEER_REMOVED:
1452                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1453                         break;
1454
1455                 default:
1456                         FATAL_ERROR("Invalid peer change event received!");
1457                         break;
1458                 }
1459         }
1460 }
1461
1462 void Server::printToConsoleOnly(const std::string &text)
1463 {
1464         if (m_admin_chat) {
1465                 m_admin_chat->outgoing_queue.push_back(
1466                         new ChatEventChat("", utf8_to_wide(text)));
1467         } else {
1468                 std::cout << text << std::endl;
1469         }
1470 }
1471
1472 void Server::Send(NetworkPacket* pkt)
1473 {
1474         m_clients.send(pkt->getPeerId(),
1475                 clientCommandFactoryTable[pkt->getCommand()].channel,
1476                 pkt,
1477                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1478 }
1479
1480 void Server::SendMovement(u16 peer_id)
1481 {
1482         DSTACK(FUNCTION_NAME);
1483         std::ostringstream os(std::ios_base::binary);
1484
1485         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1486
1487         pkt << g_settings->getFloat("movement_acceleration_default");
1488         pkt << g_settings->getFloat("movement_acceleration_air");
1489         pkt << g_settings->getFloat("movement_acceleration_fast");
1490         pkt << g_settings->getFloat("movement_speed_walk");
1491         pkt << g_settings->getFloat("movement_speed_crouch");
1492         pkt << g_settings->getFloat("movement_speed_fast");
1493         pkt << g_settings->getFloat("movement_speed_climb");
1494         pkt << g_settings->getFloat("movement_speed_jump");
1495         pkt << g_settings->getFloat("movement_liquid_fluidity");
1496         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1497         pkt << g_settings->getFloat("movement_liquid_sink");
1498         pkt << g_settings->getFloat("movement_gravity");
1499
1500         Send(&pkt);
1501 }
1502
1503 void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
1504 {
1505         if (!g_settings->getBool("enable_damage"))
1506                 return;
1507
1508         u16 peer_id   = playersao->getPeerID();
1509         bool is_alive = playersao->getHP() > 0;
1510
1511         if (is_alive)
1512                 SendPlayerHP(peer_id);
1513         else
1514                 DiePlayer(peer_id);
1515 }
1516
1517 void Server::SendHP(u16 peer_id, u8 hp)
1518 {
1519         DSTACK(FUNCTION_NAME);
1520
1521         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1522         pkt << hp;
1523         Send(&pkt);
1524 }
1525
1526 void Server::SendBreath(u16 peer_id, u16 breath)
1527 {
1528         DSTACK(FUNCTION_NAME);
1529
1530         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1531         pkt << (u16) breath;
1532         Send(&pkt);
1533 }
1534
1535 void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
1536                 const std::string &custom_reason, bool reconnect)
1537 {
1538         assert(reason < SERVER_ACCESSDENIED_MAX);
1539
1540         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1541         pkt << (u8)reason;
1542         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1543                 pkt << custom_reason;
1544         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1545                         reason == SERVER_ACCESSDENIED_CRASH)
1546                 pkt << custom_reason << (u8)reconnect;
1547         Send(&pkt);
1548 }
1549
1550 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1551 {
1552         DSTACK(FUNCTION_NAME);
1553
1554         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1555         pkt << reason;
1556         Send(&pkt);
1557 }
1558
1559 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1560                 v3f camera_point_target)
1561 {
1562         DSTACK(FUNCTION_NAME);
1563
1564         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1565         pkt << set_camera_point_target << camera_point_target;
1566         Send(&pkt);
1567 }
1568
1569 void Server::SendItemDef(u16 peer_id,
1570                 IItemDefManager *itemdef, u16 protocol_version)
1571 {
1572         DSTACK(FUNCTION_NAME);
1573
1574         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1575
1576         /*
1577                 u16 command
1578                 u32 length of the next item
1579                 zlib-compressed serialized ItemDefManager
1580         */
1581         std::ostringstream tmp_os(std::ios::binary);
1582         itemdef->serialize(tmp_os, protocol_version);
1583         std::ostringstream tmp_os2(std::ios::binary);
1584         compressZlib(tmp_os.str(), tmp_os2);
1585         pkt.putLongString(tmp_os2.str());
1586
1587         // Make data buffer
1588         verbosestream << "Server: Sending item definitions to id(" << peer_id
1589                         << "): size=" << pkt.getSize() << std::endl;
1590
1591         Send(&pkt);
1592 }
1593
1594 void Server::SendNodeDef(u16 peer_id,
1595                 INodeDefManager *nodedef, u16 protocol_version)
1596 {
1597         DSTACK(FUNCTION_NAME);
1598
1599         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1600
1601         /*
1602                 u16 command
1603                 u32 length of the next item
1604                 zlib-compressed serialized NodeDefManager
1605         */
1606         std::ostringstream tmp_os(std::ios::binary);
1607         nodedef->serialize(tmp_os, protocol_version);
1608         std::ostringstream tmp_os2(std::ios::binary);
1609         compressZlib(tmp_os.str(), tmp_os2);
1610
1611         pkt.putLongString(tmp_os2.str());
1612
1613         // Make data buffer
1614         verbosestream << "Server: Sending node definitions to id(" << peer_id
1615                         << "): size=" << pkt.getSize() << std::endl;
1616
1617         Send(&pkt);
1618 }
1619
1620 /*
1621         Non-static send methods
1622 */
1623
1624 void Server::SendInventory(PlayerSAO* playerSAO)
1625 {
1626         DSTACK(FUNCTION_NAME);
1627
1628         UpdateCrafting(playerSAO->getPlayer());
1629
1630         /*
1631                 Serialize it
1632         */
1633
1634         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1635
1636         std::ostringstream os;
1637         playerSAO->getInventory()->serialize(os);
1638
1639         std::string s = os.str();
1640
1641         pkt.putRawString(s.c_str(), s.size());
1642         Send(&pkt);
1643 }
1644
1645 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
1646 {
1647         DSTACK(FUNCTION_NAME);
1648
1649         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1650         pkt << message;
1651
1652         if (peer_id != PEER_ID_INEXISTENT) {
1653                 Send(&pkt);
1654         }
1655         else {
1656                 m_clients.sendToAll(0, &pkt, true);
1657         }
1658 }
1659
1660 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1661                                      const std::string &formname)
1662 {
1663         DSTACK(FUNCTION_NAME);
1664
1665         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1666
1667         pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1668         pkt << formname;
1669
1670         Send(&pkt);
1671 }
1672
1673 // Spawns a particle on peer with peer_id
1674 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
1675                                 float expirationtime, float size, bool collisiondetection,
1676                                 bool collision_removal,
1677                                 bool vertical, const std::string &texture)
1678 {
1679         DSTACK(FUNCTION_NAME);
1680
1681         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1682
1683         pkt << pos << velocity << acceleration << expirationtime
1684                         << size << collisiondetection;
1685         pkt.putLongString(texture);
1686         pkt << vertical;
1687         pkt << collision_removal;
1688
1689         if (peer_id != PEER_ID_INEXISTENT) {
1690                 Send(&pkt);
1691         }
1692         else {
1693                 m_clients.sendToAll(0, &pkt, true);
1694         }
1695 }
1696
1697 // Adds a ParticleSpawner on peer with peer_id
1698 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
1699         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1700         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1701         bool vertical, const std::string &texture, u32 id)
1702 {
1703         DSTACK(FUNCTION_NAME);
1704
1705         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1706
1707         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1708                         << minacc << maxacc << minexptime << maxexptime << minsize
1709                         << maxsize << collisiondetection;
1710
1711         pkt.putLongString(texture);
1712
1713         pkt << id << vertical;
1714         pkt << collision_removal;
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(getNodeBlockPos(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         MutexAutoLock 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         PlayerSAO *playersao = getPlayerSAO(peer_id);
2523         // In some rare cases this can be NULL -- if the player is disconnected
2524         // when a Lua function modifies l_punch, for example
2525         if (!playersao)
2526                 return;
2527
2528         infostream << "Server::DiePlayer(): Player "
2529                         << playersao->getPlayer()->getName()
2530                         << " dies" << std::endl;
2531
2532         playersao->setHP(0);
2533
2534         // Trigger scripted stuff
2535         m_script->on_dieplayer(playersao);
2536
2537         SendPlayerHP(peer_id);
2538         SendDeathscreen(peer_id, false, v3f(0,0,0));
2539 }
2540
2541 void Server::RespawnPlayer(u16 peer_id)
2542 {
2543         DSTACK(FUNCTION_NAME);
2544
2545         PlayerSAO *playersao = getPlayerSAO(peer_id);
2546         assert(playersao);
2547
2548         infostream << "Server::RespawnPlayer(): Player "
2549                         << playersao->getPlayer()->getName()
2550                         << " respawns" << std::endl;
2551
2552         playersao->setHP(PLAYER_MAX_HP);
2553         playersao->setBreath(PLAYER_MAX_BREATH);
2554
2555         SendPlayerHP(peer_id);
2556         SendPlayerBreath(peer_id);
2557
2558         bool repositioned = m_script->on_respawnplayer(playersao);
2559         if(!repositioned){
2560                 v3f pos = findSpawnPos();
2561                 // setPos will send the new position to client
2562                 playersao->setPos(pos);
2563         }
2564 }
2565
2566
2567 void Server::DenySudoAccess(u16 peer_id)
2568 {
2569         DSTACK(FUNCTION_NAME);
2570
2571         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2572         Send(&pkt);
2573 }
2574
2575
2576 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2577                 const std::string &str_reason, bool reconnect)
2578 {
2579         if (proto_ver >= 25) {
2580                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2581         } else {
2582                 std::wstring wreason = utf8_to_wide(
2583                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2584                         accessDeniedStrings[(u8)reason]);
2585                 SendAccessDenied_Legacy(peer_id, wreason);
2586         }
2587
2588         m_clients.event(peer_id, CSE_SetDenied);
2589         m_con.DisconnectPeer(peer_id);
2590 }
2591
2592
2593 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2594 {
2595         DSTACK(FUNCTION_NAME);
2596
2597         SendAccessDenied(peer_id, reason, custom_reason);
2598         m_clients.event(peer_id, CSE_SetDenied);
2599         m_con.DisconnectPeer(peer_id);
2600 }
2601
2602 // 13/03/15: remove this function when protocol version 25 will become
2603 // the minimum version for MT users, maybe in 1 year
2604 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2605 {
2606         DSTACK(FUNCTION_NAME);
2607
2608         SendAccessDenied_Legacy(peer_id, reason);
2609         m_clients.event(peer_id, CSE_SetDenied);
2610         m_con.DisconnectPeer(peer_id);
2611 }
2612
2613 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2614 {
2615         DSTACK(FUNCTION_NAME);
2616
2617         if (!forSudoMode) {
2618                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2619
2620                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2621
2622                 // Right now, the auth mechs don't change between login and sudo mode.
2623                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2624                 client->allowed_sudo_mechs = sudo_auth_mechs;
2625
2626                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2627                                 << g_settings->getFloat("dedicated_server_step")
2628                                 << sudo_auth_mechs;
2629
2630                 Send(&resp_pkt);
2631                 m_clients.event(peer_id, CSE_AuthAccept);
2632         } else {
2633                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2634
2635                 // We only support SRP right now
2636                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2637
2638                 resp_pkt << sudo_auth_mechs;
2639                 Send(&resp_pkt);
2640                 m_clients.event(peer_id, CSE_SudoSuccess);
2641         }
2642 }
2643
2644 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2645 {
2646         DSTACK(FUNCTION_NAME);
2647         std::wstring message;
2648         {
2649                 /*
2650                         Clear references to playing sounds
2651                 */
2652                 for(std::map<s32, ServerPlayingSound>::iterator
2653                                 i = m_playing_sounds.begin();
2654                                 i != m_playing_sounds.end();)
2655                 {
2656                         ServerPlayingSound &psound = i->second;
2657                         psound.clients.erase(peer_id);
2658                         if(psound.clients.empty())
2659                                 m_playing_sounds.erase(i++);
2660                         else
2661                                 ++i;
2662                 }
2663
2664                 Player *player = m_env->getPlayer(peer_id);
2665
2666                 // Collect information about leaving in chat
2667                 {
2668                         if(player != NULL && reason != CDR_DENY)
2669                         {
2670                                 std::wstring name = narrow_to_wide(player->getName());
2671                                 message += L"*** ";
2672                                 message += name;
2673                                 message += L" left the game.";
2674                                 if(reason == CDR_TIMEOUT)
2675                                         message += L" (timed out)";
2676                         }
2677                 }
2678
2679                 /* Run scripts and remove from environment */
2680                 {
2681                         if(player != NULL)
2682                         {
2683                                 PlayerSAO *playersao = player->getPlayerSAO();
2684                                 assert(playersao);
2685
2686                                 m_script->on_leaveplayer(playersao);
2687
2688                                 playersao->disconnected();
2689                         }
2690                 }
2691
2692                 /*
2693                         Print out action
2694                 */
2695                 {
2696                         if(player != NULL && reason != CDR_DENY) {
2697                                 std::ostringstream os(std::ios_base::binary);
2698                                 std::vector<u16> clients = m_clients.getClientIDs();
2699
2700                                 for(std::vector<u16>::iterator i = clients.begin();
2701                                         i != clients.end(); ++i) {
2702                                         // Get player
2703                                         Player *player = m_env->getPlayer(*i);
2704                                         if(!player)
2705                                                 continue;
2706
2707                                         // Get name of player
2708                                         os << player->getName() << " ";
2709                                 }
2710
2711                                 std::string name = player->getName();
2712                                 actionstream << name << " "
2713                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2714                                                 << " List of players: " << os.str() << std::endl;
2715                                 if (m_admin_chat)
2716                                         m_admin_chat->outgoing_queue.push_back(
2717                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2718                         }
2719                 }
2720                 {
2721                         MutexAutoLock env_lock(m_env_mutex);
2722                         m_clients.DeleteClient(peer_id);
2723                 }
2724         }
2725
2726         // Send leave chat message to all remaining clients
2727         if(message.length() != 0)
2728                 SendChatMessage(PEER_ID_INEXISTENT,message);
2729 }
2730
2731 void Server::UpdateCrafting(Player* player)
2732 {
2733         DSTACK(FUNCTION_NAME);
2734
2735         // Get a preview for crafting
2736         ItemStack preview;
2737         InventoryLocation loc;
2738         loc.setPlayer(player->getName());
2739         std::vector<ItemStack> output_replacements;
2740         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2741         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
2742
2743         // Put the new preview in
2744         InventoryList *plist = player->inventory.getList("craftpreview");
2745         sanity_check(plist);
2746         sanity_check(plist->getSize() >= 1);
2747         plist->changeItem(0, preview);
2748 }
2749
2750 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2751 {
2752         if (evt->type == CET_NICK_ADD) {
2753                 // The terminal informed us of its nick choice
2754                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2755                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2756                         errorstream << "You haven't set up an account." << std::endl
2757                                 << "Please log in using the client as '"
2758                                 << m_admin_nick << "' with a secure password." << std::endl
2759                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2760                                 << "and everybody can claim the user account instead of you," << std::endl
2761                                 << "giving them full control over this server." << std::endl;
2762                 }
2763         } else {
2764                 assert(evt->type == CET_CHAT);
2765                 handleAdminChat((ChatEventChat *)evt);
2766         }
2767 }
2768
2769 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2770         const std::wstring &wmessage, bool check_shout_priv,
2771         u16 peer_id_to_avoid_sending)
2772 {
2773         // If something goes wrong, this player is to blame
2774         RollbackScopeActor rollback_scope(m_rollback,
2775                 std::string("player:") + name);
2776
2777         // Line to send
2778         std::wstring line;
2779         // Whether to send line to the player that sent the message, or to all players
2780         bool broadcast_line = true;
2781
2782         // Run script hook
2783         bool ate = m_script->on_chat_message(name,
2784                 wide_to_utf8(wmessage));
2785         // If script ate the message, don't proceed
2786         if (ate)
2787                 return L"";
2788
2789         // Commands are implemented in Lua, so only catch invalid
2790         // commands that were not "eaten" and send an error back
2791         if (wmessage[0] == L'/') {
2792                 std::wstring wcmd = wmessage.substr(1);
2793                 broadcast_line = false;
2794                 if (wcmd.length() == 0)
2795                         line += L"-!- Empty command";
2796                 else
2797                         line += L"-!- Invalid command: " + str_split(wcmd, L' ')[0];
2798         } else {
2799                 if (check_shout_priv && !checkPriv(name, "shout")) {
2800                         line += L"-!- You don't have permission to shout.";
2801                         broadcast_line = false;
2802                 } else {
2803                         line += L"<";
2804                         line += wname;
2805                         line += L"> ";
2806                         line += wmessage;
2807                 }
2808         }
2809
2810         /*
2811                 Tell calling method to send the message to sender
2812         */
2813         if (!broadcast_line) {
2814                 return line;
2815         } else {
2816                 /*
2817                         Send the message to others
2818                 */
2819                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2820
2821                 std::vector<u16> clients = m_clients.getClientIDs();
2822
2823                 for (u16 i = 0; i < clients.size(); i++) {
2824                         u16 cid = clients[i];
2825                         if (cid != peer_id_to_avoid_sending)
2826                                 SendChatMessage(cid, line);
2827                 }
2828         }
2829         return L"";
2830 }
2831
2832 void Server::handleAdminChat(const ChatEventChat *evt)
2833 {
2834         std::string name = evt->nick;
2835         std::wstring wname = utf8_to_wide(name);
2836         std::wstring wmessage = evt->evt_msg;
2837
2838         std::wstring answer = handleChat(name, wname, wmessage);
2839
2840         // If asked to send answer to sender
2841         if (!answer.empty()) {
2842                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2843         }
2844 }
2845
2846 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2847 {
2848         RemoteClient *client = getClientNoEx(peer_id,state_min);
2849         if(!client)
2850                 throw ClientNotFoundException("Client not found");
2851
2852         return client;
2853 }
2854 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2855 {
2856         return m_clients.getClientNoEx(peer_id, state_min);
2857 }
2858
2859 std::string Server::getPlayerName(u16 peer_id)
2860 {
2861         Player *player = m_env->getPlayer(peer_id);
2862         if(player == NULL)
2863                 return "[id="+itos(peer_id)+"]";
2864         return player->getName();
2865 }
2866
2867 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2868 {
2869         Player *player = m_env->getPlayer(peer_id);
2870         if(player == NULL)
2871                 return NULL;
2872         return player->getPlayerSAO();
2873 }
2874
2875 std::wstring Server::getStatusString()
2876 {
2877         std::wostringstream os(std::ios_base::binary);
2878         os<<L"# Server: ";
2879         // Version
2880         os<<L"version="<<narrow_to_wide(g_version_string);
2881         // Uptime
2882         os<<L", uptime="<<m_uptime.get();
2883         // Max lag estimate
2884         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2885         // Information about clients
2886         bool first = true;
2887         os<<L", clients={";
2888         std::vector<u16> clients = m_clients.getClientIDs();
2889         for(std::vector<u16>::iterator i = clients.begin();
2890                 i != clients.end(); ++i) {
2891                 // Get player
2892                 Player *player = m_env->getPlayer(*i);
2893                 // Get name of player
2894                 std::wstring name = L"unknown";
2895                 if(player != NULL)
2896                         name = narrow_to_wide(player->getName());
2897                 // Add name to information string
2898                 if(!first)
2899                         os << L", ";
2900                 else
2901                         first = false;
2902                 os << name;
2903         }
2904         os << L"}";
2905         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2906                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2907         if(g_settings->get("motd") != "")
2908                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2909         return os.str();
2910 }
2911
2912 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2913 {
2914         std::set<std::string> privs;
2915         m_script->getAuth(name, NULL, &privs);
2916         return privs;
2917 }
2918
2919 bool Server::checkPriv(const std::string &name, const std::string &priv)
2920 {
2921         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2922         return (privs.count(priv) != 0);
2923 }
2924
2925 void Server::reportPrivsModified(const std::string &name)
2926 {
2927         if(name == "") {
2928                 std::vector<u16> clients = m_clients.getClientIDs();
2929                 for(std::vector<u16>::iterator i = clients.begin();
2930                                 i != clients.end(); ++i) {
2931                         Player *player = m_env->getPlayer(*i);
2932                         reportPrivsModified(player->getName());
2933                 }
2934         } else {
2935                 Player *player = m_env->getPlayer(name.c_str());
2936                 if(!player)
2937                         return;
2938                 SendPlayerPrivileges(player->peer_id);
2939                 PlayerSAO *sao = player->getPlayerSAO();
2940                 if(!sao)
2941                         return;
2942                 sao->updatePrivileges(
2943                                 getPlayerEffectivePrivs(name),
2944                                 isSingleplayer());
2945         }
2946 }
2947
2948 void Server::reportInventoryFormspecModified(const std::string &name)
2949 {
2950         Player *player = m_env->getPlayer(name.c_str());
2951         if(!player)
2952                 return;
2953         SendPlayerInventoryFormspec(player->peer_id);
2954 }
2955
2956 void Server::setIpBanned(const std::string &ip, const std::string &name)
2957 {
2958         m_banmanager->add(ip, name);
2959 }
2960
2961 void Server::unsetIpBanned(const std::string &ip_or_name)
2962 {
2963         m_banmanager->remove(ip_or_name);
2964 }
2965
2966 std::string Server::getBanDescription(const std::string &ip_or_name)
2967 {
2968         return m_banmanager->getBanDescription(ip_or_name);
2969 }
2970
2971 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2972 {
2973         // m_env will be NULL if the server is initializing
2974         if (!m_env)
2975                 return;
2976
2977         if (m_admin_nick == name && !m_admin_nick.empty()) {
2978                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
2979         }
2980
2981         Player *player = m_env->getPlayer(name);
2982         if (!player) {
2983                 return;
2984         }
2985
2986         if (player->peer_id == PEER_ID_INEXISTENT)
2987                 return;
2988
2989         SendChatMessage(player->peer_id, msg);
2990 }
2991
2992 bool Server::showFormspec(const char *playername, const std::string &formspec,
2993         const std::string &formname)
2994 {
2995         // m_env will be NULL if the server is initializing
2996         if (!m_env)
2997                 return false;
2998
2999         Player *player = m_env->getPlayer(playername);
3000         if (!player)
3001                 return false;
3002
3003         SendShowFormspecMessage(player->peer_id, formspec, formname);
3004         return true;
3005 }
3006
3007 u32 Server::hudAdd(Player *player, HudElement *form)
3008 {
3009         if (!player)
3010                 return -1;
3011
3012         u32 id = player->addHud(form);
3013
3014         SendHUDAdd(player->peer_id, id, form);
3015
3016         return id;
3017 }
3018
3019 bool Server::hudRemove(Player *player, u32 id) {
3020         if (!player)
3021                 return false;
3022
3023         HudElement* todel = player->removeHud(id);
3024
3025         if (!todel)
3026                 return false;
3027
3028         delete todel;
3029
3030         SendHUDRemove(player->peer_id, id);
3031         return true;
3032 }
3033
3034 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data)
3035 {
3036         if (!player)
3037                 return false;
3038
3039         SendHUDChange(player->peer_id, id, stat, data);
3040         return true;
3041 }
3042
3043 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask)
3044 {
3045         if (!player)
3046                 return false;
3047
3048         SendHUDSetFlags(player->peer_id, flags, mask);
3049         player->hud_flags &= ~mask;
3050         player->hud_flags |= flags;
3051
3052         PlayerSAO* playersao = player->getPlayerSAO();
3053
3054         if (playersao == NULL)
3055                 return false;
3056
3057         m_script->player_event(playersao, "hud_changed");
3058         return true;
3059 }
3060
3061 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount)
3062 {
3063         if (!player)
3064                 return false;
3065         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3066                 return false;
3067
3068         player->setHotbarItemcount(hotbar_itemcount);
3069         std::ostringstream os(std::ios::binary);
3070         writeS32(os, hotbar_itemcount);
3071         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3072         return true;
3073 }
3074
3075 s32 Server::hudGetHotbarItemcount(Player *player)
3076 {
3077         if (!player)
3078                 return 0;
3079         return player->getHotbarItemcount();
3080 }
3081
3082 void Server::hudSetHotbarImage(Player *player, std::string name)
3083 {
3084         if (!player)
3085                 return;
3086
3087         player->setHotbarImage(name);
3088         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3089 }
3090
3091 std::string Server::hudGetHotbarImage(Player *player)
3092 {
3093         if (!player)
3094                 return "";
3095         return player->getHotbarImage();
3096 }
3097
3098 void Server::hudSetHotbarSelectedImage(Player *player, std::string name)
3099 {
3100         if (!player)
3101                 return;
3102
3103         player->setHotbarSelectedImage(name);
3104         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3105 }
3106
3107 std::string Server::hudGetHotbarSelectedImage(Player *player)
3108 {
3109         if (!player)
3110                 return "";
3111
3112         return player->getHotbarSelectedImage();
3113 }
3114
3115 bool Server::setLocalPlayerAnimations(Player *player,
3116         v2s32 animation_frames[4], f32 frame_speed)
3117 {
3118         if (!player)
3119                 return false;
3120
3121         player->setLocalAnimations(animation_frames, frame_speed);
3122         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3123         return true;
3124 }
3125
3126 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
3127 {
3128         if (!player)
3129                 return false;
3130
3131         player->eye_offset_first = first;
3132         player->eye_offset_third = third;
3133         SendEyeOffset(player->peer_id, first, third);
3134         return true;
3135 }
3136
3137 bool Server::setSky(Player *player, const video::SColor &bgcolor,
3138         const std::string &type, const std::vector<std::string> &params)
3139 {
3140         if (!player)
3141                 return false;
3142
3143         player->setSky(bgcolor, type, params);
3144         SendSetSky(player->peer_id, bgcolor, type, params);
3145         return true;
3146 }
3147
3148 bool Server::overrideDayNightRatio(Player *player, bool do_override,
3149         float ratio)
3150 {
3151         if (!player)
3152                 return false;
3153
3154         player->overrideDayNightRatio(do_override, ratio);
3155         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3156         return true;
3157 }
3158
3159 void Server::notifyPlayers(const std::wstring &msg)
3160 {
3161         SendChatMessage(PEER_ID_INEXISTENT,msg);
3162 }
3163
3164 void Server::spawnParticle(const std::string &playername, v3f pos,
3165         v3f velocity, v3f acceleration,
3166         float expirationtime, float size, bool
3167         collisiondetection, bool collision_removal,
3168         bool vertical, const std::string &texture)
3169 {
3170         // m_env will be NULL if the server is initializing
3171         if (!m_env)
3172                 return;
3173
3174         u16 peer_id = PEER_ID_INEXISTENT;
3175         if (playername != "") {
3176                 Player* player = m_env->getPlayer(playername.c_str());
3177                 if (!player)
3178                         return;
3179                 peer_id = player->peer_id;
3180         }
3181
3182         SendSpawnParticle(peer_id, pos, velocity, acceleration,
3183                         expirationtime, size, collisiondetection,
3184                         collision_removal, vertical, texture);
3185 }
3186
3187 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3188         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3189         float minexptime, float maxexptime, float minsize, float maxsize,
3190         bool collisiondetection, bool collision_removal,
3191         bool vertical, const std::string &texture,
3192         const std::string &playername)
3193 {
3194         // m_env will be NULL if the server is initializing
3195         if (!m_env)
3196                 return -1;
3197
3198         u16 peer_id = PEER_ID_INEXISTENT;
3199         if (playername != "") {
3200                 Player* player = m_env->getPlayer(playername.c_str());
3201                 if (!player)
3202                         return -1;
3203                 peer_id = player->peer_id;
3204         }
3205
3206         u32 id = m_env->addParticleSpawner(spawntime);
3207         SendAddParticleSpawner(peer_id, amount, spawntime,
3208                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3209                 minexptime, maxexptime, minsize, maxsize,
3210                 collisiondetection, collision_removal, vertical, texture, id);
3211
3212         return id;
3213 }
3214
3215 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3216 {
3217         // m_env will be NULL if the server is initializing
3218         if (!m_env)
3219                 throw ServerError("Can't delete particle spawners during initialisation!");
3220
3221         u16 peer_id = PEER_ID_INEXISTENT;
3222         if (playername != "") {
3223                 Player* player = m_env->getPlayer(playername.c_str());
3224                 if (!player)
3225                         return;
3226                 peer_id = player->peer_id;
3227         }
3228
3229         m_env->deleteParticleSpawner(id);
3230         SendDeleteParticleSpawner(peer_id, id);
3231 }
3232
3233 void Server::deleteParticleSpawnerAll(u32 id)
3234 {
3235         m_env->deleteParticleSpawner(id);
3236         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3237 }
3238
3239 Inventory* Server::createDetachedInventory(const std::string &name)
3240 {
3241         if(m_detached_inventories.count(name) > 0){
3242                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3243                 delete m_detached_inventories[name];
3244         } else {
3245                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3246         }
3247         Inventory *inv = new Inventory(m_itemdef);
3248         sanity_check(inv);
3249         m_detached_inventories[name] = inv;
3250         //TODO find a better way to do this
3251         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3252         return inv;
3253 }
3254
3255 // actions: time-reversed list
3256 // Return value: success/failure
3257 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3258                 std::list<std::string> *log)
3259 {
3260         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3261         ServerMap *map = (ServerMap*)(&m_env->getMap());
3262
3263         // Fail if no actions to handle
3264         if(actions.empty()){
3265                 log->push_back("Nothing to do.");
3266                 return false;
3267         }
3268
3269         int num_tried = 0;
3270         int num_failed = 0;
3271
3272         for(std::list<RollbackAction>::const_iterator
3273                         i = actions.begin();
3274                         i != actions.end(); ++i)
3275         {
3276                 const RollbackAction &action = *i;
3277                 num_tried++;
3278                 bool success = action.applyRevert(map, this, this);
3279                 if(!success){
3280                         num_failed++;
3281                         std::ostringstream os;
3282                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3283                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3284                         if(log)
3285                                 log->push_back(os.str());
3286                 }else{
3287                         std::ostringstream os;
3288                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3289                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3290                         if(log)
3291                                 log->push_back(os.str());
3292                 }
3293         }
3294
3295         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3296                         <<" failed"<<std::endl;
3297
3298         // Call it done if less than half failed
3299         return num_failed <= num_tried/2;
3300 }
3301
3302 // IGameDef interface
3303 // Under envlock
3304 IItemDefManager *Server::getItemDefManager()
3305 {
3306         return m_itemdef;
3307 }
3308
3309 INodeDefManager *Server::getNodeDefManager()
3310 {
3311         return m_nodedef;
3312 }
3313
3314 ICraftDefManager *Server::getCraftDefManager()
3315 {
3316         return m_craftdef;
3317 }
3318 ITextureSource *Server::getTextureSource()
3319 {
3320         return NULL;
3321 }
3322 IShaderSource *Server::getShaderSource()
3323 {
3324         return NULL;
3325 }
3326 scene::ISceneManager *Server::getSceneManager()
3327 {
3328         return NULL;
3329 }
3330
3331 u16 Server::allocateUnknownNodeId(const std::string &name)
3332 {
3333         return m_nodedef->allocateDummy(name);
3334 }
3335
3336 ISoundManager *Server::getSoundManager()
3337 {
3338         return &dummySoundManager;
3339 }
3340
3341 MtEventManager *Server::getEventManager()
3342 {
3343         return m_event;
3344 }
3345
3346 IWritableItemDefManager *Server::getWritableItemDefManager()
3347 {
3348         return m_itemdef;
3349 }
3350
3351 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3352 {
3353         return m_nodedef;
3354 }
3355
3356 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3357 {
3358         return m_craftdef;
3359 }
3360
3361 const ModSpec *Server::getModSpec(const std::string &modname) const
3362 {
3363         std::vector<ModSpec>::const_iterator it;
3364         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3365                 const ModSpec &mod = *it;
3366                 if (mod.name == modname)
3367                         return &mod;
3368         }
3369         return NULL;
3370 }
3371
3372 void Server::getModNames(std::vector<std::string> &modlist)
3373 {
3374         std::vector<ModSpec>::iterator it;
3375         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3376                 modlist.push_back(it->name);
3377 }
3378
3379 std::string Server::getBuiltinLuaPath()
3380 {
3381         return porting::path_share + DIR_DELIM + "builtin";
3382 }
3383
3384 v3f Server::findSpawnPos()
3385 {
3386         ServerMap &map = m_env->getServerMap();
3387         v3f nodeposf;
3388         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3389                 return nodeposf * BS;
3390         }
3391
3392         bool is_good = false;
3393
3394         // Try to find a good place a few times
3395         for(s32 i = 0; i < 4000 && !is_good; i++) {
3396                 s32 range = 1 + i;
3397                 // We're going to try to throw the player to this position
3398                 v2s16 nodepos2d = v2s16(
3399                                 -range + (myrand() % (range * 2)),
3400                                 -range + (myrand() % (range * 2)));
3401
3402                 // Get spawn level at point
3403                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3404                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3405                 // the mapgen to signify an unsuitable spawn position
3406                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3407                         continue;
3408
3409                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3410
3411                 s32 air_count = 0;
3412                 for (s32 i = 0; i < 10; i++) {
3413                         v3s16 blockpos = getNodeBlockPos(nodepos);
3414                         map.emergeBlock(blockpos, true);
3415                         content_t c = map.getNodeNoEx(nodepos).getContent();
3416                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3417                                 air_count++;
3418                                 if (air_count >= 2) {
3419                                         nodeposf = intToFloat(nodepos, BS);
3420                                         // Don't spawn the player outside map boundaries
3421                                         if (objectpos_over_limit(nodeposf))
3422                                                 continue;
3423                                         is_good = true;
3424                                         break;
3425                                 }
3426                         }
3427                         nodepos.Y++;
3428                 }
3429         }
3430
3431         return nodeposf;
3432 }
3433
3434 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3435 {
3436         bool newplayer = false;
3437
3438         /*
3439                 Try to get an existing player
3440         */
3441         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3442
3443         // If player is already connected, cancel
3444         if(player != NULL && player->peer_id != 0)
3445         {
3446                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3447                 return NULL;
3448         }
3449
3450         /*
3451                 If player with the wanted peer_id already exists, cancel.
3452         */
3453         if(m_env->getPlayer(peer_id) != NULL)
3454         {
3455                 infostream<<"emergePlayer(): Player with wrong name but same"
3456                                 " peer_id already exists"<<std::endl;
3457                 return NULL;
3458         }
3459
3460         // Load player if it isn't already loaded
3461         if (!player) {
3462                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3463         }
3464
3465         // Create player if it doesn't exist
3466         if (!player) {
3467                 newplayer = true;
3468                 player = new RemotePlayer(this, name);
3469                 // Set player position
3470                 infostream<<"Server: Finding spawn place for player \""
3471                                 <<name<<"\""<<std::endl;
3472                 v3f pos = findSpawnPos();
3473                 player->setPosition(pos);
3474
3475                 // Make sure the player is saved
3476                 player->setModified(true);
3477
3478                 // Add player to environment
3479                 m_env->addPlayer(player);
3480         } else {
3481                 // If the player exists, ensure that they respawn inside legal bounds
3482                 // This fixes an assert crash when the player can't be added
3483                 // to the environment
3484                 if (objectpos_over_limit(player->getPosition())) {
3485                         actionstream << "Respawn position for player \""
3486                                 << name << "\" outside limits, resetting" << std::endl;
3487                         v3f pos = findSpawnPos();
3488                         player->setPosition(pos);
3489                 }
3490         }
3491
3492         // Create a new player active object
3493         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3494                         getPlayerEffectivePrivs(player->getName()),
3495                         isSingleplayer());
3496
3497         player->protocol_version = proto_version;
3498
3499         /* Clean up old HUD elements from previous sessions */
3500         player->clearHud();
3501
3502         /* Add object to environment */
3503         m_env->addActiveObject(playersao);
3504
3505         /* Run scripts */
3506         if (newplayer) {
3507                 m_script->on_newplayer(playersao);
3508         }
3509
3510         return playersao;
3511 }
3512
3513 void dedicated_server_loop(Server &server, bool &kill)
3514 {
3515         DSTACK(FUNCTION_NAME);
3516
3517         verbosestream<<"dedicated_server_loop()"<<std::endl;
3518
3519         IntervalLimiter m_profiler_interval;
3520
3521         static const float steplen = g_settings->getFloat("dedicated_server_step");
3522         static const float profiler_print_interval =
3523                         g_settings->getFloat("profiler_print_interval");
3524
3525         for(;;) {
3526                 // This is kind of a hack but can be done like this
3527                 // because server.step() is very light
3528                 {
3529                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3530                         sleep_ms((int)(steplen*1000.0));
3531                 }
3532                 server.step(steplen);
3533
3534                 if(server.getShutdownRequested() || kill)
3535                 {
3536                         infostream<<"Dedicated server quitting"<<std::endl;
3537 #if USE_CURL
3538                         if(g_settings->getBool("server_announce"))
3539                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3540 #endif
3541                         break;
3542                 }
3543
3544                 /*
3545                         Profiler
3546                 */
3547                 if (profiler_print_interval != 0) {
3548                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3549                         {
3550                                 infostream<<"Profiler:"<<std::endl;
3551                                 g_profiler->print(infostream);
3552                                 g_profiler->clear();
3553                         }
3554                 }
3555         }
3556 }