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