Player/LocalPlayer/RemotePlayer inheritance cleanup (part 1 on X)
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "threading/mutex_auto_lock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_game.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_abm.h"
51 #include "content_sao.h"
52 #include "mods.h"
53 #include "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                 RemotePlayer *player = dynamic_cast<RemotePlayer *>(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                 RemotePlayer *player =
1300                         dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
1301
1302                 if (!player)
1303                         return;
1304
1305                 PlayerSAO *playersao = player->getPlayerSAO();
1306                 if(!playersao)
1307                         return;
1308
1309                 SendInventory(playersao);
1310         }
1311                 break;
1312         case InventoryLocation::NODEMETA:
1313         {
1314                 v3s16 blockpos = getNodeBlockPos(loc.p);
1315
1316                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1317                 if(block)
1318                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1319
1320                 setBlockNotSent(blockpos);
1321         }
1322                 break;
1323         case InventoryLocation::DETACHED:
1324         {
1325                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1326         }
1327                 break;
1328         default:
1329                 sanity_check(false); // abort
1330                 break;
1331         }
1332 }
1333
1334 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1335 {
1336         std::vector<u16> clients = m_clients.getClientIDs();
1337         m_clients.lock();
1338         // Set the modified blocks unsent for all the clients
1339         for (std::vector<u16>::iterator i = clients.begin();
1340                  i != clients.end(); ++i) {
1341                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1342                                 client->SetBlocksNotSent(block);
1343         }
1344         m_clients.unlock();
1345 }
1346
1347 void Server::peerAdded(con::Peer *peer)
1348 {
1349         DSTACK(FUNCTION_NAME);
1350         verbosestream<<"Server::peerAdded(): peer->id="
1351                         <<peer->id<<std::endl;
1352
1353         con::PeerChange c;
1354         c.type = con::PEER_ADDED;
1355         c.peer_id = peer->id;
1356         c.timeout = false;
1357         m_peer_change_queue.push(c);
1358 }
1359
1360 void Server::deletingPeer(con::Peer *peer, bool timeout)
1361 {
1362         DSTACK(FUNCTION_NAME);
1363         verbosestream<<"Server::deletingPeer(): peer->id="
1364                         <<peer->id<<", timeout="<<timeout<<std::endl;
1365
1366         m_clients.event(peer->id, CSE_Disconnect);
1367         con::PeerChange c;
1368         c.type = con::PEER_REMOVED;
1369         c.peer_id = peer->id;
1370         c.timeout = timeout;
1371         m_peer_change_queue.push(c);
1372 }
1373
1374 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1375 {
1376         *retval = m_con.getPeerStat(peer_id,type);
1377         if (*retval == -1) return false;
1378         return true;
1379 }
1380
1381 bool Server::getClientInfo(
1382                 u16          peer_id,
1383                 ClientState* state,
1384                 u32*         uptime,
1385                 u8*          ser_vers,
1386                 u16*         prot_vers,
1387                 u8*          major,
1388                 u8*          minor,
1389                 u8*          patch,
1390                 std::string* vers_string
1391         )
1392 {
1393         *state = m_clients.getClientState(peer_id);
1394         m_clients.lock();
1395         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1396
1397         if (client == NULL) {
1398                 m_clients.unlock();
1399                 return false;
1400         }
1401
1402         *uptime = client->uptime();
1403         *ser_vers = client->serialization_version;
1404         *prot_vers = client->net_proto_version;
1405
1406         *major = client->getMajor();
1407         *minor = client->getMinor();
1408         *patch = client->getPatch();
1409         *vers_string = client->getPatch();
1410
1411         m_clients.unlock();
1412
1413         return true;
1414 }
1415
1416 void Server::handlePeerChanges()
1417 {
1418         while(m_peer_change_queue.size() > 0)
1419         {
1420                 con::PeerChange c = m_peer_change_queue.front();
1421                 m_peer_change_queue.pop();
1422
1423                 verbosestream<<"Server: Handling peer change: "
1424                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1425                                 <<std::endl;
1426
1427                 switch(c.type)
1428                 {
1429                 case con::PEER_ADDED:
1430                         m_clients.CreateClient(c.peer_id);
1431                         break;
1432
1433                 case con::PEER_REMOVED:
1434                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1435                         break;
1436
1437                 default:
1438                         FATAL_ERROR("Invalid peer change event received!");
1439                         break;
1440                 }
1441         }
1442 }
1443
1444 void Server::printToConsoleOnly(const std::string &text)
1445 {
1446         if (m_admin_chat) {
1447                 m_admin_chat->outgoing_queue.push_back(
1448                         new ChatEventChat("", utf8_to_wide(text)));
1449         } else {
1450                 std::cout << text << std::endl;
1451         }
1452 }
1453
1454 void Server::Send(NetworkPacket* pkt)
1455 {
1456         m_clients.send(pkt->getPeerId(),
1457                 clientCommandFactoryTable[pkt->getCommand()].channel,
1458                 pkt,
1459                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1460 }
1461
1462 void Server::SendMovement(u16 peer_id)
1463 {
1464         DSTACK(FUNCTION_NAME);
1465         std::ostringstream os(std::ios_base::binary);
1466
1467         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1468
1469         pkt << g_settings->getFloat("movement_acceleration_default");
1470         pkt << g_settings->getFloat("movement_acceleration_air");
1471         pkt << g_settings->getFloat("movement_acceleration_fast");
1472         pkt << g_settings->getFloat("movement_speed_walk");
1473         pkt << g_settings->getFloat("movement_speed_crouch");
1474         pkt << g_settings->getFloat("movement_speed_fast");
1475         pkt << g_settings->getFloat("movement_speed_climb");
1476         pkt << g_settings->getFloat("movement_speed_jump");
1477         pkt << g_settings->getFloat("movement_liquid_fluidity");
1478         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1479         pkt << g_settings->getFloat("movement_liquid_sink");
1480         pkt << g_settings->getFloat("movement_gravity");
1481
1482         Send(&pkt);
1483 }
1484
1485 void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
1486 {
1487         if (!g_settings->getBool("enable_damage"))
1488                 return;
1489
1490         u16 peer_id   = playersao->getPeerID();
1491         bool is_alive = playersao->getHP() > 0;
1492
1493         if (is_alive)
1494                 SendPlayerHP(peer_id);
1495         else
1496                 DiePlayer(peer_id);
1497 }
1498
1499 void Server::SendHP(u16 peer_id, u8 hp)
1500 {
1501         DSTACK(FUNCTION_NAME);
1502
1503         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1504         pkt << hp;
1505         Send(&pkt);
1506 }
1507
1508 void Server::SendBreath(u16 peer_id, u16 breath)
1509 {
1510         DSTACK(FUNCTION_NAME);
1511
1512         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1513         pkt << (u16) breath;
1514         Send(&pkt);
1515 }
1516
1517 void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
1518                 const std::string &custom_reason, bool reconnect)
1519 {
1520         assert(reason < SERVER_ACCESSDENIED_MAX);
1521
1522         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1523         pkt << (u8)reason;
1524         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1525                 pkt << custom_reason;
1526         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1527                         reason == SERVER_ACCESSDENIED_CRASH)
1528                 pkt << custom_reason << (u8)reconnect;
1529         Send(&pkt);
1530 }
1531
1532 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1533 {
1534         DSTACK(FUNCTION_NAME);
1535
1536         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1537         pkt << reason;
1538         Send(&pkt);
1539 }
1540
1541 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1542                 v3f camera_point_target)
1543 {
1544         DSTACK(FUNCTION_NAME);
1545
1546         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1547         pkt << set_camera_point_target << camera_point_target;
1548         Send(&pkt);
1549 }
1550
1551 void Server::SendItemDef(u16 peer_id,
1552                 IItemDefManager *itemdef, u16 protocol_version)
1553 {
1554         DSTACK(FUNCTION_NAME);
1555
1556         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1557
1558         /*
1559                 u16 command
1560                 u32 length of the next item
1561                 zlib-compressed serialized ItemDefManager
1562         */
1563         std::ostringstream tmp_os(std::ios::binary);
1564         itemdef->serialize(tmp_os, protocol_version);
1565         std::ostringstream tmp_os2(std::ios::binary);
1566         compressZlib(tmp_os.str(), tmp_os2);
1567         pkt.putLongString(tmp_os2.str());
1568
1569         // Make data buffer
1570         verbosestream << "Server: Sending item definitions to id(" << peer_id
1571                         << "): size=" << pkt.getSize() << std::endl;
1572
1573         Send(&pkt);
1574 }
1575
1576 void Server::SendNodeDef(u16 peer_id,
1577                 INodeDefManager *nodedef, u16 protocol_version)
1578 {
1579         DSTACK(FUNCTION_NAME);
1580
1581         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1582
1583         /*
1584                 u16 command
1585                 u32 length of the next item
1586                 zlib-compressed serialized NodeDefManager
1587         */
1588         std::ostringstream tmp_os(std::ios::binary);
1589         nodedef->serialize(tmp_os, protocol_version);
1590         std::ostringstream tmp_os2(std::ios::binary);
1591         compressZlib(tmp_os.str(), tmp_os2);
1592
1593         pkt.putLongString(tmp_os2.str());
1594
1595         // Make data buffer
1596         verbosestream << "Server: Sending node definitions to id(" << peer_id
1597                         << "): size=" << pkt.getSize() << std::endl;
1598
1599         Send(&pkt);
1600 }
1601
1602 /*
1603         Non-static send methods
1604 */
1605
1606 void Server::SendInventory(PlayerSAO* playerSAO)
1607 {
1608         DSTACK(FUNCTION_NAME);
1609
1610         UpdateCrafting(playerSAO->getPlayer());
1611
1612         /*
1613                 Serialize it
1614         */
1615
1616         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1617
1618         std::ostringstream os;
1619         playerSAO->getInventory()->serialize(os);
1620
1621         std::string s = os.str();
1622
1623         pkt.putRawString(s.c_str(), s.size());
1624         Send(&pkt);
1625 }
1626
1627 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
1628 {
1629         DSTACK(FUNCTION_NAME);
1630
1631         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1632         pkt << message;
1633
1634         if (peer_id != PEER_ID_INEXISTENT) {
1635                 Send(&pkt);
1636         }
1637         else {
1638                 m_clients.sendToAll(0, &pkt, true);
1639         }
1640 }
1641
1642 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1643                                      const std::string &formname)
1644 {
1645         DSTACK(FUNCTION_NAME);
1646
1647         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1648
1649         pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1650         pkt << formname;
1651
1652         Send(&pkt);
1653 }
1654
1655 // Spawns a particle on peer with peer_id
1656 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
1657                                 float expirationtime, float size, bool collisiondetection,
1658                                 bool collision_removal,
1659                                 bool vertical, const std::string &texture)
1660 {
1661         DSTACK(FUNCTION_NAME);
1662
1663         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1664
1665         pkt << pos << velocity << acceleration << expirationtime
1666                         << size << collisiondetection;
1667         pkt.putLongString(texture);
1668         pkt << vertical;
1669         pkt << collision_removal;
1670
1671         if (peer_id != PEER_ID_INEXISTENT) {
1672                 Send(&pkt);
1673         }
1674         else {
1675                 m_clients.sendToAll(0, &pkt, true);
1676         }
1677 }
1678
1679 // Adds a ParticleSpawner on peer with peer_id
1680 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
1681         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1682         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1683         bool vertical, const std::string &texture, u32 id)
1684 {
1685         DSTACK(FUNCTION_NAME);
1686
1687         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1688
1689         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1690                         << minacc << maxacc << minexptime << maxexptime << minsize
1691                         << maxsize << collisiondetection;
1692
1693         pkt.putLongString(texture);
1694
1695         pkt << id << vertical;
1696         pkt << collision_removal;
1697
1698         if (peer_id != PEER_ID_INEXISTENT) {
1699                 Send(&pkt);
1700         }
1701         else {
1702                 m_clients.sendToAll(0, &pkt, true);
1703         }
1704 }
1705
1706 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1707 {
1708         DSTACK(FUNCTION_NAME);
1709
1710         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1711
1712         // Ugly error in this packet
1713         pkt << (u16) id;
1714
1715         if (peer_id != PEER_ID_INEXISTENT) {
1716                 Send(&pkt);
1717         }
1718         else {
1719                 m_clients.sendToAll(0, &pkt, true);
1720         }
1721
1722 }
1723
1724 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1725 {
1726         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1727
1728         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1729                         << form->text << form->number << form->item << form->dir
1730                         << form->align << form->offset << form->world_pos << form->size;
1731
1732         Send(&pkt);
1733 }
1734
1735 void Server::SendHUDRemove(u16 peer_id, u32 id)
1736 {
1737         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1738         pkt << id;
1739         Send(&pkt);
1740 }
1741
1742 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1743 {
1744         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1745         pkt << id << (u8) stat;
1746
1747         switch (stat) {
1748                 case HUD_STAT_POS:
1749                 case HUD_STAT_SCALE:
1750                 case HUD_STAT_ALIGN:
1751                 case HUD_STAT_OFFSET:
1752                         pkt << *(v2f *) value;
1753                         break;
1754                 case HUD_STAT_NAME:
1755                 case HUD_STAT_TEXT:
1756                         pkt << *(std::string *) value;
1757                         break;
1758                 case HUD_STAT_WORLD_POS:
1759                         pkt << *(v3f *) value;
1760                         break;
1761                 case HUD_STAT_SIZE:
1762                         pkt << *(v2s32 *) value;
1763                         break;
1764                 case HUD_STAT_NUMBER:
1765                 case HUD_STAT_ITEM:
1766                 case HUD_STAT_DIR:
1767                 default:
1768                         pkt << *(u32 *) value;
1769                         break;
1770         }
1771
1772         Send(&pkt);
1773 }
1774
1775 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1776 {
1777         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1778
1779         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1780
1781         pkt << flags << mask;
1782
1783         Send(&pkt);
1784 }
1785
1786 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1787 {
1788         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1789         pkt << param << value;
1790         Send(&pkt);
1791 }
1792
1793 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1794                 const std::string &type, const std::vector<std::string> &params)
1795 {
1796         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1797         pkt << bgcolor << type << (u16) params.size();
1798
1799         for(size_t i=0; i<params.size(); i++)
1800                 pkt << params[i];
1801
1802         Send(&pkt);
1803 }
1804
1805 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1806                 float ratio)
1807 {
1808         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1809                         1 + 2, peer_id);
1810
1811         pkt << do_override << (u16) (ratio * 65535);
1812
1813         Send(&pkt);
1814 }
1815
1816 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1817 {
1818         DSTACK(FUNCTION_NAME);
1819
1820         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1821         pkt << time << time_speed;
1822
1823         if (peer_id == PEER_ID_INEXISTENT) {
1824                 m_clients.sendToAll(0, &pkt, true);
1825         }
1826         else {
1827                 Send(&pkt);
1828         }
1829 }
1830
1831 void Server::SendPlayerHP(u16 peer_id)
1832 {
1833         DSTACK(FUNCTION_NAME);
1834         PlayerSAO *playersao = getPlayerSAO(peer_id);
1835         // In some rare case if the player is disconnected
1836         // while Lua call l_punch, for example, this can be NULL
1837         if (!playersao)
1838                 return;
1839
1840         SendHP(peer_id, playersao->getHP());
1841         m_script->player_event(playersao,"health_changed");
1842
1843         // Send to other clients
1844         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1845         ActiveObjectMessage aom(playersao->getId(), true, str);
1846         playersao->m_messages_out.push(aom);
1847 }
1848
1849 void Server::SendPlayerBreath(u16 peer_id)
1850 {
1851         DSTACK(FUNCTION_NAME);
1852         PlayerSAO *playersao = getPlayerSAO(peer_id);
1853         assert(playersao);
1854
1855         m_script->player_event(playersao, "breath_changed");
1856         SendBreath(peer_id, playersao->getBreath());
1857 }
1858
1859 void Server::SendMovePlayer(u16 peer_id)
1860 {
1861         DSTACK(FUNCTION_NAME);
1862         Player *player = m_env->getPlayer(peer_id);
1863         assert(player);
1864
1865         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1866         pkt << player->getPosition() << player->getPitch() << player->getYaw();
1867
1868         {
1869                 v3f pos = player->getPosition();
1870                 f32 pitch = player->getPitch();
1871                 f32 yaw = player->getYaw();
1872                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1873                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1874                                 << " pitch=" << pitch
1875                                 << " yaw=" << yaw
1876                                 << std::endl;
1877         }
1878
1879         Send(&pkt);
1880 }
1881
1882 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1883 {
1884         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1885                 peer_id);
1886
1887         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1888                         << animation_frames[3] << animation_speed;
1889
1890         Send(&pkt);
1891 }
1892
1893 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1894 {
1895         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1896         pkt << first << third;
1897         Send(&pkt);
1898 }
1899 void Server::SendPlayerPrivileges(u16 peer_id)
1900 {
1901         Player *player = m_env->getPlayer(peer_id);
1902         assert(player);
1903         if(player->peer_id == PEER_ID_INEXISTENT)
1904                 return;
1905
1906         std::set<std::string> privs;
1907         m_script->getAuth(player->getName(), NULL, &privs);
1908
1909         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1910         pkt << (u16) privs.size();
1911
1912         for(std::set<std::string>::const_iterator i = privs.begin();
1913                         i != privs.end(); ++i) {
1914                 pkt << (*i);
1915         }
1916
1917         Send(&pkt);
1918 }
1919
1920 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1921 {
1922         Player *player = m_env->getPlayer(peer_id);
1923         assert(player);
1924         if(player->peer_id == PEER_ID_INEXISTENT)
1925                 return;
1926
1927         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1928         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
1929         Send(&pkt);
1930 }
1931
1932 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
1933 {
1934         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
1935         pkt.putRawString(datas.c_str(), datas.size());
1936         Send(&pkt);
1937         return pkt.getSize();
1938 }
1939
1940 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
1941 {
1942         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
1943                         datas.size(), peer_id);
1944
1945         pkt.putRawString(datas.c_str(), datas.size());
1946
1947         m_clients.send(pkt.getPeerId(),
1948                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
1949                         &pkt, reliable);
1950
1951 }
1952
1953 s32 Server::playSound(const SimpleSoundSpec &spec,
1954                 const ServerSoundParams &params)
1955 {
1956         // Find out initial position of sound
1957         bool pos_exists = false;
1958         v3f pos = params.getPos(m_env, &pos_exists);
1959         // If position is not found while it should be, cancel sound
1960         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
1961                 return -1;
1962
1963         // Filter destination clients
1964         std::vector<u16> dst_clients;
1965         if(params.to_player != "")
1966         {
1967                 Player *player = m_env->getPlayer(params.to_player.c_str());
1968                 if(!player){
1969                         infostream<<"Server::playSound: Player \""<<params.to_player
1970                                         <<"\" not found"<<std::endl;
1971                         return -1;
1972                 }
1973                 if(player->peer_id == PEER_ID_INEXISTENT){
1974                         infostream<<"Server::playSound: Player \""<<params.to_player
1975                                         <<"\" not connected"<<std::endl;
1976                         return -1;
1977                 }
1978                 dst_clients.push_back(player->peer_id);
1979         }
1980         else {
1981                 std::vector<u16> clients = m_clients.getClientIDs();
1982
1983                 for(std::vector<u16>::iterator
1984                                 i = clients.begin(); i != clients.end(); ++i) {
1985                         Player *player = m_env->getPlayer(*i);
1986                         if(!player)
1987                                 continue;
1988
1989                         if(pos_exists) {
1990                                 if(player->getPosition().getDistanceFrom(pos) >
1991                                                 params.max_hear_distance)
1992                                         continue;
1993                         }
1994                         dst_clients.push_back(*i);
1995                 }
1996         }
1997
1998         if(dst_clients.empty())
1999                 return -1;
2000
2001         // Create the sound
2002         s32 id = m_next_sound_id++;
2003         // The sound will exist as a reference in m_playing_sounds
2004         m_playing_sounds[id] = ServerPlayingSound();
2005         ServerPlayingSound &psound = m_playing_sounds[id];
2006         psound.params = params;
2007
2008         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2009         pkt << id << spec.name << (float) (spec.gain * params.gain)
2010                         << (u8) params.type << pos << params.object << params.loop;
2011
2012         for(std::vector<u16>::iterator i = dst_clients.begin();
2013                         i != dst_clients.end(); ++i) {
2014                 psound.clients.insert(*i);
2015                 m_clients.send(*i, 0, &pkt, true);
2016         }
2017         return id;
2018 }
2019 void Server::stopSound(s32 handle)
2020 {
2021         // Get sound reference
2022         UNORDERED_MAP<s32, ServerPlayingSound>::iterator i = m_playing_sounds.find(handle);
2023         if (i == m_playing_sounds.end())
2024                 return;
2025         ServerPlayingSound &psound = i->second;
2026
2027         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2028         pkt << handle;
2029
2030         for (UNORDERED_SET<u16>::iterator i = psound.clients.begin();
2031                         i != psound.clients.end(); ++i) {
2032                 // Send as reliable
2033                 m_clients.send(*i, 0, &pkt, true);
2034         }
2035         // Remove sound reference
2036         m_playing_sounds.erase(i);
2037 }
2038
2039 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2040         std::vector<u16> *far_players, float far_d_nodes)
2041 {
2042         float maxd = far_d_nodes*BS;
2043         v3f p_f = intToFloat(p, BS);
2044
2045         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2046         pkt << p;
2047
2048         std::vector<u16> clients = m_clients.getClientIDs();
2049         for(std::vector<u16>::iterator i = clients.begin();
2050                 i != clients.end(); ++i) {
2051                 if (far_players) {
2052                         // Get player
2053                         if(Player *player = m_env->getPlayer(*i)) {
2054                                 // If player is far away, only set modified blocks not sent
2055                                 v3f player_pos = player->getPosition();
2056                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2057                                         far_players->push_back(*i);
2058                                         continue;
2059                                 }
2060                         }
2061                 }
2062
2063                 // Send as reliable
2064                 m_clients.send(*i, 0, &pkt, true);
2065         }
2066 }
2067
2068 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2069                 std::vector<u16> *far_players, float far_d_nodes,
2070                 bool remove_metadata)
2071 {
2072         float maxd = far_d_nodes*BS;
2073         v3f p_f = intToFloat(p, BS);
2074
2075         std::vector<u16> clients = m_clients.getClientIDs();
2076         for(std::vector<u16>::iterator i = clients.begin();
2077                         i != clients.end(); ++i) {
2078
2079                 if(far_players) {
2080                         // Get player
2081                         if(Player *player = m_env->getPlayer(*i)) {
2082                                 // If player is far away, only set modified blocks not sent
2083                                 v3f player_pos = player->getPosition();
2084                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2085                                         far_players->push_back(*i);
2086                                         continue;
2087                                 }
2088                         }
2089                 }
2090
2091                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2092                 m_clients.lock();
2093                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2094                 if (client != 0) {
2095                         pkt << p << n.param0 << n.param1 << n.param2
2096                                         << (u8) (remove_metadata ? 0 : 1);
2097
2098                         if (!remove_metadata) {
2099                                 if (client->net_proto_version <= 21) {
2100                                         // Old clients always clear metadata; fix it
2101                                         // by sending the full block again.
2102                                         client->SetBlockNotSent(getNodeBlockPos(p));
2103                                 }
2104                         }
2105                 }
2106                 m_clients.unlock();
2107
2108                 // Send as reliable
2109                 if (pkt.getSize() > 0)
2110                         m_clients.send(*i, 0, &pkt, true);
2111         }
2112 }
2113
2114 void Server::setBlockNotSent(v3s16 p)
2115 {
2116         std::vector<u16> clients = m_clients.getClientIDs();
2117         m_clients.lock();
2118         for(std::vector<u16>::iterator i = clients.begin();
2119                 i != clients.end(); ++i) {
2120                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2121                 client->SetBlockNotSent(p);
2122         }
2123         m_clients.unlock();
2124 }
2125
2126 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2127 {
2128         DSTACK(FUNCTION_NAME);
2129
2130         v3s16 p = block->getPos();
2131
2132         /*
2133                 Create a packet with the block in the right format
2134         */
2135
2136         std::ostringstream os(std::ios_base::binary);
2137         block->serialize(os, ver, false);
2138         block->serializeNetworkSpecific(os, net_proto_version);
2139         std::string s = os.str();
2140
2141         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2142
2143         pkt << p;
2144         pkt.putRawString(s.c_str(), s.size());
2145         Send(&pkt);
2146 }
2147
2148 void Server::SendBlocks(float dtime)
2149 {
2150         DSTACK(FUNCTION_NAME);
2151
2152         MutexAutoLock envlock(m_env_mutex);
2153         //TODO check if one big lock could be faster then multiple small ones
2154
2155         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2156
2157         std::vector<PrioritySortedBlockTransfer> queue;
2158
2159         s32 total_sending = 0;
2160
2161         {
2162                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2163
2164                 std::vector<u16> clients = m_clients.getClientIDs();
2165
2166                 m_clients.lock();
2167                 for(std::vector<u16>::iterator i = clients.begin();
2168                         i != clients.end(); ++i) {
2169                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2170
2171                         if (client == NULL)
2172                                 continue;
2173
2174                         total_sending += client->SendingCount();
2175                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2176                 }
2177                 m_clients.unlock();
2178         }
2179
2180         // Sort.
2181         // Lowest priority number comes first.
2182         // Lowest is most important.
2183         std::sort(queue.begin(), queue.end());
2184
2185         m_clients.lock();
2186         for(u32 i=0; i<queue.size(); i++)
2187         {
2188                 //TODO: Calculate limit dynamically
2189                 if(total_sending >= g_settings->getS32
2190                                 ("max_simultaneous_block_sends_server_total"))
2191                         break;
2192
2193                 PrioritySortedBlockTransfer q = queue[i];
2194
2195                 MapBlock *block = NULL;
2196                 try
2197                 {
2198                         block = m_env->getMap().getBlockNoCreate(q.pos);
2199                 }
2200                 catch(InvalidPositionException &e)
2201                 {
2202                         continue;
2203                 }
2204
2205                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2206
2207                 if(!client)
2208                         continue;
2209
2210                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2211
2212                 client->SentBlock(q.pos);
2213                 total_sending++;
2214         }
2215         m_clients.unlock();
2216 }
2217
2218 void Server::fillMediaCache()
2219 {
2220         DSTACK(FUNCTION_NAME);
2221
2222         infostream<<"Server: Calculating media file checksums"<<std::endl;
2223
2224         // Collect all media file paths
2225         std::vector<std::string> paths;
2226         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2227                         i != m_mods.end(); ++i) {
2228                 const ModSpec &mod = *i;
2229                 paths.push_back(mod.path + DIR_DELIM + "textures");
2230                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2231                 paths.push_back(mod.path + DIR_DELIM + "media");
2232                 paths.push_back(mod.path + DIR_DELIM + "models");
2233         }
2234         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2235
2236         // Collect media file information from paths into cache
2237         for(std::vector<std::string>::iterator i = paths.begin();
2238                         i != paths.end(); ++i) {
2239                 std::string mediapath = *i;
2240                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2241                 for (u32 j = 0; j < dirlist.size(); j++) {
2242                         if (dirlist[j].dir) // Ignode dirs
2243                                 continue;
2244                         std::string filename = dirlist[j].name;
2245                         // If name contains illegal characters, ignore the file
2246                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2247                                 infostream<<"Server: ignoring illegal file name: \""
2248                                                 << filename << "\"" << std::endl;
2249                                 continue;
2250                         }
2251                         // If name is not in a supported format, ignore it
2252                         const char *supported_ext[] = {
2253                                 ".png", ".jpg", ".bmp", ".tga",
2254                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2255                                 ".ogg",
2256                                 ".x", ".b3d", ".md2", ".obj",
2257                                 NULL
2258                         };
2259                         if (removeStringEnd(filename, supported_ext) == ""){
2260                                 infostream << "Server: ignoring unsupported file extension: \""
2261                                                 << filename << "\"" << std::endl;
2262                                 continue;
2263                         }
2264                         // Ok, attempt to load the file and add to cache
2265                         std::string filepath = mediapath + DIR_DELIM + filename;
2266                         // Read data
2267                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2268                         if (!fis.good()) {
2269                                 errorstream << "Server::fillMediaCache(): Could not open \""
2270                                                 << filename << "\" for reading" << std::endl;
2271                                 continue;
2272                         }
2273                         std::ostringstream tmp_os(std::ios_base::binary);
2274                         bool bad = false;
2275                         for(;;) {
2276                                 char buf[1024];
2277                                 fis.read(buf, 1024);
2278                                 std::streamsize len = fis.gcount();
2279                                 tmp_os.write(buf, len);
2280                                 if (fis.eof())
2281                                         break;
2282                                 if (!fis.good()) {
2283                                         bad = true;
2284                                         break;
2285                                 }
2286                         }
2287                         if(bad) {
2288                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2289                                                 << filename << "\"" << std::endl;
2290                                 continue;
2291                         }
2292                         if(tmp_os.str().length() == 0) {
2293                                 errorstream << "Server::fillMediaCache(): Empty file \""
2294                                                 << filepath << "\"" << std::endl;
2295                                 continue;
2296                         }
2297
2298                         SHA1 sha1;
2299                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2300
2301                         unsigned char *digest = sha1.getDigest();
2302                         std::string sha1_base64 = base64_encode(digest, 20);
2303                         std::string sha1_hex = hex_encode((char*)digest, 20);
2304                         free(digest);
2305
2306                         // Put in list
2307                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2308                         verbosestream << "Server: " << sha1_hex << " is " << filename
2309                                         << std::endl;
2310                 }
2311         }
2312 }
2313
2314 void Server::sendMediaAnnouncement(u16 peer_id)
2315 {
2316         DSTACK(FUNCTION_NAME);
2317
2318         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2319                 << std::endl;
2320
2321         // Make packet
2322         std::ostringstream os(std::ios_base::binary);
2323
2324         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2325         pkt << (u16) m_media.size();
2326
2327         for (UNORDERED_MAP<std::string, MediaInfo>::iterator i = m_media.begin();
2328                         i != m_media.end(); ++i) {
2329                 pkt << i->first << i->second.sha1_digest;
2330         }
2331
2332         pkt << g_settings->get("remote_media");
2333         Send(&pkt);
2334 }
2335
2336 struct SendableMedia
2337 {
2338         std::string name;
2339         std::string path;
2340         std::string data;
2341
2342         SendableMedia(const std::string &name_="", const std::string &path_="",
2343                       const std::string &data_=""):
2344                 name(name_),
2345                 path(path_),
2346                 data(data_)
2347         {}
2348 };
2349
2350 void Server::sendRequestedMedia(u16 peer_id,
2351                 const std::vector<std::string> &tosend)
2352 {
2353         DSTACK(FUNCTION_NAME);
2354
2355         verbosestream<<"Server::sendRequestedMedia(): "
2356                         <<"Sending files to client"<<std::endl;
2357
2358         /* Read files */
2359
2360         // Put 5kB in one bunch (this is not accurate)
2361         u32 bytes_per_bunch = 5000;
2362
2363         std::vector< std::vector<SendableMedia> > file_bunches;
2364         file_bunches.push_back(std::vector<SendableMedia>());
2365
2366         u32 file_size_bunch_total = 0;
2367
2368         for(std::vector<std::string>::const_iterator i = tosend.begin();
2369                         i != tosend.end(); ++i) {
2370                 const std::string &name = *i;
2371
2372                 if (m_media.find(name) == m_media.end()) {
2373                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2374                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2375                         continue;
2376                 }
2377
2378                 //TODO get path + name
2379                 std::string tpath = m_media[name].path;
2380
2381                 // Read data
2382                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2383                 if(fis.good() == false){
2384                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2385                                         <<tpath<<"\" for reading"<<std::endl;
2386                         continue;
2387                 }
2388                 std::ostringstream tmp_os(std::ios_base::binary);
2389                 bool bad = false;
2390                 for(;;) {
2391                         char buf[1024];
2392                         fis.read(buf, 1024);
2393                         std::streamsize len = fis.gcount();
2394                         tmp_os.write(buf, len);
2395                         file_size_bunch_total += len;
2396                         if(fis.eof())
2397                                 break;
2398                         if(!fis.good()) {
2399                                 bad = true;
2400                                 break;
2401                         }
2402                 }
2403                 if(bad) {
2404                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2405                                         <<name<<"\""<<std::endl;
2406                         continue;
2407                 }
2408                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2409                                 <<tname<<"\""<<std::endl;*/
2410                 // Put in list
2411                 file_bunches[file_bunches.size()-1].push_back(
2412                                 SendableMedia(name, tpath, tmp_os.str()));
2413
2414                 // Start next bunch if got enough data
2415                 if(file_size_bunch_total >= bytes_per_bunch) {
2416                         file_bunches.push_back(std::vector<SendableMedia>());
2417                         file_size_bunch_total = 0;
2418                 }
2419
2420         }
2421
2422         /* Create and send packets */
2423
2424         u16 num_bunches = file_bunches.size();
2425         for(u16 i = 0; i < num_bunches; i++) {
2426                 /*
2427                         u16 command
2428                         u16 total number of texture bunches
2429                         u16 index of this bunch
2430                         u32 number of files in this bunch
2431                         for each file {
2432                                 u16 length of name
2433                                 string name
2434                                 u32 length of data
2435                                 data
2436                         }
2437                 */
2438
2439                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2440                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2441
2442                 for(std::vector<SendableMedia>::iterator
2443                                 j = file_bunches[i].begin();
2444                                 j != file_bunches[i].end(); ++j) {
2445                         pkt << j->name;
2446                         pkt.putLongString(j->data);
2447                 }
2448
2449                 verbosestream << "Server::sendRequestedMedia(): bunch "
2450                                 << i << "/" << num_bunches
2451                                 << " files=" << file_bunches[i].size()
2452                                 << " size="  << pkt.getSize() << std::endl;
2453                 Send(&pkt);
2454         }
2455 }
2456
2457 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2458 {
2459         if(m_detached_inventories.count(name) == 0) {
2460                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2461                 return;
2462         }
2463         Inventory *inv = m_detached_inventories[name];
2464         std::ostringstream os(std::ios_base::binary);
2465
2466         os << serializeString(name);
2467         inv->serialize(os);
2468
2469         // Make data buffer
2470         std::string s = os.str();
2471
2472         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2473         pkt.putRawString(s.c_str(), s.size());
2474
2475         if (peer_id != PEER_ID_INEXISTENT) {
2476                 Send(&pkt);
2477         }
2478         else {
2479                 m_clients.sendToAll(0, &pkt, true);
2480         }
2481 }
2482
2483 void Server::sendDetachedInventories(u16 peer_id)
2484 {
2485         DSTACK(FUNCTION_NAME);
2486
2487         for(std::map<std::string, Inventory*>::iterator
2488                         i = m_detached_inventories.begin();
2489                         i != m_detached_inventories.end(); ++i) {
2490                 const std::string &name = i->first;
2491                 //Inventory *inv = i->second;
2492                 sendDetachedInventory(name, peer_id);
2493         }
2494 }
2495
2496 /*
2497         Something random
2498 */
2499
2500 void Server::DiePlayer(u16 peer_id)
2501 {
2502         DSTACK(FUNCTION_NAME);
2503         PlayerSAO *playersao = getPlayerSAO(peer_id);
2504         // In some rare cases this can be NULL -- if the player is disconnected
2505         // when a Lua function modifies l_punch, for example
2506         if (!playersao)
2507                 return;
2508
2509         infostream << "Server::DiePlayer(): Player "
2510                         << playersao->getPlayer()->getName()
2511                         << " dies" << std::endl;
2512
2513         playersao->setHP(0);
2514
2515         // Trigger scripted stuff
2516         m_script->on_dieplayer(playersao);
2517
2518         SendPlayerHP(peer_id);
2519         SendDeathscreen(peer_id, false, v3f(0,0,0));
2520 }
2521
2522 void Server::RespawnPlayer(u16 peer_id)
2523 {
2524         DSTACK(FUNCTION_NAME);
2525
2526         PlayerSAO *playersao = getPlayerSAO(peer_id);
2527         assert(playersao);
2528
2529         infostream << "Server::RespawnPlayer(): Player "
2530                         << playersao->getPlayer()->getName()
2531                         << " respawns" << std::endl;
2532
2533         playersao->setHP(PLAYER_MAX_HP);
2534         playersao->setBreath(PLAYER_MAX_BREATH);
2535
2536         SendPlayerHP(peer_id);
2537         SendPlayerBreath(peer_id);
2538
2539         bool repositioned = m_script->on_respawnplayer(playersao);
2540         if(!repositioned){
2541                 v3f pos = findSpawnPos();
2542                 // setPos will send the new position to client
2543                 playersao->setPos(pos);
2544         }
2545 }
2546
2547
2548 void Server::DenySudoAccess(u16 peer_id)
2549 {
2550         DSTACK(FUNCTION_NAME);
2551
2552         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2553         Send(&pkt);
2554 }
2555
2556
2557 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2558                 const std::string &str_reason, bool reconnect)
2559 {
2560         if (proto_ver >= 25) {
2561                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2562         } else {
2563                 std::wstring wreason = utf8_to_wide(
2564                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2565                         accessDeniedStrings[(u8)reason]);
2566                 SendAccessDenied_Legacy(peer_id, wreason);
2567         }
2568
2569         m_clients.event(peer_id, CSE_SetDenied);
2570         m_con.DisconnectPeer(peer_id);
2571 }
2572
2573
2574 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2575 {
2576         DSTACK(FUNCTION_NAME);
2577
2578         SendAccessDenied(peer_id, reason, custom_reason);
2579         m_clients.event(peer_id, CSE_SetDenied);
2580         m_con.DisconnectPeer(peer_id);
2581 }
2582
2583 // 13/03/15: remove this function when protocol version 25 will become
2584 // the minimum version for MT users, maybe in 1 year
2585 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2586 {
2587         DSTACK(FUNCTION_NAME);
2588
2589         SendAccessDenied_Legacy(peer_id, reason);
2590         m_clients.event(peer_id, CSE_SetDenied);
2591         m_con.DisconnectPeer(peer_id);
2592 }
2593
2594 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2595 {
2596         DSTACK(FUNCTION_NAME);
2597
2598         if (!forSudoMode) {
2599                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2600
2601                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2602
2603                 // Right now, the auth mechs don't change between login and sudo mode.
2604                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2605                 client->allowed_sudo_mechs = sudo_auth_mechs;
2606
2607                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2608                                 << g_settings->getFloat("dedicated_server_step")
2609                                 << sudo_auth_mechs;
2610
2611                 Send(&resp_pkt);
2612                 m_clients.event(peer_id, CSE_AuthAccept);
2613         } else {
2614                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2615
2616                 // We only support SRP right now
2617                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2618
2619                 resp_pkt << sudo_auth_mechs;
2620                 Send(&resp_pkt);
2621                 m_clients.event(peer_id, CSE_SudoSuccess);
2622         }
2623 }
2624
2625 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2626 {
2627         DSTACK(FUNCTION_NAME);
2628         std::wstring message;
2629         {
2630                 /*
2631                         Clear references to playing sounds
2632                 */
2633                 for (UNORDERED_MAP<s32, ServerPlayingSound>::iterator
2634                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2635                         ServerPlayingSound &psound = i->second;
2636                         psound.clients.erase(peer_id);
2637                         if (psound.clients.empty())
2638                                 m_playing_sounds.erase(i++);
2639                         else
2640                                 ++i;
2641                 }
2642
2643                 RemotePlayer *player = dynamic_cast<RemotePlayer *>(m_env->getPlayer(peer_id));
2644
2645                 /* Run scripts and remove from environment */
2646                 if(player != NULL) {
2647                         PlayerSAO *playersao = player->getPlayerSAO();
2648                         assert(playersao);
2649
2650                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2651
2652                         playersao->disconnected();
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(RemotePlayer* 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(),
2705                         (&player->inventory)->getList("craft"), loc);
2706
2707         // Put the new preview in
2708         InventoryList *plist = player->inventory.getList("craftpreview");
2709         sanity_check(plist);
2710         sanity_check(plist->getSize() >= 1);
2711         plist->changeItem(0, preview);
2712 }
2713
2714 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2715 {
2716         if (evt->type == CET_NICK_ADD) {
2717                 // The terminal informed us of its nick choice
2718                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2719                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2720                         errorstream << "You haven't set up an account." << std::endl
2721                                 << "Please log in using the client as '"
2722                                 << m_admin_nick << "' with a secure password." << std::endl
2723                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2724                                 << "and everybody can claim the user account instead of you," << std::endl
2725                                 << "giving them full control over this server." << std::endl;
2726                 }
2727         } else {
2728                 assert(evt->type == CET_CHAT);
2729                 handleAdminChat((ChatEventChat *)evt);
2730         }
2731 }
2732
2733 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2734         const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
2735 {
2736         // If something goes wrong, this player is to blame
2737         RollbackScopeActor rollback_scope(m_rollback,
2738                 std::string("player:") + name);
2739
2740         // Line to send
2741         std::wstring line;
2742         // Whether to send line to the player that sent the message, or to all players
2743         bool broadcast_line = true;
2744
2745         // Run script hook
2746         bool ate = m_script->on_chat_message(name,
2747                 wide_to_utf8(wmessage));
2748         // If script ate the message, don't proceed
2749         if (ate)
2750                 return L"";
2751
2752         if (player) {
2753                 switch (player->canSendChatMessage()) {
2754                         case RPLAYER_CHATRESULT_FLOODING: {
2755                                 std::wstringstream ws;
2756                                 ws << L"You cannot send more messages. You are limited to "
2757                                 << g_settings->getFloat("chat_message_limit_per_10sec")
2758                                 << L" messages per 10 seconds.";
2759                                 return ws.str();
2760                         }
2761                         case RPLAYER_CHATRESULT_KICK:
2762                                 DenyAccess_Legacy(player->peer_id, L"You have been kicked due to message flooding.");
2763                                 return L"";
2764                         case RPLAYER_CHATRESULT_OK: break;
2765                         default: FATAL_ERROR("Unhandled chat filtering result found.");
2766                 }
2767         }
2768
2769         if (m_max_chatmessage_length > 0 && wmessage.length() > m_max_chatmessage_length) {
2770                 return L"Your message exceed the maximum chat message limit set on the server. "
2771                         L"It was refused. Send a shorter message";
2772         }
2773
2774         // Commands are implemented in Lua, so only catch invalid
2775         // commands that were not "eaten" and send an error back
2776         if (wmessage[0] == L'/') {
2777                 std::wstring wcmd = wmessage.substr(1);
2778                 broadcast_line = false;
2779                 if (wcmd.length() == 0)
2780                         line += L"-!- Empty command";
2781                 else
2782                         line += L"-!- Invalid command: " + str_split(wcmd, L' ')[0];
2783         } else {
2784                 if (check_shout_priv && !checkPriv(name, "shout")) {
2785                         line += L"-!- You don't have permission to shout.";
2786                         broadcast_line = false;
2787                 } else {
2788                         line += L"<";
2789                         line += wname;
2790                         line += L"> ";
2791                         line += wmessage;
2792                 }
2793         }
2794
2795         /*
2796                 Tell calling method to send the message to sender
2797         */
2798         if (!broadcast_line) {
2799                 return line;
2800         } else {
2801                 /*
2802                         Send the message to others
2803                 */
2804                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2805
2806                 std::vector<u16> clients = m_clients.getClientIDs();
2807
2808                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2809                 for (u16 i = 0; i < clients.size(); i++) {
2810                         u16 cid = clients[i];
2811                         if (cid != peer_id_to_avoid_sending)
2812                                 SendChatMessage(cid, line);
2813                 }
2814         }
2815         return L"";
2816 }
2817
2818 void Server::handleAdminChat(const ChatEventChat *evt)
2819 {
2820         std::string name = evt->nick;
2821         std::wstring wname = utf8_to_wide(name);
2822         std::wstring wmessage = evt->evt_msg;
2823
2824         std::wstring answer = handleChat(name, wname, wmessage);
2825
2826         // If asked to send answer to sender
2827         if (!answer.empty()) {
2828                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2829         }
2830 }
2831
2832 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2833 {
2834         RemoteClient *client = getClientNoEx(peer_id,state_min);
2835         if(!client)
2836                 throw ClientNotFoundException("Client not found");
2837
2838         return client;
2839 }
2840 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2841 {
2842         return m_clients.getClientNoEx(peer_id, state_min);
2843 }
2844
2845 std::string Server::getPlayerName(u16 peer_id)
2846 {
2847         Player *player = m_env->getPlayer(peer_id);
2848         if(player == NULL)
2849                 return "[id="+itos(peer_id)+"]";
2850         return player->getName();
2851 }
2852
2853 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2854 {
2855         RemotePlayer *player = dynamic_cast<RemotePlayer *>(m_env->getPlayer(peer_id));
2856         if (player == NULL)
2857                 return NULL;
2858         return player->getPlayerSAO();
2859 }
2860
2861 std::wstring Server::getStatusString()
2862 {
2863         std::wostringstream os(std::ios_base::binary);
2864         os<<L"# Server: ";
2865         // Version
2866         os<<L"version="<<narrow_to_wide(g_version_string);
2867         // Uptime
2868         os<<L", uptime="<<m_uptime.get();
2869         // Max lag estimate
2870         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2871         // Information about clients
2872         bool first = true;
2873         os<<L", clients={";
2874         std::vector<u16> clients = m_clients.getClientIDs();
2875         for(std::vector<u16>::iterator i = clients.begin();
2876                 i != clients.end(); ++i) {
2877                 // Get player
2878                 Player *player = m_env->getPlayer(*i);
2879                 // Get name of player
2880                 std::wstring name = L"unknown";
2881                 if(player != NULL)
2882                         name = narrow_to_wide(player->getName());
2883                 // Add name to information string
2884                 if(!first)
2885                         os << L", ";
2886                 else
2887                         first = false;
2888                 os << name;
2889         }
2890         os << L"}";
2891         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2892                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2893         if(g_settings->get("motd") != "")
2894                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2895         return os.str();
2896 }
2897
2898 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2899 {
2900         std::set<std::string> privs;
2901         m_script->getAuth(name, NULL, &privs);
2902         return privs;
2903 }
2904
2905 bool Server::checkPriv(const std::string &name, const std::string &priv)
2906 {
2907         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2908         return (privs.count(priv) != 0);
2909 }
2910
2911 void Server::reportPrivsModified(const std::string &name)
2912 {
2913         if(name == "") {
2914                 std::vector<u16> clients = m_clients.getClientIDs();
2915                 for(std::vector<u16>::iterator i = clients.begin();
2916                                 i != clients.end(); ++i) {
2917                         Player *player = m_env->getPlayer(*i);
2918                         reportPrivsModified(player->getName());
2919                 }
2920         } else {
2921                 RemotePlayer *player =
2922                         dynamic_cast<RemotePlayer *>(m_env->getPlayer(name.c_str()));
2923                 if (!player)
2924                         return;
2925                 SendPlayerPrivileges(player->peer_id);
2926                 PlayerSAO *sao = player->getPlayerSAO();
2927                 if(!sao)
2928                         return;
2929                 sao->updatePrivileges(
2930                                 getPlayerEffectivePrivs(name),
2931                                 isSingleplayer());
2932         }
2933 }
2934
2935 void Server::reportInventoryFormspecModified(const std::string &name)
2936 {
2937         Player *player = m_env->getPlayer(name.c_str());
2938         if(!player)
2939                 return;
2940         SendPlayerInventoryFormspec(player->peer_id);
2941 }
2942
2943 void Server::setIpBanned(const std::string &ip, const std::string &name)
2944 {
2945         m_banmanager->add(ip, name);
2946 }
2947
2948 void Server::unsetIpBanned(const std::string &ip_or_name)
2949 {
2950         m_banmanager->remove(ip_or_name);
2951 }
2952
2953 std::string Server::getBanDescription(const std::string &ip_or_name)
2954 {
2955         return m_banmanager->getBanDescription(ip_or_name);
2956 }
2957
2958 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2959 {
2960         // m_env will be NULL if the server is initializing
2961         if (!m_env)
2962                 return;
2963
2964         if (m_admin_nick == name && !m_admin_nick.empty()) {
2965                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
2966         }
2967
2968         Player *player = m_env->getPlayer(name);
2969         if (!player) {
2970                 return;
2971         }
2972
2973         if (player->peer_id == PEER_ID_INEXISTENT)
2974                 return;
2975
2976         SendChatMessage(player->peer_id, msg);
2977 }
2978
2979 bool Server::showFormspec(const char *playername, const std::string &formspec,
2980         const std::string &formname)
2981 {
2982         // m_env will be NULL if the server is initializing
2983         if (!m_env)
2984                 return false;
2985
2986         Player *player = m_env->getPlayer(playername);
2987         if (!player)
2988                 return false;
2989
2990         SendShowFormspecMessage(player->peer_id, formspec, formname);
2991         return true;
2992 }
2993
2994 u32 Server::hudAdd(Player *player, HudElement *form)
2995 {
2996         if (!player)
2997                 return -1;
2998
2999         u32 id = player->addHud(form);
3000
3001         SendHUDAdd(player->peer_id, id, form);
3002
3003         return id;
3004 }
3005
3006 bool Server::hudRemove(Player *player, u32 id) {
3007         if (!player)
3008                 return false;
3009
3010         HudElement* todel = player->removeHud(id);
3011
3012         if (!todel)
3013                 return false;
3014
3015         delete todel;
3016
3017         SendHUDRemove(player->peer_id, id);
3018         return true;
3019 }
3020
3021 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data)
3022 {
3023         if (!player)
3024                 return false;
3025
3026         SendHUDChange(player->peer_id, id, stat, data);
3027         return true;
3028 }
3029
3030 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3031 {
3032         if (!player)
3033                 return false;
3034
3035         SendHUDSetFlags(player->peer_id, flags, mask);
3036         player->hud_flags &= ~mask;
3037         player->hud_flags |= flags;
3038
3039         PlayerSAO* playersao = player->getPlayerSAO();
3040
3041         if (playersao == NULL)
3042                 return false;
3043
3044         m_script->player_event(playersao, "hud_changed");
3045         return true;
3046 }
3047
3048 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3049 {
3050         if (!player)
3051                 return false;
3052
3053         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3054                 return false;
3055
3056         player->setHotbarItemcount(hotbar_itemcount);
3057         std::ostringstream os(std::ios::binary);
3058         writeS32(os, hotbar_itemcount);
3059         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3060         return true;
3061 }
3062
3063 void Server::hudSetHotbarImage(Player *player, std::string name)
3064 {
3065         if (!player)
3066                 return;
3067
3068         player->setHotbarImage(name);
3069         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3070 }
3071
3072 std::string Server::hudGetHotbarImage(Player *player)
3073 {
3074         if (!player)
3075                 return "";
3076         return player->getHotbarImage();
3077 }
3078
3079 void Server::hudSetHotbarSelectedImage(Player *player, std::string name)
3080 {
3081         if (!player)
3082                 return;
3083
3084         player->setHotbarSelectedImage(name);
3085         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3086 }
3087
3088 std::string Server::hudGetHotbarSelectedImage(Player *player)
3089 {
3090         if (!player)
3091                 return "";
3092
3093         return player->getHotbarSelectedImage();
3094 }
3095
3096 bool Server::setLocalPlayerAnimations(Player *player,
3097         v2s32 animation_frames[4], f32 frame_speed)
3098 {
3099         if (!player)
3100                 return false;
3101
3102         player->setLocalAnimations(animation_frames, frame_speed);
3103         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3104         return true;
3105 }
3106
3107 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
3108 {
3109         if (!player)
3110                 return false;
3111
3112         player->eye_offset_first = first;
3113         player->eye_offset_third = third;
3114         SendEyeOffset(player->peer_id, first, third);
3115         return true;
3116 }
3117
3118 bool Server::setSky(Player *player, const video::SColor &bgcolor,
3119         const std::string &type, const std::vector<std::string> &params)
3120 {
3121         if (!player)
3122                 return false;
3123
3124         player->setSky(bgcolor, type, params);
3125         SendSetSky(player->peer_id, bgcolor, type, params);
3126         return true;
3127 }
3128
3129 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3130         float ratio)
3131 {
3132         if (!player)
3133                 return false;
3134
3135         player->overrideDayNightRatio(do_override, ratio);
3136         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3137         return true;
3138 }
3139
3140 void Server::notifyPlayers(const std::wstring &msg)
3141 {
3142         SendChatMessage(PEER_ID_INEXISTENT,msg);
3143 }
3144
3145 void Server::spawnParticle(const std::string &playername, v3f pos,
3146         v3f velocity, v3f acceleration,
3147         float expirationtime, float size, bool
3148         collisiondetection, bool collision_removal,
3149         bool vertical, const std::string &texture)
3150 {
3151         // m_env will be NULL if the server is initializing
3152         if (!m_env)
3153                 return;
3154
3155         u16 peer_id = PEER_ID_INEXISTENT;
3156         if (playername != "") {
3157                 Player* player = m_env->getPlayer(playername.c_str());
3158                 if (!player)
3159                         return;
3160                 peer_id = player->peer_id;
3161         }
3162
3163         SendSpawnParticle(peer_id, pos, velocity, acceleration,
3164                         expirationtime, size, collisiondetection,
3165                         collision_removal, vertical, texture);
3166 }
3167
3168 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3169         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3170         float minexptime, float maxexptime, float minsize, float maxsize,
3171         bool collisiondetection, bool collision_removal,
3172         bool vertical, const std::string &texture,
3173         const std::string &playername)
3174 {
3175         // m_env will be NULL if the server is initializing
3176         if (!m_env)
3177                 return -1;
3178
3179         u16 peer_id = PEER_ID_INEXISTENT;
3180         if (playername != "") {
3181                 Player* player = m_env->getPlayer(playername.c_str());
3182                 if (!player)
3183                         return -1;
3184                 peer_id = player->peer_id;
3185         }
3186
3187         u32 id = m_env->addParticleSpawner(spawntime);
3188         SendAddParticleSpawner(peer_id, amount, spawntime,
3189                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3190                 minexptime, maxexptime, minsize, maxsize,
3191                 collisiondetection, collision_removal, vertical, texture, id);
3192
3193         return id;
3194 }
3195
3196 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3197 {
3198         // m_env will be NULL if the server is initializing
3199         if (!m_env)
3200                 throw ServerError("Can't delete particle spawners during initialisation!");
3201
3202         u16 peer_id = PEER_ID_INEXISTENT;
3203         if (playername != "") {
3204                 Player* player = m_env->getPlayer(playername.c_str());
3205                 if (!player)
3206                         return;
3207                 peer_id = player->peer_id;
3208         }
3209
3210         m_env->deleteParticleSpawner(id);
3211         SendDeleteParticleSpawner(peer_id, id);
3212 }
3213
3214 void Server::deleteParticleSpawnerAll(u32 id)
3215 {
3216         m_env->deleteParticleSpawner(id);
3217         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
3218 }
3219
3220 Inventory* Server::createDetachedInventory(const std::string &name)
3221 {
3222         if(m_detached_inventories.count(name) > 0){
3223                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3224                 delete m_detached_inventories[name];
3225         } else {
3226                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3227         }
3228         Inventory *inv = new Inventory(m_itemdef);
3229         sanity_check(inv);
3230         m_detached_inventories[name] = inv;
3231         //TODO find a better way to do this
3232         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3233         return inv;
3234 }
3235
3236 // actions: time-reversed list
3237 // Return value: success/failure
3238 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3239                 std::list<std::string> *log)
3240 {
3241         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3242         ServerMap *map = (ServerMap*)(&m_env->getMap());
3243
3244         // Fail if no actions to handle
3245         if(actions.empty()){
3246                 log->push_back("Nothing to do.");
3247                 return false;
3248         }
3249
3250         int num_tried = 0;
3251         int num_failed = 0;
3252
3253         for(std::list<RollbackAction>::const_iterator
3254                         i = actions.begin();
3255                         i != actions.end(); ++i)
3256         {
3257                 const RollbackAction &action = *i;
3258                 num_tried++;
3259                 bool success = action.applyRevert(map, this, this);
3260                 if(!success){
3261                         num_failed++;
3262                         std::ostringstream os;
3263                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3264                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3265                         if(log)
3266                                 log->push_back(os.str());
3267                 }else{
3268                         std::ostringstream os;
3269                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3270                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3271                         if(log)
3272                                 log->push_back(os.str());
3273                 }
3274         }
3275
3276         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3277                         <<" failed"<<std::endl;
3278
3279         // Call it done if less than half failed
3280         return num_failed <= num_tried/2;
3281 }
3282
3283 // IGameDef interface
3284 // Under envlock
3285 IItemDefManager *Server::getItemDefManager()
3286 {
3287         return m_itemdef;
3288 }
3289
3290 INodeDefManager *Server::getNodeDefManager()
3291 {
3292         return m_nodedef;
3293 }
3294
3295 ICraftDefManager *Server::getCraftDefManager()
3296 {
3297         return m_craftdef;
3298 }
3299 ITextureSource *Server::getTextureSource()
3300 {
3301         return NULL;
3302 }
3303 IShaderSource *Server::getShaderSource()
3304 {
3305         return NULL;
3306 }
3307 scene::ISceneManager *Server::getSceneManager()
3308 {
3309         return NULL;
3310 }
3311
3312 u16 Server::allocateUnknownNodeId(const std::string &name)
3313 {
3314         return m_nodedef->allocateDummy(name);
3315 }
3316
3317 ISoundManager *Server::getSoundManager()
3318 {
3319         return &dummySoundManager;
3320 }
3321
3322 MtEventManager *Server::getEventManager()
3323 {
3324         return m_event;
3325 }
3326
3327 IWritableItemDefManager *Server::getWritableItemDefManager()
3328 {
3329         return m_itemdef;
3330 }
3331
3332 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3333 {
3334         return m_nodedef;
3335 }
3336
3337 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3338 {
3339         return m_craftdef;
3340 }
3341
3342 const ModSpec *Server::getModSpec(const std::string &modname) const
3343 {
3344         std::vector<ModSpec>::const_iterator it;
3345         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3346                 const ModSpec &mod = *it;
3347                 if (mod.name == modname)
3348                         return &mod;
3349         }
3350         return NULL;
3351 }
3352
3353 void Server::getModNames(std::vector<std::string> &modlist)
3354 {
3355         std::vector<ModSpec>::iterator it;
3356         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3357                 modlist.push_back(it->name);
3358 }
3359
3360 std::string Server::getBuiltinLuaPath()
3361 {
3362         return porting::path_share + DIR_DELIM + "builtin";
3363 }
3364
3365 v3f Server::findSpawnPos()
3366 {
3367         ServerMap &map = m_env->getServerMap();
3368         v3f nodeposf;
3369         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3370                 return nodeposf * BS;
3371         }
3372
3373         bool is_good = false;
3374
3375         // Try to find a good place a few times
3376         for(s32 i = 0; i < 4000 && !is_good; i++) {
3377                 s32 range = 1 + i;
3378                 // We're going to try to throw the player to this position
3379                 v2s16 nodepos2d = v2s16(
3380                                 -range + (myrand() % (range * 2)),
3381                                 -range + (myrand() % (range * 2)));
3382
3383                 // Get spawn level at point
3384                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3385                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3386                 // the mapgen to signify an unsuitable spawn position
3387                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3388                         continue;
3389
3390                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3391
3392                 s32 air_count = 0;
3393                 for (s32 i = 0; i < 10; i++) {
3394                         v3s16 blockpos = getNodeBlockPos(nodepos);
3395                         map.emergeBlock(blockpos, true);
3396                         content_t c = map.getNodeNoEx(nodepos).getContent();
3397                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3398                                 air_count++;
3399                                 if (air_count >= 2) {
3400                                         nodeposf = intToFloat(nodepos, BS);
3401                                         // Don't spawn the player outside map boundaries
3402                                         if (objectpos_over_limit(nodeposf))
3403                                                 continue;
3404                                         is_good = true;
3405                                         break;
3406                                 }
3407                         }
3408                         nodepos.Y++;
3409                 }
3410         }
3411
3412         return nodeposf;
3413 }
3414
3415 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3416 {
3417         bool newplayer = false;
3418
3419         /*
3420                 Try to get an existing player
3421         */
3422         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3423
3424         // If player is already connected, cancel
3425         if(player != NULL && player->peer_id != 0)
3426         {
3427                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3428                 return NULL;
3429         }
3430
3431         /*
3432                 If player with the wanted peer_id already exists, cancel.
3433         */
3434         if(m_env->getPlayer(peer_id) != NULL)
3435         {
3436                 infostream<<"emergePlayer(): Player with wrong name but same"
3437                                 " peer_id already exists"<<std::endl;
3438                 return NULL;
3439         }
3440
3441         // Load player if it isn't already loaded
3442         if (!player) {
3443                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3444         }
3445
3446         // Create player if it doesn't exist
3447         if (!player) {
3448                 newplayer = true;
3449                 player = new RemotePlayer(this, name);
3450                 // Set player position
3451                 infostream<<"Server: Finding spawn place for player \""
3452                                 <<name<<"\""<<std::endl;
3453                 v3f pos = findSpawnPos();
3454                 player->setPosition(pos);
3455
3456                 // Make sure the player is saved
3457                 player->setModified(true);
3458
3459                 // Add player to environment
3460                 m_env->addPlayer(player);
3461         } else {
3462                 // If the player exists, ensure that they respawn inside legal bounds
3463                 // This fixes an assert crash when the player can't be added
3464                 // to the environment
3465                 if (objectpos_over_limit(player->getPosition())) {
3466                         actionstream << "Respawn position for player \""
3467                                 << name << "\" outside limits, resetting" << std::endl;
3468                         v3f pos = findSpawnPos();
3469                         player->setPosition(pos);
3470                 }
3471         }
3472
3473         // Create a new player active object
3474         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3475                         getPlayerEffectivePrivs(player->getName()),
3476                         isSingleplayer());
3477
3478         player->protocol_version = proto_version;
3479
3480         /* Clean up old HUD elements from previous sessions */
3481         player->clearHud();
3482
3483         /* Add object to environment */
3484         m_env->addActiveObject(playersao);
3485
3486         /* Run scripts */
3487         if (newplayer) {
3488                 m_script->on_newplayer(playersao);
3489         }
3490
3491         return playersao;
3492 }
3493
3494 void dedicated_server_loop(Server &server, bool &kill)
3495 {
3496         DSTACK(FUNCTION_NAME);
3497
3498         verbosestream<<"dedicated_server_loop()"<<std::endl;
3499
3500         IntervalLimiter m_profiler_interval;
3501
3502         static const float steplen = g_settings->getFloat("dedicated_server_step");
3503         static const float profiler_print_interval =
3504                         g_settings->getFloat("profiler_print_interval");
3505
3506         for(;;) {
3507                 // This is kind of a hack but can be done like this
3508                 // because server.step() is very light
3509                 {
3510                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3511                         sleep_ms((int)(steplen*1000.0));
3512                 }
3513                 server.step(steplen);
3514
3515                 if(server.getShutdownRequested() || kill)
3516                 {
3517                         infostream<<"Dedicated server quitting"<<std::endl;
3518 #if USE_CURL
3519                         if(g_settings->getBool("server_announce"))
3520                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3521 #endif
3522                         break;
3523                 }
3524
3525                 /*
3526                         Profiler
3527                 */
3528                 if (profiler_print_interval != 0) {
3529                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3530                         {
3531                                 infostream<<"Profiler:"<<std::endl;
3532                                 g_profiler->print(infostream);
3533                                 g_profiler->clear();
3534                         }
3535                 }
3536         }
3537 }