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