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