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