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