]> git.lizzy.rs Git - minetest.git/blob - src/server.cpp
Dungeongen: Fix out-of-voxelmanip access segfault
[minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "threading/mutex_auto_lock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_game.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_abm.h"
51 #include "content_sao.h"
52 #include "mods.h"
53 #include "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 && g_settings->getBool("show_statusline_on_connect")) {
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         infostream << "Server::DiePlayer(): Player "
2564                         << playersao->getPlayer()->getName()
2565                         << " dies" << std::endl;
2566
2567         playersao->setHP(0);
2568
2569         // Trigger scripted stuff
2570         m_script->on_dieplayer(playersao);
2571
2572         SendPlayerHP(peer_id);
2573         SendDeathscreen(peer_id, false, v3f(0,0,0));
2574 }
2575
2576 void Server::RespawnPlayer(u16 peer_id)
2577 {
2578         DSTACK(FUNCTION_NAME);
2579
2580         PlayerSAO *playersao = getPlayerSAO(peer_id);
2581         assert(playersao);
2582
2583         infostream << "Server::RespawnPlayer(): Player "
2584                         << playersao->getPlayer()->getName()
2585                         << " respawns" << std::endl;
2586
2587         playersao->setHP(PLAYER_MAX_HP);
2588         playersao->setBreath(PLAYER_MAX_BREATH);
2589
2590         bool repositioned = m_script->on_respawnplayer(playersao);
2591         if (!repositioned) {
2592                 v3f pos = findSpawnPos();
2593                 // setPos will send the new position to client
2594                 playersao->setPos(pos);
2595         }
2596
2597         SendPlayerHP(peer_id);
2598 }
2599
2600
2601 void Server::DenySudoAccess(u16 peer_id)
2602 {
2603         DSTACK(FUNCTION_NAME);
2604
2605         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2606         Send(&pkt);
2607 }
2608
2609
2610 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2611                 const std::string &str_reason, bool reconnect)
2612 {
2613         if (proto_ver >= 25) {
2614                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2615         } else {
2616                 std::wstring wreason = utf8_to_wide(
2617                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2618                         accessDeniedStrings[(u8)reason]);
2619                 SendAccessDenied_Legacy(peer_id, wreason);
2620         }
2621
2622         m_clients.event(peer_id, CSE_SetDenied);
2623         m_con.DisconnectPeer(peer_id);
2624 }
2625
2626
2627 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2628 {
2629         DSTACK(FUNCTION_NAME);
2630
2631         SendAccessDenied(peer_id, reason, custom_reason);
2632         m_clients.event(peer_id, CSE_SetDenied);
2633         m_con.DisconnectPeer(peer_id);
2634 }
2635
2636 // 13/03/15: remove this function when protocol version 25 will become
2637 // the minimum version for MT users, maybe in 1 year
2638 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2639 {
2640         DSTACK(FUNCTION_NAME);
2641
2642         SendAccessDenied_Legacy(peer_id, reason);
2643         m_clients.event(peer_id, CSE_SetDenied);
2644         m_con.DisconnectPeer(peer_id);
2645 }
2646
2647 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2648 {
2649         DSTACK(FUNCTION_NAME);
2650
2651         if (!forSudoMode) {
2652                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2653
2654                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2655
2656                 // Right now, the auth mechs don't change between login and sudo mode.
2657                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2658                 client->allowed_sudo_mechs = sudo_auth_mechs;
2659
2660                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2661                                 << g_settings->getFloat("dedicated_server_step")
2662                                 << sudo_auth_mechs;
2663
2664                 Send(&resp_pkt);
2665                 m_clients.event(peer_id, CSE_AuthAccept);
2666         } else {
2667                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2668
2669                 // We only support SRP right now
2670                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2671
2672                 resp_pkt << sudo_auth_mechs;
2673                 Send(&resp_pkt);
2674                 m_clients.event(peer_id, CSE_SudoSuccess);
2675         }
2676 }
2677
2678 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2679 {
2680         DSTACK(FUNCTION_NAME);
2681         std::wstring message;
2682         {
2683                 /*
2684                         Clear references to playing sounds
2685                 */
2686                 for (UNORDERED_MAP<s32, ServerPlayingSound>::iterator
2687                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2688                         ServerPlayingSound &psound = i->second;
2689                         psound.clients.erase(peer_id);
2690                         if (psound.clients.empty())
2691                                 m_playing_sounds.erase(i++);
2692                         else
2693                                 ++i;
2694                 }
2695
2696                 RemotePlayer *player = m_env->getPlayer(peer_id);
2697
2698                 /* Run scripts and remove from environment */
2699                 if (player != NULL) {
2700                         PlayerSAO *playersao = player->getPlayerSAO();
2701                         assert(playersao);
2702
2703                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2704
2705                         playersao->disconnected();
2706                 }
2707
2708                 /*
2709                         Print out action
2710                 */
2711                 {
2712                         if(player != NULL && reason != CDR_DENY) {
2713                                 std::ostringstream os(std::ios_base::binary);
2714                                 std::vector<u16> clients = m_clients.getClientIDs();
2715
2716                                 for(std::vector<u16>::iterator i = clients.begin();
2717                                         i != clients.end(); ++i) {
2718                                         // Get player
2719                                         RemotePlayer *player = m_env->getPlayer(*i);
2720                                         if (!player)
2721                                                 continue;
2722
2723                                         // Get name of player
2724                                         os << player->getName() << " ";
2725                                 }
2726
2727                                 std::string name = player->getName();
2728                                 actionstream << name << " "
2729                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2730                                                 << " List of players: " << os.str() << std::endl;
2731                                 if (m_admin_chat)
2732                                         m_admin_chat->outgoing_queue.push_back(
2733                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2734                         }
2735                 }
2736                 {
2737                         MutexAutoLock env_lock(m_env_mutex);
2738                         m_clients.DeleteClient(peer_id);
2739                 }
2740         }
2741
2742         // Send leave chat message to all remaining clients
2743         if(message.length() != 0)
2744                 SendChatMessage(PEER_ID_INEXISTENT,message);
2745 }
2746
2747 void Server::UpdateCrafting(RemotePlayer *player)
2748 {
2749         DSTACK(FUNCTION_NAME);
2750
2751         // Get a preview for crafting
2752         ItemStack preview;
2753         InventoryLocation loc;
2754         loc.setPlayer(player->getName());
2755         std::vector<ItemStack> output_replacements;
2756         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2757         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2758                         (&player->inventory)->getList("craft"), loc);
2759
2760         // Put the new preview in
2761         InventoryList *plist = player->inventory.getList("craftpreview");
2762         sanity_check(plist);
2763         sanity_check(plist->getSize() >= 1);
2764         plist->changeItem(0, preview);
2765 }
2766
2767 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2768 {
2769         if (evt->type == CET_NICK_ADD) {
2770                 // The terminal informed us of its nick choice
2771                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2772                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2773                         errorstream << "You haven't set up an account." << std::endl
2774                                 << "Please log in using the client as '"
2775                                 << m_admin_nick << "' with a secure password." << std::endl
2776                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2777                                 << "and everybody can claim the user account instead of you," << std::endl
2778                                 << "giving them full control over this server." << std::endl;
2779                 }
2780         } else {
2781                 assert(evt->type == CET_CHAT);
2782                 handleAdminChat((ChatEventChat *)evt);
2783         }
2784 }
2785
2786 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2787         const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
2788 {
2789         // If something goes wrong, this player is to blame
2790         RollbackScopeActor rollback_scope(m_rollback,
2791                 std::string("player:") + name);
2792
2793         if (player) {
2794                 switch (player->canSendChatMessage()) {
2795                         case RPLAYER_CHATRESULT_FLOODING: {
2796                                 std::wstringstream ws;
2797                                 ws << L"You cannot send more messages. You are limited to "
2798                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2799                                    << L" messages per 10 seconds.";
2800                                 return ws.str();
2801                         }
2802                         case RPLAYER_CHATRESULT_KICK:
2803                                 DenyAccess_Legacy(player->peer_id,
2804                                                 L"You have been kicked due to message flooding.");
2805                                 return L"";
2806                         case RPLAYER_CHATRESULT_OK:
2807                                 break;
2808                         default:
2809                                 FATAL_ERROR("Unhandled chat filtering result found.");
2810                 }
2811         }
2812
2813         if (m_max_chatmessage_length > 0
2814                         && wmessage.length() > m_max_chatmessage_length) {
2815                 return L"Your message exceed the maximum chat message limit set on the server. "
2816                                 L"It was refused. Send a shorter message";
2817         }
2818
2819         // Run script hook, exit if script ate the chat message
2820         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2821                 return L"";
2822
2823         // Line to send
2824         std::wstring line;
2825         // Whether to send line to the player that sent the message, or to all players
2826         bool broadcast_line = true;
2827
2828         // Commands are implemented in Lua, so only catch invalid
2829         // commands that were not "eaten" and send an error back
2830         if (wmessage[0] == L'/') {
2831                 std::wstring wcmd = wmessage.substr(1);
2832                 broadcast_line = false;
2833                 if (wcmd.length() == 0)
2834                         line += L"-!- Empty command";
2835                 else
2836                         line += L"-!- Invalid command: " + str_split(wcmd, L' ')[0];
2837         } else {
2838                 if (check_shout_priv && !checkPriv(name, "shout")) {
2839                         line += L"-!- You don't have permission to shout.";
2840                         broadcast_line = false;
2841                 } else {
2842                         line += L"<";
2843                         line += wname;
2844                         line += L"> ";
2845                         line += wmessage;
2846                 }
2847         }
2848
2849         /*
2850                 Tell calling method to send the message to sender
2851         */
2852         if (!broadcast_line) {
2853                 return line;
2854         } else {
2855                 /*
2856                         Send the message to others
2857                 */
2858                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2859
2860                 std::vector<u16> clients = m_clients.getClientIDs();
2861
2862                 /*
2863                         Send the message back to the inital sender
2864                         if they are using protocol version >= 29
2865                 */
2866
2867                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2868                 if (player && player->protocol_version >= 29)
2869                         peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2870
2871                 for (u16 i = 0; i < clients.size(); i++) {
2872                         u16 cid = clients[i];
2873                         if (cid != peer_id_to_avoid_sending)
2874                                 SendChatMessage(cid, line);
2875                 }
2876         }
2877         return L"";
2878 }
2879
2880 void Server::handleAdminChat(const ChatEventChat *evt)
2881 {
2882         std::string name = evt->nick;
2883         std::wstring wname = utf8_to_wide(name);
2884         std::wstring wmessage = evt->evt_msg;
2885
2886         std::wstring answer = handleChat(name, wname, wmessage);
2887
2888         // If asked to send answer to sender
2889         if (!answer.empty()) {
2890                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2891         }
2892 }
2893
2894 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2895 {
2896         RemoteClient *client = getClientNoEx(peer_id,state_min);
2897         if(!client)
2898                 throw ClientNotFoundException("Client not found");
2899
2900         return client;
2901 }
2902 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2903 {
2904         return m_clients.getClientNoEx(peer_id, state_min);
2905 }
2906
2907 std::string Server::getPlayerName(u16 peer_id)
2908 {
2909         RemotePlayer *player = m_env->getPlayer(peer_id);
2910         if (player == NULL)
2911                 return "[id="+itos(peer_id)+"]";
2912         return player->getName();
2913 }
2914
2915 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2916 {
2917         RemotePlayer *player = m_env->getPlayer(peer_id);
2918         if (player == NULL)
2919                 return NULL;
2920         return player->getPlayerSAO();
2921 }
2922
2923 std::wstring Server::getStatusString()
2924 {
2925         std::wostringstream os(std::ios_base::binary);
2926         os<<L"# Server: ";
2927         // Version
2928         os<<L"version="<<narrow_to_wide(g_version_string);
2929         // Uptime
2930         os<<L", uptime="<<m_uptime.get();
2931         // Max lag estimate
2932         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2933         // Information about clients
2934         bool first = true;
2935         os<<L", clients={";
2936         std::vector<u16> clients = m_clients.getClientIDs();
2937         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2938                 // Get player
2939                 RemotePlayer *player = m_env->getPlayer(*i);
2940                 // Get name of player
2941                 std::wstring name = L"unknown";
2942                 if (player != NULL)
2943                         name = narrow_to_wide(player->getName());
2944                 // Add name to information string
2945                 if(!first)
2946                         os << L", ";
2947                 else
2948                         first = false;
2949                 os << name;
2950         }
2951         os << L"}";
2952         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2953                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2954         if(g_settings->get("motd") != "")
2955                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2956         return os.str();
2957 }
2958
2959 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2960 {
2961         std::set<std::string> privs;
2962         m_script->getAuth(name, NULL, &privs);
2963         return privs;
2964 }
2965
2966 bool Server::checkPriv(const std::string &name, const std::string &priv)
2967 {
2968         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2969         return (privs.count(priv) != 0);
2970 }
2971
2972 void Server::reportPrivsModified(const std::string &name)
2973 {
2974         if(name == "") {
2975                 std::vector<u16> clients = m_clients.getClientIDs();
2976                 for(std::vector<u16>::iterator i = clients.begin();
2977                                 i != clients.end(); ++i) {
2978                         RemotePlayer *player = m_env->getPlayer(*i);
2979                         reportPrivsModified(player->getName());
2980                 }
2981         } else {
2982                 RemotePlayer *player = m_env->getPlayer(name.c_str());
2983                 if (!player)
2984                         return;
2985                 SendPlayerPrivileges(player->peer_id);
2986                 PlayerSAO *sao = player->getPlayerSAO();
2987                 if(!sao)
2988                         return;
2989                 sao->updatePrivileges(
2990                                 getPlayerEffectivePrivs(name),
2991                                 isSingleplayer());
2992         }
2993 }
2994
2995 void Server::reportInventoryFormspecModified(const std::string &name)
2996 {
2997         RemotePlayer *player = m_env->getPlayer(name.c_str());
2998         if (!player)
2999                 return;
3000         SendPlayerInventoryFormspec(player->peer_id);
3001 }
3002
3003 void Server::setIpBanned(const std::string &ip, const std::string &name)
3004 {
3005         m_banmanager->add(ip, name);
3006 }
3007
3008 void Server::unsetIpBanned(const std::string &ip_or_name)
3009 {
3010         m_banmanager->remove(ip_or_name);
3011 }
3012
3013 std::string Server::getBanDescription(const std::string &ip_or_name)
3014 {
3015         return m_banmanager->getBanDescription(ip_or_name);
3016 }
3017
3018 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3019 {
3020         // m_env will be NULL if the server is initializing
3021         if (!m_env)
3022                 return;
3023
3024         if (m_admin_nick == name && !m_admin_nick.empty()) {
3025                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3026         }
3027
3028         RemotePlayer *player = m_env->getPlayer(name);
3029         if (!player) {
3030                 return;
3031         }
3032
3033         if (player->peer_id == PEER_ID_INEXISTENT)
3034                 return;
3035
3036         SendChatMessage(player->peer_id, msg);
3037 }
3038
3039 bool Server::showFormspec(const char *playername, const std::string &formspec,
3040         const std::string &formname)
3041 {
3042         // m_env will be NULL if the server is initializing
3043         if (!m_env)
3044                 return false;
3045
3046         RemotePlayer *player = m_env->getPlayer(playername);
3047         if (!player)
3048                 return false;
3049
3050         SendShowFormspecMessage(player->peer_id, formspec, formname);
3051         return true;
3052 }
3053
3054 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3055 {
3056         if (!player)
3057                 return -1;
3058
3059         u32 id = player->addHud(form);
3060
3061         SendHUDAdd(player->peer_id, id, form);
3062
3063         return id;
3064 }
3065
3066 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3067         if (!player)
3068                 return false;
3069
3070         HudElement* todel = player->removeHud(id);
3071
3072         if (!todel)
3073                 return false;
3074
3075         delete todel;
3076
3077         SendHUDRemove(player->peer_id, id);
3078         return true;
3079 }
3080
3081 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3082 {
3083         if (!player)
3084                 return false;
3085
3086         SendHUDChange(player->peer_id, id, stat, data);
3087         return true;
3088 }
3089
3090 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3091 {
3092         if (!player)
3093                 return false;
3094
3095         SendHUDSetFlags(player->peer_id, flags, mask);
3096         player->hud_flags &= ~mask;
3097         player->hud_flags |= flags;
3098
3099         PlayerSAO* playersao = player->getPlayerSAO();
3100
3101         if (playersao == NULL)
3102                 return false;
3103
3104         m_script->player_event(playersao, "hud_changed");
3105         return true;
3106 }
3107
3108 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3109 {
3110         if (!player)
3111                 return false;
3112
3113         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3114                 return false;
3115
3116         player->setHotbarItemcount(hotbar_itemcount);
3117         std::ostringstream os(std::ios::binary);
3118         writeS32(os, hotbar_itemcount);
3119         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3120         return true;
3121 }
3122
3123 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3124 {
3125         if (!player)
3126                 return;
3127
3128         player->setHotbarImage(name);
3129         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3130 }
3131
3132 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3133 {
3134         if (!player)
3135                 return "";
3136         return player->getHotbarImage();
3137 }
3138
3139 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3140 {
3141         if (!player)
3142                 return;
3143
3144         player->setHotbarSelectedImage(name);
3145         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3146 }
3147
3148 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3149                 v2s32 animation_frames[4], f32 frame_speed)
3150 {
3151         if (!player)
3152                 return false;
3153
3154         player->setLocalAnimations(animation_frames, frame_speed);
3155         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3156         return true;
3157 }
3158
3159 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3160 {
3161         if (!player)
3162                 return false;
3163
3164         player->eye_offset_first = first;
3165         player->eye_offset_third = third;
3166         SendEyeOffset(player->peer_id, first, third);
3167         return true;
3168 }
3169
3170 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3171         const std::string &type, const std::vector<std::string> &params)
3172 {
3173         if (!player)
3174                 return false;
3175
3176         player->setSky(bgcolor, type, params);
3177         SendSetSky(player->peer_id, bgcolor, type, params);
3178         return true;
3179 }
3180
3181 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3182         float ratio)
3183 {
3184         if (!player)
3185                 return false;
3186
3187         player->overrideDayNightRatio(do_override, ratio);
3188         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3189         return true;
3190 }
3191
3192 void Server::notifyPlayers(const std::wstring &msg)
3193 {
3194         SendChatMessage(PEER_ID_INEXISTENT,msg);
3195 }
3196
3197 void Server::spawnParticle(const std::string &playername, v3f pos,
3198         v3f velocity, v3f acceleration,
3199         float expirationtime, float size, bool
3200         collisiondetection, bool collision_removal,
3201         bool vertical, const std::string &texture,
3202         const struct TileAnimationParams &animation, u8 glow)
3203 {
3204         // m_env will be NULL if the server is initializing
3205         if (!m_env)
3206                 return;
3207
3208         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3209         if (playername != "") {
3210                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3211                 if (!player)
3212                         return;
3213                 peer_id = player->peer_id;
3214                 proto_ver = player->protocol_version;
3215         }
3216
3217         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3218                         expirationtime, size, collisiondetection,
3219                         collision_removal, vertical, texture, animation, glow);
3220 }
3221
3222 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3223         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3224         float minexptime, float maxexptime, float minsize, float maxsize,
3225         bool collisiondetection, bool collision_removal,
3226         ServerActiveObject *attached, bool vertical, const std::string &texture,
3227         const std::string &playername, const struct TileAnimationParams &animation,
3228         u8 glow)
3229 {
3230         // m_env will be NULL if the server is initializing
3231         if (!m_env)
3232                 return -1;
3233
3234         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3235         if (playername != "") {
3236                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3237                 if (!player)
3238                         return -1;
3239                 peer_id = player->peer_id;
3240                 proto_ver = player->protocol_version;
3241         }
3242
3243         u16 attached_id = attached ? attached->getId() : 0;
3244
3245         u32 id;
3246         if (attached_id == 0)
3247                 id = m_env->addParticleSpawner(spawntime);
3248         else
3249                 id = m_env->addParticleSpawner(spawntime, attached_id);
3250
3251         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3252                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3253                 minexptime, maxexptime, minsize, maxsize,
3254                 collisiondetection, collision_removal, attached_id, vertical,
3255                 texture, id, animation, glow);
3256
3257         return id;
3258 }
3259
3260 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3261 {
3262         // m_env will be NULL if the server is initializing
3263         if (!m_env)
3264                 throw ServerError("Can't delete particle spawners during initialisation!");
3265
3266         u16 peer_id = PEER_ID_INEXISTENT;
3267         if (playername != "") {
3268                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3269                 if (!player)
3270                         return;
3271                 peer_id = player->peer_id;
3272         }
3273
3274         m_env->deleteParticleSpawner(id);
3275         SendDeleteParticleSpawner(peer_id, id);
3276 }
3277
3278 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3279 {
3280         if(m_detached_inventories.count(name) > 0){
3281                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3282                 delete m_detached_inventories[name];
3283         } else {
3284                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3285         }
3286         Inventory *inv = new Inventory(m_itemdef);
3287         sanity_check(inv);
3288         m_detached_inventories[name] = inv;
3289         m_detached_inventories_player[name] = player;
3290         //TODO find a better way to do this
3291         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3292         return inv;
3293 }
3294
3295 // actions: time-reversed list
3296 // Return value: success/failure
3297 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3298                 std::list<std::string> *log)
3299 {
3300         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3301         ServerMap *map = (ServerMap*)(&m_env->getMap());
3302
3303         // Fail if no actions to handle
3304         if(actions.empty()){
3305                 log->push_back("Nothing to do.");
3306                 return false;
3307         }
3308
3309         int num_tried = 0;
3310         int num_failed = 0;
3311
3312         for(std::list<RollbackAction>::const_iterator
3313                         i = actions.begin();
3314                         i != actions.end(); ++i)
3315         {
3316                 const RollbackAction &action = *i;
3317                 num_tried++;
3318                 bool success = action.applyRevert(map, this, this);
3319                 if(!success){
3320                         num_failed++;
3321                         std::ostringstream os;
3322                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3323                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3324                         if(log)
3325                                 log->push_back(os.str());
3326                 }else{
3327                         std::ostringstream os;
3328                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3329                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3330                         if(log)
3331                                 log->push_back(os.str());
3332                 }
3333         }
3334
3335         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3336                         <<" failed"<<std::endl;
3337
3338         // Call it done if less than half failed
3339         return num_failed <= num_tried/2;
3340 }
3341
3342 // IGameDef interface
3343 // Under envlock
3344 IItemDefManager *Server::getItemDefManager()
3345 {
3346         return m_itemdef;
3347 }
3348
3349 INodeDefManager *Server::getNodeDefManager()
3350 {
3351         return m_nodedef;
3352 }
3353
3354 ICraftDefManager *Server::getCraftDefManager()
3355 {
3356         return m_craftdef;
3357 }
3358
3359 u16 Server::allocateUnknownNodeId(const std::string &name)
3360 {
3361         return m_nodedef->allocateDummy(name);
3362 }
3363
3364 MtEventManager *Server::getEventManager()
3365 {
3366         return m_event;
3367 }
3368
3369 IWritableItemDefManager *Server::getWritableItemDefManager()
3370 {
3371         return m_itemdef;
3372 }
3373
3374 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3375 {
3376         return m_nodedef;
3377 }
3378
3379 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3380 {
3381         return m_craftdef;
3382 }
3383
3384 const ModSpec *Server::getModSpec(const std::string &modname) const
3385 {
3386         std::vector<ModSpec>::const_iterator it;
3387         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3388                 const ModSpec &mod = *it;
3389                 if (mod.name == modname)
3390                         return &mod;
3391         }
3392         return NULL;
3393 }
3394
3395 void Server::getModNames(std::vector<std::string> &modlist)
3396 {
3397         std::vector<ModSpec>::iterator it;
3398         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3399                 modlist.push_back(it->name);
3400 }
3401
3402 std::string Server::getBuiltinLuaPath()
3403 {
3404         return porting::path_share + DIR_DELIM + "builtin";
3405 }
3406
3407 v3f Server::findSpawnPos()
3408 {
3409         ServerMap &map = m_env->getServerMap();
3410         v3f nodeposf;
3411         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3412                 return nodeposf * BS;
3413         }
3414
3415         bool is_good = false;
3416
3417         // Try to find a good place a few times
3418         for(s32 i = 0; i < 4000 && !is_good; i++) {
3419                 s32 range = 1 + i;
3420                 // We're going to try to throw the player to this position
3421                 v2s16 nodepos2d = v2s16(
3422                                 -range + (myrand() % (range * 2)),
3423                                 -range + (myrand() % (range * 2)));
3424
3425                 // Get spawn level at point
3426                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3427                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3428                 // the mapgen to signify an unsuitable spawn position
3429                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3430                         continue;
3431
3432                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3433
3434                 s32 air_count = 0;
3435                 for (s32 i = 0; i < 10; i++) {
3436                         v3s16 blockpos = getNodeBlockPos(nodepos);
3437                         map.emergeBlock(blockpos, true);
3438                         content_t c = map.getNodeNoEx(nodepos).getContent();
3439                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3440                                 air_count++;
3441                                 if (air_count >= 2) {
3442                                         nodeposf = intToFloat(nodepos, BS);
3443                                         // Don't spawn the player outside map boundaries
3444                                         if (objectpos_over_limit(nodeposf))
3445                                                 continue;
3446                                         is_good = true;
3447                                         break;
3448                                 }
3449                         }
3450                         nodepos.Y++;
3451                 }
3452         }
3453
3454         return nodeposf;
3455 }
3456
3457 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3458 {
3459         bool newplayer = false;
3460
3461         /*
3462                 Try to get an existing player
3463         */
3464         RemotePlayer *player = m_env->getPlayer(name);
3465
3466         // If player is already connected, cancel
3467         if (player != NULL && player->peer_id != 0) {
3468                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3469                 return NULL;
3470         }
3471
3472         /*
3473                 If player with the wanted peer_id already exists, cancel.
3474         */
3475         if (m_env->getPlayer(peer_id) != NULL) {
3476                 infostream<<"emergePlayer(): Player with wrong name but same"
3477                                 " peer_id already exists"<<std::endl;
3478                 return NULL;
3479         }
3480
3481         // Create a new player active object
3482         PlayerSAO *playersao = new PlayerSAO(m_env, peer_id, isSingleplayer());
3483         player = m_env->loadPlayer(name, playersao);
3484
3485         // Create player if it doesn't exist
3486         if (!player) {
3487                 newplayer = true;
3488                 player = new RemotePlayer(name, this->idef());
3489                 // Set player position
3490                 infostream<<"Server: Finding spawn place for player \""
3491                                 <<name<<"\""<<std::endl;
3492                 playersao->setBasePosition(findSpawnPos());
3493
3494                 // Make sure the player is saved
3495                 player->setModified(true);
3496
3497                 // Add player to environment
3498                 m_env->addPlayer(player);
3499         } else {
3500                 // If the player exists, ensure that they respawn inside legal bounds
3501                 // This fixes an assert crash when the player can't be added
3502                 // to the environment
3503                 if (objectpos_over_limit(playersao->getBasePosition())) {
3504                         actionstream << "Respawn position for player \""
3505                                 << name << "\" outside limits, resetting" << std::endl;
3506                         playersao->setBasePosition(findSpawnPos());
3507                 }
3508         }
3509
3510         playersao->initialize(player, getPlayerEffectivePrivs(player->getName()));
3511
3512         player->protocol_version = proto_version;
3513
3514         /* Clean up old HUD elements from previous sessions */
3515         player->clearHud();
3516
3517         /* Add object to environment */
3518         m_env->addActiveObject(playersao);
3519
3520         /* Run scripts */
3521         if (newplayer) {
3522                 m_script->on_newplayer(playersao);
3523         }
3524
3525         return playersao;
3526 }
3527
3528 void dedicated_server_loop(Server &server, bool &kill)
3529 {
3530         DSTACK(FUNCTION_NAME);
3531
3532         verbosestream<<"dedicated_server_loop()"<<std::endl;
3533
3534         IntervalLimiter m_profiler_interval;
3535
3536         static const float steplen = g_settings->getFloat("dedicated_server_step");
3537         static const float profiler_print_interval =
3538                         g_settings->getFloat("profiler_print_interval");
3539
3540         for(;;) {
3541                 // This is kind of a hack but can be done like this
3542                 // because server.step() is very light
3543                 {
3544                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3545                         sleep_ms((int)(steplen*1000.0));
3546                 }
3547                 server.step(steplen);
3548
3549                 if(server.getShutdownRequested() || kill)
3550                 {
3551                         infostream<<"Dedicated server quitting"<<std::endl;
3552 #if USE_CURL
3553                         if(g_settings->getBool("server_announce"))
3554                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3555 #endif
3556                         break;
3557                 }
3558
3559                 /*
3560                         Profiler
3561                 */
3562                 if (profiler_print_interval != 0) {
3563                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3564                         {
3565                                 infostream<<"Profiler:"<<std::endl;
3566                                 g_profiler->print(infostream);
3567                                 g_profiler->clear();
3568                         }
3569                 }
3570         }
3571 }