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