Player/LocalPlayer/RemotePlayer inheritance cleanup (part 2 on X)
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "threading/mutex_auto_lock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_game.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_abm.h"
51 #include "content_sao.h"
52 #include "mods.h"
53 #include "sound.h" // dummySoundManager
54 #include "event_manager.h"
55 #include "serverlist.h"
56 #include "util/string.h"
57 #include "util/mathconstants.h"
58 #include "rollback.h"
59 #include "util/serialize.h"
60 #include "util/thread.h"
61 #include "defaultsettings.h"
62 #include "util/base64.h"
63 #include "util/sha1.h"
64 #include "util/hex.h"
65
66 class ClientNotFoundException : public BaseException
67 {
68 public:
69         ClientNotFoundException(const char *s):
70                 BaseException(s)
71         {}
72 };
73
74 class ServerThread : public Thread
75 {
76 public:
77
78         ServerThread(Server *server):
79                 Thread("Server"),
80                 m_server(server)
81         {}
82
83         void *run();
84
85 private:
86         Server *m_server;
87 };
88
89 void *ServerThread::run()
90 {
91         DSTACK(FUNCTION_NAME);
92         BEGIN_DEBUG_EXCEPTION_HANDLER
93
94         m_server->AsyncRunStep(true);
95
96         while (!stopRequested()) {
97                 try {
98                         //TimeTaker timer("AsyncRunStep() + Receive()");
99
100                         m_server->AsyncRunStep();
101
102                         m_server->Receive();
103
104                 } catch (con::NoIncomingDataException &e) {
105                 } catch (con::PeerNotFoundException &e) {
106                         infostream<<"Server: PeerNotFoundException"<<std::endl;
107                 } catch (ClientNotFoundException &e) {
108                 } catch (con::ConnectionBindFailed &e) {
109                         m_server->setAsyncFatalError(e.what());
110                 } catch (LuaError &e) {
111                         m_server->setAsyncFatalError("Lua: " + std::string(e.what()));
112                 }
113         }
114
115         END_DEBUG_EXCEPTION_HANDLER
116
117         return NULL;
118 }
119
120 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
121 {
122         if(pos_exists) *pos_exists = false;
123         switch(type){
124         case SSP_LOCAL:
125                 return v3f(0,0,0);
126         case SSP_POSITIONAL:
127                 if(pos_exists) *pos_exists = true;
128                 return pos;
129         case SSP_OBJECT: {
130                 if(object == 0)
131                         return v3f(0,0,0);
132                 ServerActiveObject *sao = env->getActiveObject(object);
133                 if(!sao)
134                         return v3f(0,0,0);
135                 if(pos_exists) *pos_exists = true;
136                 return sao->getBasePosition(); }
137         }
138         return v3f(0,0,0);
139 }
140
141
142
143 /*
144         Server
145 */
146
147 Server::Server(
148                 const std::string &path_world,
149                 const SubgameSpec &gamespec,
150                 bool simple_singleplayer_mode,
151                 bool ipv6,
152                 ChatInterface *iface
153         ):
154         m_path_world(path_world),
155         m_gamespec(gamespec),
156         m_simple_singleplayer_mode(simple_singleplayer_mode),
157         m_async_fatal_error(""),
158         m_env(NULL),
159         m_con(PROTOCOL_ID,
160                         512,
161                         CONNECTION_TIMEOUT,
162                         ipv6,
163                         this),
164         m_banmanager(NULL),
165         m_rollback(NULL),
166         m_enable_rollback_recording(false),
167         m_emerge(NULL),
168         m_script(NULL),
169         m_itemdef(createItemDefManager()),
170         m_nodedef(createNodeDefManager()),
171         m_craftdef(createCraftDefManager()),
172         m_event(new EventManager()),
173         m_thread(NULL),
174         m_time_of_day_send_timer(0),
175         m_uptime(0),
176         m_clients(&m_con),
177         m_shutdown_requested(false),
178         m_shutdown_ask_reconnect(false),
179         m_admin_chat(iface),
180         m_ignore_map_edit_events(false),
181         m_ignore_map_edit_events_peer_id(0),
182         m_next_sound_id(0)
183
184 {
185         m_liquid_transform_timer = 0.0;
186         m_liquid_transform_every = 1.0;
187         m_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                         Player *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                 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>::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         Player *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         Player *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         Player *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                 Player *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
1982                                 i = clients.begin(); i != clients.end(); ++i) {
1983                         Player *player = m_env->getPlayer(*i);
1984                         if(!player)
1985                                 continue;
1986
1987                         if(pos_exists) {
1988                                 if(player->getPosition().getDistanceFrom(pos) >
1989                                                 params.max_hear_distance)
1990                                         continue;
1991                         }
1992                         dst_clients.push_back(*i);
1993                 }
1994         }
1995
1996         if(dst_clients.empty())
1997                 return -1;
1998
1999         // Create the sound
2000         s32 id = m_next_sound_id++;
2001         // The sound will exist as a reference in m_playing_sounds
2002         m_playing_sounds[id] = ServerPlayingSound();
2003         ServerPlayingSound &psound = m_playing_sounds[id];
2004         psound.params = params;
2005
2006         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2007         pkt << id << spec.name << (float) (spec.gain * params.gain)
2008                         << (u8) params.type << pos << params.object << params.loop;
2009
2010         for(std::vector<u16>::iterator i = dst_clients.begin();
2011                         i != dst_clients.end(); ++i) {
2012                 psound.clients.insert(*i);
2013                 m_clients.send(*i, 0, &pkt, true);
2014         }
2015         return id;
2016 }
2017 void Server::stopSound(s32 handle)
2018 {
2019         // Get sound reference
2020         UNORDERED_MAP<s32, ServerPlayingSound>::iterator i = m_playing_sounds.find(handle);
2021         if (i == m_playing_sounds.end())
2022                 return;
2023         ServerPlayingSound &psound = i->second;
2024
2025         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2026         pkt << handle;
2027
2028         for (UNORDERED_SET<u16>::iterator i = psound.clients.begin();
2029                         i != psound.clients.end(); ++i) {
2030                 // Send as reliable
2031                 m_clients.send(*i, 0, &pkt, true);
2032         }
2033         // Remove sound reference
2034         m_playing_sounds.erase(i);
2035 }
2036
2037 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2038         std::vector<u16> *far_players, float far_d_nodes)
2039 {
2040         float maxd = far_d_nodes*BS;
2041         v3f p_f = intToFloat(p, BS);
2042
2043         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2044         pkt << p;
2045
2046         std::vector<u16> clients = m_clients.getClientIDs();
2047         for(std::vector<u16>::iterator i = clients.begin();
2048                 i != clients.end(); ++i) {
2049                 if (far_players) {
2050                         // Get player
2051                         if(Player *player = m_env->getPlayer(*i)) {
2052                                 // If player is far away, only set modified blocks not sent
2053                                 v3f player_pos = player->getPosition();
2054                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2055                                         far_players->push_back(*i);
2056                                         continue;
2057                                 }
2058                         }
2059                 }
2060
2061                 // Send as reliable
2062                 m_clients.send(*i, 0, &pkt, true);
2063         }
2064 }
2065
2066 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2067                 std::vector<u16> *far_players, float far_d_nodes,
2068                 bool remove_metadata)
2069 {
2070         float maxd = far_d_nodes*BS;
2071         v3f p_f = intToFloat(p, BS);
2072
2073         std::vector<u16> clients = m_clients.getClientIDs();
2074         for(std::vector<u16>::iterator i = clients.begin();
2075                         i != clients.end(); ++i) {
2076
2077                 if(far_players) {
2078                         // Get player
2079                         if(Player *player = m_env->getPlayer(*i)) {
2080                                 // If player is far away, only set modified blocks not sent
2081                                 v3f player_pos = player->getPosition();
2082                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2083                                         far_players->push_back(*i);
2084                                         continue;
2085                                 }
2086                         }
2087                 }
2088
2089                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2090                 m_clients.lock();
2091                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2092                 if (client != 0) {
2093                         pkt << p << n.param0 << n.param1 << n.param2
2094                                         << (u8) (remove_metadata ? 0 : 1);
2095
2096                         if (!remove_metadata) {
2097                                 if (client->net_proto_version <= 21) {
2098                                         // Old clients always clear metadata; fix it
2099                                         // by sending the full block again.
2100                                         client->SetBlockNotSent(getNodeBlockPos(p));
2101                                 }
2102                         }
2103                 }
2104                 m_clients.unlock();
2105
2106                 // Send as reliable
2107                 if (pkt.getSize() > 0)
2108                         m_clients.send(*i, 0, &pkt, true);
2109         }
2110 }
2111
2112 void Server::setBlockNotSent(v3s16 p)
2113 {
2114         std::vector<u16> clients = m_clients.getClientIDs();
2115         m_clients.lock();
2116         for(std::vector<u16>::iterator i = clients.begin();
2117                 i != clients.end(); ++i) {
2118                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2119                 client->SetBlockNotSent(p);
2120         }
2121         m_clients.unlock();
2122 }
2123
2124 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2125 {
2126         DSTACK(FUNCTION_NAME);
2127
2128         v3s16 p = block->getPos();
2129
2130         /*
2131                 Create a packet with the block in the right format
2132         */
2133
2134         std::ostringstream os(std::ios_base::binary);
2135         block->serialize(os, ver, false);
2136         block->serializeNetworkSpecific(os, net_proto_version);
2137         std::string s = os.str();
2138
2139         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2140
2141         pkt << p;
2142         pkt.putRawString(s.c_str(), s.size());
2143         Send(&pkt);
2144 }
2145
2146 void Server::SendBlocks(float dtime)
2147 {
2148         DSTACK(FUNCTION_NAME);
2149
2150         MutexAutoLock envlock(m_env_mutex);
2151         //TODO check if one big lock could be faster then multiple small ones
2152
2153         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2154
2155         std::vector<PrioritySortedBlockTransfer> queue;
2156
2157         s32 total_sending = 0;
2158
2159         {
2160                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2161
2162                 std::vector<u16> clients = m_clients.getClientIDs();
2163
2164                 m_clients.lock();
2165                 for(std::vector<u16>::iterator i = clients.begin();
2166                         i != clients.end(); ++i) {
2167                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2168
2169                         if (client == NULL)
2170                                 continue;
2171
2172                         total_sending += client->SendingCount();
2173                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2174                 }
2175                 m_clients.unlock();
2176         }
2177
2178         // Sort.
2179         // Lowest priority number comes first.
2180         // Lowest is most important.
2181         std::sort(queue.begin(), queue.end());
2182
2183         m_clients.lock();
2184         for(u32 i=0; i<queue.size(); i++)
2185         {
2186                 //TODO: Calculate limit dynamically
2187                 if(total_sending >= g_settings->getS32
2188                                 ("max_simultaneous_block_sends_server_total"))
2189                         break;
2190
2191                 PrioritySortedBlockTransfer q = queue[i];
2192
2193                 MapBlock *block = NULL;
2194                 try
2195                 {
2196                         block = m_env->getMap().getBlockNoCreate(q.pos);
2197                 }
2198                 catch(InvalidPositionException &e)
2199                 {
2200                         continue;
2201                 }
2202
2203                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2204
2205                 if(!client)
2206                         continue;
2207
2208                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2209
2210                 client->SentBlock(q.pos);
2211                 total_sending++;
2212         }
2213         m_clients.unlock();
2214 }
2215
2216 void Server::fillMediaCache()
2217 {
2218         DSTACK(FUNCTION_NAME);
2219
2220         infostream<<"Server: Calculating media file checksums"<<std::endl;
2221
2222         // Collect all media file paths
2223         std::vector<std::string> paths;
2224         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2225                         i != m_mods.end(); ++i) {
2226                 const ModSpec &mod = *i;
2227                 paths.push_back(mod.path + DIR_DELIM + "textures");
2228                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2229                 paths.push_back(mod.path + DIR_DELIM + "media");
2230                 paths.push_back(mod.path + DIR_DELIM + "models");
2231         }
2232         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2233
2234         // Collect media file information from paths into cache
2235         for(std::vector<std::string>::iterator i = paths.begin();
2236                         i != paths.end(); ++i) {
2237                 std::string mediapath = *i;
2238                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2239                 for (u32 j = 0; j < dirlist.size(); j++) {
2240                         if (dirlist[j].dir) // Ignode dirs
2241                                 continue;
2242                         std::string filename = dirlist[j].name;
2243                         // If name contains illegal characters, ignore the file
2244                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2245                                 infostream<<"Server: ignoring illegal file name: \""
2246                                                 << filename << "\"" << std::endl;
2247                                 continue;
2248                         }
2249                         // If name is not in a supported format, ignore it
2250                         const char *supported_ext[] = {
2251                                 ".png", ".jpg", ".bmp", ".tga",
2252                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2253                                 ".ogg",
2254                                 ".x", ".b3d", ".md2", ".obj",
2255                                 NULL
2256                         };
2257                         if (removeStringEnd(filename, supported_ext) == ""){
2258                                 infostream << "Server: ignoring unsupported file extension: \""
2259                                                 << filename << "\"" << std::endl;
2260                                 continue;
2261                         }
2262                         // Ok, attempt to load the file and add to cache
2263                         std::string filepath = mediapath + DIR_DELIM + filename;
2264                         // Read data
2265                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2266                         if (!fis.good()) {
2267                                 errorstream << "Server::fillMediaCache(): Could not open \""
2268                                                 << filename << "\" for reading" << std::endl;
2269                                 continue;
2270                         }
2271                         std::ostringstream tmp_os(std::ios_base::binary);
2272                         bool bad = false;
2273                         for(;;) {
2274                                 char buf[1024];
2275                                 fis.read(buf, 1024);
2276                                 std::streamsize len = fis.gcount();
2277                                 tmp_os.write(buf, len);
2278                                 if (fis.eof())
2279                                         break;
2280                                 if (!fis.good()) {
2281                                         bad = true;
2282                                         break;
2283                                 }
2284                         }
2285                         if(bad) {
2286                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2287                                                 << filename << "\"" << std::endl;
2288                                 continue;
2289                         }
2290                         if(tmp_os.str().length() == 0) {
2291                                 errorstream << "Server::fillMediaCache(): Empty file \""
2292                                                 << filepath << "\"" << std::endl;
2293                                 continue;
2294                         }
2295
2296                         SHA1 sha1;
2297                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2298
2299                         unsigned char *digest = sha1.getDigest();
2300                         std::string sha1_base64 = base64_encode(digest, 20);
2301                         std::string sha1_hex = hex_encode((char*)digest, 20);
2302                         free(digest);
2303
2304                         // Put in list
2305                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2306                         verbosestream << "Server: " << sha1_hex << " is " << filename
2307                                         << std::endl;
2308                 }
2309         }
2310 }
2311
2312 void Server::sendMediaAnnouncement(u16 peer_id)
2313 {
2314         DSTACK(FUNCTION_NAME);
2315
2316         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2317                 << std::endl;
2318
2319         // Make packet
2320         std::ostringstream os(std::ios_base::binary);
2321
2322         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2323         pkt << (u16) m_media.size();
2324
2325         for (UNORDERED_MAP<std::string, MediaInfo>::iterator i = m_media.begin();
2326                         i != m_media.end(); ++i) {
2327                 pkt << i->first << i->second.sha1_digest;
2328         }
2329
2330         pkt << g_settings->get("remote_media");
2331         Send(&pkt);
2332 }
2333
2334 struct SendableMedia
2335 {
2336         std::string name;
2337         std::string path;
2338         std::string data;
2339
2340         SendableMedia(const std::string &name_="", const std::string &path_="",
2341                       const std::string &data_=""):
2342                 name(name_),
2343                 path(path_),
2344                 data(data_)
2345         {}
2346 };
2347
2348 void Server::sendRequestedMedia(u16 peer_id,
2349                 const std::vector<std::string> &tosend)
2350 {
2351         DSTACK(FUNCTION_NAME);
2352
2353         verbosestream<<"Server::sendRequestedMedia(): "
2354                         <<"Sending files to client"<<std::endl;
2355
2356         /* Read files */
2357
2358         // Put 5kB in one bunch (this is not accurate)
2359         u32 bytes_per_bunch = 5000;
2360
2361         std::vector< std::vector<SendableMedia> > file_bunches;
2362         file_bunches.push_back(std::vector<SendableMedia>());
2363
2364         u32 file_size_bunch_total = 0;
2365
2366         for(std::vector<std::string>::const_iterator i = tosend.begin();
2367                         i != tosend.end(); ++i) {
2368                 const std::string &name = *i;
2369
2370                 if (m_media.find(name) == m_media.end()) {
2371                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2372                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2373                         continue;
2374                 }
2375
2376                 //TODO get path + name
2377                 std::string tpath = m_media[name].path;
2378
2379                 // Read data
2380                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2381                 if(fis.good() == false){
2382                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2383                                         <<tpath<<"\" for reading"<<std::endl;
2384                         continue;
2385                 }
2386                 std::ostringstream tmp_os(std::ios_base::binary);
2387                 bool bad = false;
2388                 for(;;) {
2389                         char buf[1024];
2390                         fis.read(buf, 1024);
2391                         std::streamsize len = fis.gcount();
2392                         tmp_os.write(buf, len);
2393                         file_size_bunch_total += len;
2394                         if(fis.eof())
2395                                 break;
2396                         if(!fis.good()) {
2397                                 bad = true;
2398                                 break;
2399                         }
2400                 }
2401                 if(bad) {
2402                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2403                                         <<name<<"\""<<std::endl;
2404                         continue;
2405                 }
2406                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2407                                 <<tname<<"\""<<std::endl;*/
2408                 // Put in list
2409                 file_bunches[file_bunches.size()-1].push_back(
2410                                 SendableMedia(name, tpath, tmp_os.str()));
2411
2412                 // Start next bunch if got enough data
2413                 if(file_size_bunch_total >= bytes_per_bunch) {
2414                         file_bunches.push_back(std::vector<SendableMedia>());
2415                         file_size_bunch_total = 0;
2416                 }
2417
2418         }
2419
2420         /* Create and send packets */
2421
2422         u16 num_bunches = file_bunches.size();
2423         for(u16 i = 0; i < num_bunches; i++) {
2424                 /*
2425                         u16 command
2426                         u16 total number of texture bunches
2427                         u16 index of this bunch
2428                         u32 number of files in this bunch
2429                         for each file {
2430                                 u16 length of name
2431                                 string name
2432                                 u32 length of data
2433                                 data
2434                         }
2435                 */
2436
2437                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2438                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2439
2440                 for(std::vector<SendableMedia>::iterator
2441                                 j = file_bunches[i].begin();
2442                                 j != file_bunches[i].end(); ++j) {
2443                         pkt << j->name;
2444                         pkt.putLongString(j->data);
2445                 }
2446
2447                 verbosestream << "Server::sendRequestedMedia(): bunch "
2448                                 << i << "/" << num_bunches
2449                                 << " files=" << file_bunches[i].size()
2450                                 << " size="  << pkt.getSize() << std::endl;
2451                 Send(&pkt);
2452         }
2453 }
2454
2455 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2456 {
2457         if(m_detached_inventories.count(name) == 0) {
2458                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2459                 return;
2460         }
2461         Inventory *inv = m_detached_inventories[name];
2462         std::ostringstream os(std::ios_base::binary);
2463
2464         os << serializeString(name);
2465         inv->serialize(os);
2466
2467         // Make data buffer
2468         std::string s = os.str();
2469
2470         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2471         pkt.putRawString(s.c_str(), s.size());
2472
2473         if (peer_id != PEER_ID_INEXISTENT) {
2474                 Send(&pkt);
2475         }
2476         else {
2477                 m_clients.sendToAll(0, &pkt, true);
2478         }
2479 }
2480
2481 void Server::sendDetachedInventories(u16 peer_id)
2482 {
2483         DSTACK(FUNCTION_NAME);
2484
2485         for(std::map<std::string, Inventory*>::iterator
2486                         i = m_detached_inventories.begin();
2487                         i != m_detached_inventories.end(); ++i) {
2488                 const std::string &name = i->first;
2489                 //Inventory *inv = i->second;
2490                 sendDetachedInventory(name, peer_id);
2491         }
2492 }
2493
2494 /*
2495         Something random
2496 */
2497
2498 void Server::DiePlayer(u16 peer_id)
2499 {
2500         DSTACK(FUNCTION_NAME);
2501         PlayerSAO *playersao = getPlayerSAO(peer_id);
2502         // In some rare cases this can be NULL -- if the player is disconnected
2503         // when a Lua function modifies l_punch, for example
2504         if (!playersao)
2505                 return;
2506
2507         infostream << "Server::DiePlayer(): Player "
2508                         << playersao->getPlayer()->getName()
2509                         << " dies" << std::endl;
2510
2511         playersao->setHP(0);
2512
2513         // Trigger scripted stuff
2514         m_script->on_dieplayer(playersao);
2515
2516         SendPlayerHP(peer_id);
2517         SendDeathscreen(peer_id, false, v3f(0,0,0));
2518 }
2519
2520 void Server::RespawnPlayer(u16 peer_id)
2521 {
2522         DSTACK(FUNCTION_NAME);
2523
2524         PlayerSAO *playersao = getPlayerSAO(peer_id);
2525         assert(playersao);
2526
2527         infostream << "Server::RespawnPlayer(): Player "
2528                         << playersao->getPlayer()->getName()
2529                         << " respawns" << std::endl;
2530
2531         playersao->setHP(PLAYER_MAX_HP);
2532         playersao->setBreath(PLAYER_MAX_BREATH);
2533
2534         SendPlayerHP(peer_id);
2535         SendPlayerBreath(peer_id);
2536
2537         bool repositioned = m_script->on_respawnplayer(playersao);
2538         if(!repositioned){
2539                 v3f pos = findSpawnPos();
2540                 // setPos will send the new position to client
2541                 playersao->setPos(pos);
2542         }
2543 }
2544
2545
2546 void Server::DenySudoAccess(u16 peer_id)
2547 {
2548         DSTACK(FUNCTION_NAME);
2549
2550         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2551         Send(&pkt);
2552 }
2553
2554
2555 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2556                 const std::string &str_reason, bool reconnect)
2557 {
2558         if (proto_ver >= 25) {
2559                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2560         } else {
2561                 std::wstring wreason = utf8_to_wide(
2562                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2563                         accessDeniedStrings[(u8)reason]);
2564                 SendAccessDenied_Legacy(peer_id, wreason);
2565         }
2566
2567         m_clients.event(peer_id, CSE_SetDenied);
2568         m_con.DisconnectPeer(peer_id);
2569 }
2570
2571
2572 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2573 {
2574         DSTACK(FUNCTION_NAME);
2575
2576         SendAccessDenied(peer_id, reason, custom_reason);
2577         m_clients.event(peer_id, CSE_SetDenied);
2578         m_con.DisconnectPeer(peer_id);
2579 }
2580
2581 // 13/03/15: remove this function when protocol version 25 will become
2582 // the minimum version for MT users, maybe in 1 year
2583 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2584 {
2585         DSTACK(FUNCTION_NAME);
2586
2587         SendAccessDenied_Legacy(peer_id, reason);
2588         m_clients.event(peer_id, CSE_SetDenied);
2589         m_con.DisconnectPeer(peer_id);
2590 }
2591
2592 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2593 {
2594         DSTACK(FUNCTION_NAME);
2595
2596         if (!forSudoMode) {
2597                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2598
2599                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2600
2601                 // Right now, the auth mechs don't change between login and sudo mode.
2602                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2603                 client->allowed_sudo_mechs = sudo_auth_mechs;
2604
2605                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2606                                 << g_settings->getFloat("dedicated_server_step")
2607                                 << sudo_auth_mechs;
2608
2609                 Send(&resp_pkt);
2610                 m_clients.event(peer_id, CSE_AuthAccept);
2611         } else {
2612                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2613
2614                 // We only support SRP right now
2615                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2616
2617                 resp_pkt << sudo_auth_mechs;
2618                 Send(&resp_pkt);
2619                 m_clients.event(peer_id, CSE_SudoSuccess);
2620         }
2621 }
2622
2623 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2624 {
2625         DSTACK(FUNCTION_NAME);
2626         std::wstring message;
2627         {
2628                 /*
2629                         Clear references to playing sounds
2630                 */
2631                 for (UNORDERED_MAP<s32, ServerPlayingSound>::iterator
2632                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2633                         ServerPlayingSound &psound = i->second;
2634                         psound.clients.erase(peer_id);
2635                         if (psound.clients.empty())
2636                                 m_playing_sounds.erase(i++);
2637                         else
2638                                 ++i;
2639                 }
2640
2641                 RemotePlayer *player = m_env->getPlayer(peer_id);
2642
2643                 /* Run scripts and remove from environment */
2644                 if(player != NULL) {
2645                         PlayerSAO *playersao = player->getPlayerSAO();
2646                         assert(playersao);
2647
2648                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2649
2650                         playersao->disconnected();
2651                 }
2652
2653                 /*
2654                         Print out action
2655                 */
2656                 {
2657                         if(player != NULL && reason != CDR_DENY) {
2658                                 std::ostringstream os(std::ios_base::binary);
2659                                 std::vector<u16> clients = m_clients.getClientIDs();
2660
2661                                 for(std::vector<u16>::iterator i = clients.begin();
2662                                         i != clients.end(); ++i) {
2663                                         // Get player
2664                                         Player *player = m_env->getPlayer(*i);
2665                                         if(!player)
2666                                                 continue;
2667
2668                                         // Get name of player
2669                                         os << player->getName() << " ";
2670                                 }
2671
2672                                 std::string name = player->getName();
2673                                 actionstream << name << " "
2674                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2675                                                 << " List of players: " << os.str() << std::endl;
2676                                 if (m_admin_chat)
2677                                         m_admin_chat->outgoing_queue.push_back(
2678                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2679                         }
2680                 }
2681                 {
2682                         MutexAutoLock env_lock(m_env_mutex);
2683                         m_clients.DeleteClient(peer_id);
2684                 }
2685         }
2686
2687         // Send leave chat message to all remaining clients
2688         if(message.length() != 0)
2689                 SendChatMessage(PEER_ID_INEXISTENT,message);
2690 }
2691
2692 void Server::UpdateCrafting(RemotePlayer* player)
2693 {
2694         DSTACK(FUNCTION_NAME);
2695
2696         // Get a preview for crafting
2697         ItemStack preview;
2698         InventoryLocation loc;
2699         loc.setPlayer(player->getName());
2700         std::vector<ItemStack> output_replacements;
2701         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2702         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2703                         (&player->inventory)->getList("craft"), loc);
2704
2705         // Put the new preview in
2706         InventoryList *plist = player->inventory.getList("craftpreview");
2707         sanity_check(plist);
2708         sanity_check(plist->getSize() >= 1);
2709         plist->changeItem(0, preview);
2710 }
2711
2712 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2713 {
2714         if (evt->type == CET_NICK_ADD) {
2715                 // The terminal informed us of its nick choice
2716                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2717                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2718                         errorstream << "You haven't set up an account." << std::endl
2719                                 << "Please log in using the client as '"
2720                                 << m_admin_nick << "' with a secure password." << std::endl
2721                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2722                                 << "and everybody can claim the user account instead of you," << std::endl
2723                                 << "giving them full control over this server." << std::endl;
2724                 }
2725         } else {
2726                 assert(evt->type == CET_CHAT);
2727                 handleAdminChat((ChatEventChat *)evt);
2728         }
2729 }
2730
2731 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2732         const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
2733 {
2734         // If something goes wrong, this player is to blame
2735         RollbackScopeActor rollback_scope(m_rollback,
2736                 std::string("player:") + name);
2737
2738         // Line to send
2739         std::wstring line;
2740         // Whether to send line to the player that sent the message, or to all players
2741         bool broadcast_line = true;
2742
2743         // Run script hook
2744         bool ate = m_script->on_chat_message(name,
2745                 wide_to_utf8(wmessage));
2746         // If script ate the message, don't proceed
2747         if (ate)
2748                 return L"";
2749
2750         if (player) {
2751                 switch (player->canSendChatMessage()) {
2752                         case RPLAYER_CHATRESULT_FLOODING: {
2753                                 std::wstringstream ws;
2754                                 ws << L"You cannot send more messages. You are limited to "
2755                                 << g_settings->getFloat("chat_message_limit_per_10sec")
2756                                 << L" messages per 10 seconds.";
2757                                 return ws.str();
2758                         }
2759                         case RPLAYER_CHATRESULT_KICK:
2760                                 DenyAccess_Legacy(player->peer_id, L"You have been kicked due to message flooding.");
2761                                 return L"";
2762                         case RPLAYER_CHATRESULT_OK: break;
2763                         default: FATAL_ERROR("Unhandled chat filtering result found.");
2764                 }
2765         }
2766
2767         if (m_max_chatmessage_length > 0 && wmessage.length() > m_max_chatmessage_length) {
2768                 return L"Your message exceed the maximum chat message limit set on the server. "
2769                         L"It was refused. Send a shorter message";
2770         }
2771
2772         // Commands are implemented in Lua, so only catch invalid
2773         // commands that were not "eaten" and send an error back
2774         if (wmessage[0] == L'/') {
2775                 std::wstring wcmd = wmessage.substr(1);
2776                 broadcast_line = false;
2777                 if (wcmd.length() == 0)
2778                         line += L"-!- Empty command";
2779                 else
2780                         line += L"-!- Invalid command: " + str_split(wcmd, L' ')[0];
2781         } else {
2782                 if (check_shout_priv && !checkPriv(name, "shout")) {
2783                         line += L"-!- You don't have permission to shout.";
2784                         broadcast_line = false;
2785                 } else {
2786                         line += L"<";
2787                         line += wname;
2788                         line += L"> ";
2789                         line += wmessage;
2790                 }
2791         }
2792
2793         /*
2794                 Tell calling method to send the message to sender
2795         */
2796         if (!broadcast_line) {
2797                 return line;
2798         } else {
2799                 /*
2800                         Send the message to others
2801                 */
2802                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2803
2804                 std::vector<u16> clients = m_clients.getClientIDs();
2805
2806                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2807                 for (u16 i = 0; i < clients.size(); i++) {
2808                         u16 cid = clients[i];
2809                         if (cid != peer_id_to_avoid_sending)
2810                                 SendChatMessage(cid, line);
2811                 }
2812         }
2813         return L"";
2814 }
2815
2816 void Server::handleAdminChat(const ChatEventChat *evt)
2817 {
2818         std::string name = evt->nick;
2819         std::wstring wname = utf8_to_wide(name);
2820         std::wstring wmessage = evt->evt_msg;
2821
2822         std::wstring answer = handleChat(name, wname, wmessage);
2823
2824         // If asked to send answer to sender
2825         if (!answer.empty()) {
2826                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2827         }
2828 }
2829
2830 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2831 {
2832         RemoteClient *client = getClientNoEx(peer_id,state_min);
2833         if(!client)
2834                 throw ClientNotFoundException("Client not found");
2835
2836         return client;
2837 }
2838 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2839 {
2840         return m_clients.getClientNoEx(peer_id, state_min);
2841 }
2842
2843 std::string Server::getPlayerName(u16 peer_id)
2844 {
2845         Player *player = m_env->getPlayer(peer_id);
2846         if(player == NULL)
2847                 return "[id="+itos(peer_id)+"]";
2848         return player->getName();
2849 }
2850
2851 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2852 {
2853         RemotePlayer *player = m_env->getPlayer(peer_id);
2854         if (player == NULL)
2855                 return NULL;
2856         return player->getPlayerSAO();
2857 }
2858
2859 std::wstring Server::getStatusString()
2860 {
2861         std::wostringstream os(std::ios_base::binary);
2862         os<<L"# Server: ";
2863         // Version
2864         os<<L"version="<<narrow_to_wide(g_version_string);
2865         // Uptime
2866         os<<L", uptime="<<m_uptime.get();
2867         // Max lag estimate
2868         os<<L", max_lag="<<m_env->getMaxLagEstimate();
2869         // Information about clients
2870         bool first = true;
2871         os<<L", clients={";
2872         std::vector<u16> clients = m_clients.getClientIDs();
2873         for(std::vector<u16>::iterator i = clients.begin();
2874                 i != clients.end(); ++i) {
2875                 // Get player
2876                 Player *player = m_env->getPlayer(*i);
2877                 // Get name of player
2878                 std::wstring name = L"unknown";
2879                 if(player != NULL)
2880                         name = narrow_to_wide(player->getName());
2881                 // Add name to information string
2882                 if(!first)
2883                         os << L", ";
2884                 else
2885                         first = false;
2886                 os << name;
2887         }
2888         os << L"}";
2889         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
2890                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
2891         if(g_settings->get("motd") != "")
2892                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
2893         return os.str();
2894 }
2895
2896 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
2897 {
2898         std::set<std::string> privs;
2899         m_script->getAuth(name, NULL, &privs);
2900         return privs;
2901 }
2902
2903 bool Server::checkPriv(const std::string &name, const std::string &priv)
2904 {
2905         std::set<std::string> privs = getPlayerEffectivePrivs(name);
2906         return (privs.count(priv) != 0);
2907 }
2908
2909 void Server::reportPrivsModified(const std::string &name)
2910 {
2911         if(name == "") {
2912                 std::vector<u16> clients = m_clients.getClientIDs();
2913                 for(std::vector<u16>::iterator i = clients.begin();
2914                                 i != clients.end(); ++i) {
2915                         Player *player = m_env->getPlayer(*i);
2916                         reportPrivsModified(player->getName());
2917                 }
2918         } else {
2919                 RemotePlayer *player =
2920                         dynamic_cast<RemotePlayer *>(m_env->getPlayer(name.c_str()));
2921                 if (!player)
2922                         return;
2923                 SendPlayerPrivileges(player->peer_id);
2924                 PlayerSAO *sao = player->getPlayerSAO();
2925                 if(!sao)
2926                         return;
2927                 sao->updatePrivileges(
2928                                 getPlayerEffectivePrivs(name),
2929                                 isSingleplayer());
2930         }
2931 }
2932
2933 void Server::reportInventoryFormspecModified(const std::string &name)
2934 {
2935         Player *player = m_env->getPlayer(name.c_str());
2936         if(!player)
2937                 return;
2938         SendPlayerInventoryFormspec(player->peer_id);
2939 }
2940
2941 void Server::setIpBanned(const std::string &ip, const std::string &name)
2942 {
2943         m_banmanager->add(ip, name);
2944 }
2945
2946 void Server::unsetIpBanned(const std::string &ip_or_name)
2947 {
2948         m_banmanager->remove(ip_or_name);
2949 }
2950
2951 std::string Server::getBanDescription(const std::string &ip_or_name)
2952 {
2953         return m_banmanager->getBanDescription(ip_or_name);
2954 }
2955
2956 void Server::notifyPlayer(const char *name, const std::wstring &msg)
2957 {
2958         // m_env will be NULL if the server is initializing
2959         if (!m_env)
2960                 return;
2961
2962         if (m_admin_nick == name && !m_admin_nick.empty()) {
2963                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
2964         }
2965
2966         Player *player = m_env->getPlayer(name);
2967         if (!player) {
2968                 return;
2969         }
2970
2971         if (player->peer_id == PEER_ID_INEXISTENT)
2972                 return;
2973
2974         SendChatMessage(player->peer_id, msg);
2975 }
2976
2977 bool Server::showFormspec(const char *playername, const std::string &formspec,
2978         const std::string &formname)
2979 {
2980         // m_env will be NULL if the server is initializing
2981         if (!m_env)
2982                 return false;
2983
2984         Player *player = m_env->getPlayer(playername);
2985         if (!player)
2986                 return false;
2987
2988         SendShowFormspecMessage(player->peer_id, formspec, formname);
2989         return true;
2990 }
2991
2992 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
2993 {
2994         if (!player)
2995                 return -1;
2996
2997         u32 id = player->addHud(form);
2998
2999         SendHUDAdd(player->peer_id, id, form);
3000
3001         return id;
3002 }
3003
3004 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3005         if (!player)
3006                 return false;
3007
3008         HudElement* todel = player->removeHud(id);
3009
3010         if (!todel)
3011                 return false;
3012
3013         delete todel;
3014
3015         SendHUDRemove(player->peer_id, id);
3016         return true;
3017 }
3018
3019 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3020 {
3021         if (!player)
3022                 return false;
3023
3024         SendHUDChange(player->peer_id, id, stat, data);
3025         return true;
3026 }
3027
3028 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3029 {
3030         if (!player)
3031                 return false;
3032
3033         SendHUDSetFlags(player->peer_id, flags, mask);
3034         player->hud_flags &= ~mask;
3035         player->hud_flags |= flags;
3036
3037         PlayerSAO* playersao = player->getPlayerSAO();
3038
3039         if (playersao == NULL)
3040                 return false;
3041
3042         m_script->player_event(playersao, "hud_changed");
3043         return true;
3044 }
3045
3046 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3047 {
3048         if (!player)
3049                 return false;
3050
3051         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3052                 return false;
3053
3054         player->setHotbarItemcount(hotbar_itemcount);
3055         std::ostringstream os(std::ios::binary);
3056         writeS32(os, hotbar_itemcount);
3057         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3058         return true;
3059 }
3060
3061 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3062 {
3063         if (!player)
3064                 return;
3065
3066         player->setHotbarImage(name);
3067         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3068 }
3069
3070 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3071 {
3072         if (!player)
3073                 return "";
3074         return player->getHotbarImage();
3075 }
3076
3077 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3078 {
3079         if (!player)
3080                 return;
3081
3082         player->setHotbarSelectedImage(name);
3083         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3084 }
3085
3086 std::string Server::hudGetHotbarSelectedImage(RemotePlayer *player)
3087 {
3088         if (!player)
3089                 return "";
3090
3091         return player->getHotbarSelectedImage();
3092 }
3093
3094 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3095                 v2s32 animation_frames[4], f32 frame_speed)
3096 {
3097         if (!player)
3098                 return false;
3099
3100         player->setLocalAnimations(animation_frames, frame_speed);
3101         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3102         return true;
3103 }
3104
3105 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3106 {
3107         if (!player)
3108                 return false;
3109
3110         player->eye_offset_first = first;
3111         player->eye_offset_third = third;
3112         SendEyeOffset(player->peer_id, first, third);
3113         return true;
3114 }
3115
3116 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3117         const std::string &type, const std::vector<std::string> &params)
3118 {
3119         if (!player)
3120                 return false;
3121
3122         player->setSky(bgcolor, type, params);
3123         SendSetSky(player->peer_id, bgcolor, type, params);
3124         return true;
3125 }
3126
3127 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3128         float ratio)
3129 {
3130         if (!player)
3131                 return false;
3132
3133         player->overrideDayNightRatio(do_override, ratio);
3134         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3135         return true;
3136 }
3137
3138 void Server::notifyPlayers(const std::wstring &msg)
3139 {
3140         SendChatMessage(PEER_ID_INEXISTENT,msg);
3141 }
3142
3143 void Server::spawnParticle(const std::string &playername, v3f pos,
3144         v3f velocity, v3f acceleration,
3145         float expirationtime, float size, bool
3146         collisiondetection, bool collision_removal,
3147         bool vertical, const std::string &texture)
3148 {
3149         // m_env will be NULL if the server is initializing
3150         if (!m_env)
3151                 return;
3152
3153         u16 peer_id = PEER_ID_INEXISTENT;
3154         if (playername != "") {
3155                 Player* player = m_env->getPlayer(playername.c_str());
3156                 if (!player)
3157                         return;
3158                 peer_id = player->peer_id;
3159         }
3160
3161         SendSpawnParticle(peer_id, pos, velocity, acceleration,
3162                         expirationtime, size, collisiondetection,
3163                         collision_removal, vertical, texture);
3164 }
3165
3166 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3167         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3168         float minexptime, float maxexptime, float minsize, float maxsize,
3169         bool collisiondetection, bool collision_removal,
3170         bool vertical, const std::string &texture,
3171         const std::string &playername)
3172 {
3173         // m_env will be NULL if the server is initializing
3174         if (!m_env)
3175                 return -1;
3176
3177         u16 peer_id = PEER_ID_INEXISTENT;
3178         if (playername != "") {
3179                 Player* player = m_env->getPlayer(playername.c_str());
3180                 if (!player)
3181                         return -1;
3182                 peer_id = player->peer_id;
3183         }
3184
3185         u32 id = m_env->addParticleSpawner(spawntime);
3186         SendAddParticleSpawner(peer_id, amount, spawntime,
3187                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3188                 minexptime, maxexptime, minsize, maxsize,
3189                 collisiondetection, collision_removal, vertical, texture, id);
3190
3191         return id;
3192 }
3193
3194 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3195 {
3196         // m_env will be NULL if the server is initializing
3197         if (!m_env)
3198                 throw ServerError("Can't delete particle spawners during initialisation!");
3199
3200         u16 peer_id = PEER_ID_INEXISTENT;
3201         if (playername != "") {
3202                 Player* player = m_env->getPlayer(playername.c_str());
3203                 if (!player)
3204                         return;
3205                 peer_id = player->peer_id;
3206         }
3207
3208         m_env->deleteParticleSpawner(id);
3209         SendDeleteParticleSpawner(peer_id, id);
3210 }
3211
3212 Inventory* Server::createDetachedInventory(const std::string &name)
3213 {
3214         if(m_detached_inventories.count(name) > 0){
3215                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3216                 delete m_detached_inventories[name];
3217         } else {
3218                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3219         }
3220         Inventory *inv = new Inventory(m_itemdef);
3221         sanity_check(inv);
3222         m_detached_inventories[name] = inv;
3223         //TODO find a better way to do this
3224         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3225         return inv;
3226 }
3227
3228 // actions: time-reversed list
3229 // Return value: success/failure
3230 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3231                 std::list<std::string> *log)
3232 {
3233         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3234         ServerMap *map = (ServerMap*)(&m_env->getMap());
3235
3236         // Fail if no actions to handle
3237         if(actions.empty()){
3238                 log->push_back("Nothing to do.");
3239                 return false;
3240         }
3241
3242         int num_tried = 0;
3243         int num_failed = 0;
3244
3245         for(std::list<RollbackAction>::const_iterator
3246                         i = actions.begin();
3247                         i != actions.end(); ++i)
3248         {
3249                 const RollbackAction &action = *i;
3250                 num_tried++;
3251                 bool success = action.applyRevert(map, this, this);
3252                 if(!success){
3253                         num_failed++;
3254                         std::ostringstream os;
3255                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3256                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3257                         if(log)
3258                                 log->push_back(os.str());
3259                 }else{
3260                         std::ostringstream os;
3261                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3262                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3263                         if(log)
3264                                 log->push_back(os.str());
3265                 }
3266         }
3267
3268         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3269                         <<" failed"<<std::endl;
3270
3271         // Call it done if less than half failed
3272         return num_failed <= num_tried/2;
3273 }
3274
3275 // IGameDef interface
3276 // Under envlock
3277 IItemDefManager *Server::getItemDefManager()
3278 {
3279         return m_itemdef;
3280 }
3281
3282 INodeDefManager *Server::getNodeDefManager()
3283 {
3284         return m_nodedef;
3285 }
3286
3287 ICraftDefManager *Server::getCraftDefManager()
3288 {
3289         return m_craftdef;
3290 }
3291 ITextureSource *Server::getTextureSource()
3292 {
3293         return NULL;
3294 }
3295 IShaderSource *Server::getShaderSource()
3296 {
3297         return NULL;
3298 }
3299 scene::ISceneManager *Server::getSceneManager()
3300 {
3301         return NULL;
3302 }
3303
3304 u16 Server::allocateUnknownNodeId(const std::string &name)
3305 {
3306         return m_nodedef->allocateDummy(name);
3307 }
3308
3309 ISoundManager *Server::getSoundManager()
3310 {
3311         return &dummySoundManager;
3312 }
3313
3314 MtEventManager *Server::getEventManager()
3315 {
3316         return m_event;
3317 }
3318
3319 IWritableItemDefManager *Server::getWritableItemDefManager()
3320 {
3321         return m_itemdef;
3322 }
3323
3324 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3325 {
3326         return m_nodedef;
3327 }
3328
3329 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3330 {
3331         return m_craftdef;
3332 }
3333
3334 const ModSpec *Server::getModSpec(const std::string &modname) const
3335 {
3336         std::vector<ModSpec>::const_iterator it;
3337         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3338                 const ModSpec &mod = *it;
3339                 if (mod.name == modname)
3340                         return &mod;
3341         }
3342         return NULL;
3343 }
3344
3345 void Server::getModNames(std::vector<std::string> &modlist)
3346 {
3347         std::vector<ModSpec>::iterator it;
3348         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3349                 modlist.push_back(it->name);
3350 }
3351
3352 std::string Server::getBuiltinLuaPath()
3353 {
3354         return porting::path_share + DIR_DELIM + "builtin";
3355 }
3356
3357 v3f Server::findSpawnPos()
3358 {
3359         ServerMap &map = m_env->getServerMap();
3360         v3f nodeposf;
3361         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3362                 return nodeposf * BS;
3363         }
3364
3365         bool is_good = false;
3366
3367         // Try to find a good place a few times
3368         for(s32 i = 0; i < 4000 && !is_good; i++) {
3369                 s32 range = 1 + i;
3370                 // We're going to try to throw the player to this position
3371                 v2s16 nodepos2d = v2s16(
3372                                 -range + (myrand() % (range * 2)),
3373                                 -range + (myrand() % (range * 2)));
3374
3375                 // Get spawn level at point
3376                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3377                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3378                 // the mapgen to signify an unsuitable spawn position
3379                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3380                         continue;
3381
3382                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3383
3384                 s32 air_count = 0;
3385                 for (s32 i = 0; i < 10; i++) {
3386                         v3s16 blockpos = getNodeBlockPos(nodepos);
3387                         map.emergeBlock(blockpos, true);
3388                         content_t c = map.getNodeNoEx(nodepos).getContent();
3389                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3390                                 air_count++;
3391                                 if (air_count >= 2) {
3392                                         nodeposf = intToFloat(nodepos, BS);
3393                                         // Don't spawn the player outside map boundaries
3394                                         if (objectpos_over_limit(nodeposf))
3395                                                 continue;
3396                                         is_good = true;
3397                                         break;
3398                                 }
3399                         }
3400                         nodepos.Y++;
3401                 }
3402         }
3403
3404         return nodeposf;
3405 }
3406
3407 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3408 {
3409         bool newplayer = false;
3410
3411         /*
3412                 Try to get an existing player
3413         */
3414         RemotePlayer *player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
3415
3416         // If player is already connected, cancel
3417         if(player != NULL && player->peer_id != 0)
3418         {
3419                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3420                 return NULL;
3421         }
3422
3423         /*
3424                 If player with the wanted peer_id already exists, cancel.
3425         */
3426         if(m_env->getPlayer(peer_id) != NULL)
3427         {
3428                 infostream<<"emergePlayer(): Player with wrong name but same"
3429                                 " peer_id already exists"<<std::endl;
3430                 return NULL;
3431         }
3432
3433         // Load player if it isn't already loaded
3434         if (!player) {
3435                 player = static_cast<RemotePlayer*>(m_env->loadPlayer(name));
3436         }
3437
3438         // Create player if it doesn't exist
3439         if (!player) {
3440                 newplayer = true;
3441                 player = new RemotePlayer(this, name);
3442                 // Set player position
3443                 infostream<<"Server: Finding spawn place for player \""
3444                                 <<name<<"\""<<std::endl;
3445                 v3f pos = findSpawnPos();
3446                 player->setPosition(pos);
3447
3448                 // Make sure the player is saved
3449                 player->setModified(true);
3450
3451                 // Add player to environment
3452                 m_env->addPlayer(player);
3453         } else {
3454                 // If the player exists, ensure that they respawn inside legal bounds
3455                 // This fixes an assert crash when the player can't be added
3456                 // to the environment
3457                 if (objectpos_over_limit(player->getPosition())) {
3458                         actionstream << "Respawn position for player \""
3459                                 << name << "\" outside limits, resetting" << std::endl;
3460                         v3f pos = findSpawnPos();
3461                         player->setPosition(pos);
3462                 }
3463         }
3464
3465         // Create a new player active object
3466         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
3467                         getPlayerEffectivePrivs(player->getName()),
3468                         isSingleplayer());
3469
3470         player->protocol_version = proto_version;
3471
3472         /* Clean up old HUD elements from previous sessions */
3473         player->clearHud();
3474
3475         /* Add object to environment */
3476         m_env->addActiveObject(playersao);
3477
3478         /* Run scripts */
3479         if (newplayer) {
3480                 m_script->on_newplayer(playersao);
3481         }
3482
3483         return playersao;
3484 }
3485
3486 void dedicated_server_loop(Server &server, bool &kill)
3487 {
3488         DSTACK(FUNCTION_NAME);
3489
3490         verbosestream<<"dedicated_server_loop()"<<std::endl;
3491
3492         IntervalLimiter m_profiler_interval;
3493
3494         static const float steplen = g_settings->getFloat("dedicated_server_step");
3495         static const float profiler_print_interval =
3496                         g_settings->getFloat("profiler_print_interval");
3497
3498         for(;;) {
3499                 // This is kind of a hack but can be done like this
3500                 // because server.step() is very light
3501                 {
3502                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3503                         sleep_ms((int)(steplen*1000.0));
3504                 }
3505                 server.step(steplen);
3506
3507                 if(server.getShutdownRequested() || kill)
3508                 {
3509                         infostream<<"Dedicated server quitting"<<std::endl;
3510 #if USE_CURL
3511                         if(g_settings->getBool("server_announce"))
3512                                 ServerList::sendAnnounce("delete", server.m_bind_addr.getPort());
3513 #endif
3514                         break;
3515                 }
3516
3517                 /*
3518                         Profiler
3519                 */
3520                 if (profiler_print_interval != 0) {
3521                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3522                         {
3523                                 infostream<<"Profiler:"<<std::endl;
3524                                 g_profiler->print(infostream);
3525                                 g_profiler->clear();
3526                         }
3527                 }
3528         }
3529 }