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