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