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