]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Add function to get server info.
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "threading/mutex_auto_lock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_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                 bool &clouds)
1876 {
1877         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1878         pkt << bgcolor << type << (u16) params.size();
1879
1880         for(size_t i=0; i<params.size(); i++)
1881                 pkt << params[i];
1882
1883         pkt << clouds;
1884
1885         Send(&pkt);
1886 }
1887
1888 void Server::SendCloudParams(u16 peer_id, float density,
1889                 const video::SColor &color_bright,
1890                 const video::SColor &color_ambient,
1891                 float height,
1892                 float thickness,
1893                 const v2f &speed)
1894 {
1895         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1896         pkt << density << color_bright << color_ambient
1897                         << height << thickness << speed;
1898
1899         Send(&pkt);
1900 }
1901
1902 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1903                 float ratio)
1904 {
1905         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1906                         1 + 2, peer_id);
1907
1908         pkt << do_override << (u16) (ratio * 65535);
1909
1910         Send(&pkt);
1911 }
1912
1913 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1914 {
1915         DSTACK(FUNCTION_NAME);
1916
1917         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1918         pkt << time << time_speed;
1919
1920         if (peer_id == PEER_ID_INEXISTENT) {
1921                 m_clients.sendToAll(&pkt);
1922         }
1923         else {
1924                 Send(&pkt);
1925         }
1926 }
1927
1928 void Server::SendPlayerHP(u16 peer_id)
1929 {
1930         DSTACK(FUNCTION_NAME);
1931         PlayerSAO *playersao = getPlayerSAO(peer_id);
1932         // In some rare case if the player is disconnected
1933         // while Lua call l_punch, for example, this can be NULL
1934         if (!playersao)
1935                 return;
1936
1937         SendHP(peer_id, playersao->getHP());
1938         m_script->player_event(playersao,"health_changed");
1939
1940         // Send to other clients
1941         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1942         ActiveObjectMessage aom(playersao->getId(), true, str);
1943         playersao->m_messages_out.push(aom);
1944 }
1945
1946 void Server::SendPlayerBreath(PlayerSAO *sao)
1947 {
1948         DSTACK(FUNCTION_NAME);
1949         assert(sao);
1950
1951         m_script->player_event(sao, "breath_changed");
1952         SendBreath(sao->getPeerID(), sao->getBreath());
1953 }
1954
1955 void Server::SendMovePlayer(u16 peer_id)
1956 {
1957         DSTACK(FUNCTION_NAME);
1958         RemotePlayer *player = m_env->getPlayer(peer_id);
1959         assert(player);
1960         PlayerSAO *sao = player->getPlayerSAO();
1961         assert(sao);
1962
1963         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1964         pkt << sao->getBasePosition() << sao->getPitch() << sao->getYaw();
1965
1966         {
1967                 v3f pos = sao->getBasePosition();
1968                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1969                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1970                                 << " pitch=" << sao->getPitch()
1971                                 << " yaw=" << sao->getYaw()
1972                                 << std::endl;
1973         }
1974
1975         Send(&pkt);
1976 }
1977
1978 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1979 {
1980         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1981                 peer_id);
1982
1983         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1984                         << animation_frames[3] << animation_speed;
1985
1986         Send(&pkt);
1987 }
1988
1989 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1990 {
1991         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1992         pkt << first << third;
1993         Send(&pkt);
1994 }
1995 void Server::SendPlayerPrivileges(u16 peer_id)
1996 {
1997         RemotePlayer *player = m_env->getPlayer(peer_id);
1998         assert(player);
1999         if(player->peer_id == PEER_ID_INEXISTENT)
2000                 return;
2001
2002         std::set<std::string> privs;
2003         m_script->getAuth(player->getName(), NULL, &privs);
2004
2005         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
2006         pkt << (u16) privs.size();
2007
2008         for(std::set<std::string>::const_iterator i = privs.begin();
2009                         i != privs.end(); ++i) {
2010                 pkt << (*i);
2011         }
2012
2013         Send(&pkt);
2014 }
2015
2016 void Server::SendPlayerInventoryFormspec(u16 peer_id)
2017 {
2018         RemotePlayer *player = m_env->getPlayer(peer_id);
2019         assert(player);
2020         if(player->peer_id == PEER_ID_INEXISTENT)
2021                 return;
2022
2023         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
2024         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
2025         Send(&pkt);
2026 }
2027
2028 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
2029 {
2030         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
2031         pkt.putRawString(datas.c_str(), datas.size());
2032         Send(&pkt);
2033         return pkt.getSize();
2034 }
2035
2036 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
2037 {
2038         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
2039                         datas.size(), peer_id);
2040
2041         pkt.putRawString(datas.c_str(), datas.size());
2042
2043         m_clients.send(pkt.getPeerId(),
2044                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
2045                         &pkt, reliable);
2046
2047 }
2048
2049 s32 Server::playSound(const SimpleSoundSpec &spec,
2050                 const ServerSoundParams &params)
2051 {
2052         // Find out initial position of sound
2053         bool pos_exists = false;
2054         v3f pos = params.getPos(m_env, &pos_exists);
2055         // If position is not found while it should be, cancel sound
2056         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
2057                 return -1;
2058
2059         // Filter destination clients
2060         std::vector<u16> dst_clients;
2061         if(params.to_player != "")
2062         {
2063                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
2064                 if(!player){
2065                         infostream<<"Server::playSound: Player \""<<params.to_player
2066                                         <<"\" not found"<<std::endl;
2067                         return -1;
2068                 }
2069                 if(player->peer_id == PEER_ID_INEXISTENT){
2070                         infostream<<"Server::playSound: Player \""<<params.to_player
2071                                         <<"\" not connected"<<std::endl;
2072                         return -1;
2073                 }
2074                 dst_clients.push_back(player->peer_id);
2075         }
2076         else {
2077                 std::vector<u16> clients = m_clients.getClientIDs();
2078
2079                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2080                         RemotePlayer *player = m_env->getPlayer(*i);
2081                         if (!player)
2082                                 continue;
2083
2084                         PlayerSAO *sao = player->getPlayerSAO();
2085                         if (!sao)
2086                                 continue;
2087
2088                         if (pos_exists) {
2089                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2090                                                 params.max_hear_distance)
2091                                         continue;
2092                         }
2093                         dst_clients.push_back(*i);
2094                 }
2095         }
2096
2097         if(dst_clients.empty())
2098                 return -1;
2099
2100         // Create the sound
2101         s32 id = m_next_sound_id++;
2102         // The sound will exist as a reference in m_playing_sounds
2103         m_playing_sounds[id] = ServerPlayingSound();
2104         ServerPlayingSound &psound = m_playing_sounds[id];
2105         psound.params = params;
2106         psound.spec = spec;
2107
2108         float gain = params.gain * spec.gain;
2109         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2110         pkt << id << spec.name << gain
2111                         << (u8) params.type << pos << params.object
2112                         << params.loop << params.fade;
2113
2114         // Backwards compability
2115         bool play_sound = gain > 0;
2116
2117         for (std::vector<u16>::iterator i = dst_clients.begin();
2118                         i != dst_clients.end(); ++i) {
2119                 if (play_sound || m_clients.getProtocolVersion(*i) >= 32) {
2120                         psound.clients.insert(*i);
2121                         m_clients.send(*i, 0, &pkt, true);
2122                 }
2123         }
2124         return id;
2125 }
2126 void Server::stopSound(s32 handle)
2127 {
2128         // Get sound reference
2129         UNORDERED_MAP<s32, ServerPlayingSound>::iterator i = m_playing_sounds.find(handle);
2130         if (i == m_playing_sounds.end())
2131                 return;
2132         ServerPlayingSound &psound = i->second;
2133
2134         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2135         pkt << handle;
2136
2137         for (UNORDERED_SET<u16>::iterator i = psound.clients.begin();
2138                         i != psound.clients.end(); ++i) {
2139                 // Send as reliable
2140                 m_clients.send(*i, 0, &pkt, true);
2141         }
2142         // Remove sound reference
2143         m_playing_sounds.erase(i);
2144 }
2145
2146 void Server::fadeSound(s32 handle, float step, float gain)
2147 {
2148         // Get sound reference
2149         UNORDERED_MAP<s32, ServerPlayingSound>::iterator i =
2150                         m_playing_sounds.find(handle);
2151         if (i == m_playing_sounds.end())
2152                 return;
2153
2154         ServerPlayingSound &psound = i->second;
2155         psound.params.gain = gain;
2156
2157         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2158         pkt << handle << step << gain;
2159
2160         // Backwards compability
2161         bool play_sound = gain > 0;
2162         ServerPlayingSound compat_psound = psound;
2163         compat_psound.clients.clear();
2164
2165         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2166         compat_pkt << handle;
2167
2168         for (UNORDERED_SET<u16>::iterator it = psound.clients.begin();
2169                         it != psound.clients.end();) {
2170                 if (m_clients.getProtocolVersion(*it) >= 32) {
2171                         // Send as reliable
2172                         m_clients.send(*it, 0, &pkt, true);
2173                         ++it;
2174                 } else {
2175                         compat_psound.clients.insert(*it);
2176                         // Stop old sound
2177                         m_clients.send(*it, 0, &compat_pkt, true);
2178                         psound.clients.erase(it++);
2179                 }
2180         }
2181
2182         // Remove sound reference
2183         if (!play_sound || psound.clients.size() == 0)
2184                 m_playing_sounds.erase(i);
2185
2186         if (play_sound && compat_psound.clients.size() > 0) {
2187                 // Play new sound volume on older clients
2188                 playSound(compat_psound.spec, compat_psound.params);
2189         }
2190 }
2191
2192 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2193         std::vector<u16> *far_players, float far_d_nodes)
2194 {
2195         float maxd = far_d_nodes*BS;
2196         v3f p_f = intToFloat(p, BS);
2197
2198         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2199         pkt << p;
2200
2201         std::vector<u16> clients = m_clients.getClientIDs();
2202         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2203                 if (far_players) {
2204                         // Get player
2205                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2206                                 PlayerSAO *sao = player->getPlayerSAO();
2207                                 if (!sao)
2208                                         continue;
2209
2210                                 // If player is far away, only set modified blocks not sent
2211                                 v3f player_pos = sao->getBasePosition();
2212                                 if (player_pos.getDistanceFrom(p_f) > maxd) {
2213                                         far_players->push_back(*i);
2214                                         continue;
2215                                 }
2216                         }
2217                 }
2218
2219                 // Send as reliable
2220                 m_clients.send(*i, 0, &pkt, true);
2221         }
2222 }
2223
2224 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2225                 std::vector<u16> *far_players, float far_d_nodes,
2226                 bool remove_metadata)
2227 {
2228         float maxd = far_d_nodes*BS;
2229         v3f p_f = intToFloat(p, BS);
2230
2231         std::vector<u16> clients = m_clients.getClientIDs();
2232         for(std::vector<u16>::iterator i = clients.begin();     i != clients.end(); ++i) {
2233                 if (far_players) {
2234                         // Get player
2235                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2236                                 PlayerSAO *sao = player->getPlayerSAO();
2237                                 if (!sao)
2238                                         continue;
2239
2240                                 // If player is far away, only set modified blocks not sent
2241                                 v3f player_pos = sao->getBasePosition();
2242                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2243                                         far_players->push_back(*i);
2244                                         continue;
2245                                 }
2246                         }
2247                 }
2248
2249                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2250                 m_clients.lock();
2251                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2252                 if (client != 0) {
2253                         pkt << p << n.param0 << n.param1 << n.param2
2254                                         << (u8) (remove_metadata ? 0 : 1);
2255                 }
2256                 m_clients.unlock();
2257
2258                 // Send as reliable
2259                 if (pkt.getSize() > 0)
2260                         m_clients.send(*i, 0, &pkt, true);
2261         }
2262 }
2263
2264 void Server::setBlockNotSent(v3s16 p)
2265 {
2266         std::vector<u16> clients = m_clients.getClientIDs();
2267         m_clients.lock();
2268         for(std::vector<u16>::iterator i = clients.begin();
2269                 i != clients.end(); ++i) {
2270                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2271                 client->SetBlockNotSent(p);
2272         }
2273         m_clients.unlock();
2274 }
2275
2276 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2277 {
2278         DSTACK(FUNCTION_NAME);
2279
2280         v3s16 p = block->getPos();
2281
2282         /*
2283                 Create a packet with the block in the right format
2284         */
2285
2286         std::ostringstream os(std::ios_base::binary);
2287         block->serialize(os, ver, false);
2288         block->serializeNetworkSpecific(os);
2289         std::string s = os.str();
2290
2291         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2292
2293         pkt << p;
2294         pkt.putRawString(s.c_str(), s.size());
2295         Send(&pkt);
2296 }
2297
2298 void Server::SendBlocks(float dtime)
2299 {
2300         DSTACK(FUNCTION_NAME);
2301
2302         MutexAutoLock envlock(m_env_mutex);
2303         //TODO check if one big lock could be faster then multiple small ones
2304
2305         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2306
2307         std::vector<PrioritySortedBlockTransfer> queue;
2308
2309         s32 total_sending = 0;
2310
2311         {
2312                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2313
2314                 std::vector<u16> clients = m_clients.getClientIDs();
2315
2316                 m_clients.lock();
2317                 for(std::vector<u16>::iterator i = clients.begin();
2318                         i != clients.end(); ++i) {
2319                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2320
2321                         if (client == NULL)
2322                                 continue;
2323
2324                         total_sending += client->SendingCount();
2325                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2326                 }
2327                 m_clients.unlock();
2328         }
2329
2330         // Sort.
2331         // Lowest priority number comes first.
2332         // Lowest is most important.
2333         std::sort(queue.begin(), queue.end());
2334
2335         m_clients.lock();
2336         for(u32 i=0; i<queue.size(); i++)
2337         {
2338                 //TODO: Calculate limit dynamically
2339                 if(total_sending >= g_settings->getS32
2340                                 ("max_simultaneous_block_sends_server_total"))
2341                         break;
2342
2343                 PrioritySortedBlockTransfer q = queue[i];
2344
2345                 MapBlock *block = NULL;
2346                 try
2347                 {
2348                         block = m_env->getMap().getBlockNoCreate(q.pos);
2349                 }
2350                 catch(InvalidPositionException &e)
2351                 {
2352                         continue;
2353                 }
2354
2355                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2356
2357                 if(!client)
2358                         continue;
2359
2360                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2361
2362                 client->SentBlock(q.pos);
2363                 total_sending++;
2364         }
2365         m_clients.unlock();
2366 }
2367
2368 void Server::fillMediaCache()
2369 {
2370         DSTACK(FUNCTION_NAME);
2371
2372         infostream<<"Server: Calculating media file checksums"<<std::endl;
2373
2374         // Collect all media file paths
2375         std::vector<std::string> paths;
2376         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2377                         i != m_mods.end(); ++i) {
2378                 const ModSpec &mod = *i;
2379                 paths.push_back(mod.path + DIR_DELIM + "textures");
2380                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2381                 paths.push_back(mod.path + DIR_DELIM + "media");
2382                 paths.push_back(mod.path + DIR_DELIM + "models");
2383         }
2384         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2385
2386         // Collect media file information from paths into cache
2387         for(std::vector<std::string>::iterator i = paths.begin();
2388                         i != paths.end(); ++i) {
2389                 std::string mediapath = *i;
2390                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2391                 for (u32 j = 0; j < dirlist.size(); j++) {
2392                         if (dirlist[j].dir) // Ignode dirs
2393                                 continue;
2394                         std::string filename = dirlist[j].name;
2395                         // If name contains illegal characters, ignore the file
2396                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2397                                 infostream<<"Server: ignoring illegal file name: \""
2398                                                 << filename << "\"" << std::endl;
2399                                 continue;
2400                         }
2401                         // If name is not in a supported format, ignore it
2402                         const char *supported_ext[] = {
2403                                 ".png", ".jpg", ".bmp", ".tga",
2404                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2405                                 ".ogg",
2406                                 ".x", ".b3d", ".md2", ".obj",
2407                                 NULL
2408                         };
2409                         if (removeStringEnd(filename, supported_ext) == ""){
2410                                 infostream << "Server: ignoring unsupported file extension: \""
2411                                                 << filename << "\"" << std::endl;
2412                                 continue;
2413                         }
2414                         // Ok, attempt to load the file and add to cache
2415                         std::string filepath = mediapath + DIR_DELIM + filename;
2416                         // Read data
2417                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2418                         if (!fis.good()) {
2419                                 errorstream << "Server::fillMediaCache(): Could not open \""
2420                                                 << filename << "\" for reading" << std::endl;
2421                                 continue;
2422                         }
2423                         std::ostringstream tmp_os(std::ios_base::binary);
2424                         bool bad = false;
2425                         for(;;) {
2426                                 char buf[1024];
2427                                 fis.read(buf, 1024);
2428                                 std::streamsize len = fis.gcount();
2429                                 tmp_os.write(buf, len);
2430                                 if (fis.eof())
2431                                         break;
2432                                 if (!fis.good()) {
2433                                         bad = true;
2434                                         break;
2435                                 }
2436                         }
2437                         if(bad) {
2438                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2439                                                 << filename << "\"" << std::endl;
2440                                 continue;
2441                         }
2442                         if(tmp_os.str().length() == 0) {
2443                                 errorstream << "Server::fillMediaCache(): Empty file \""
2444                                                 << filepath << "\"" << std::endl;
2445                                 continue;
2446                         }
2447
2448                         SHA1 sha1;
2449                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2450
2451                         unsigned char *digest = sha1.getDigest();
2452                         std::string sha1_base64 = base64_encode(digest, 20);
2453                         std::string sha1_hex = hex_encode((char*)digest, 20);
2454                         free(digest);
2455
2456                         // Put in list
2457                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2458                         verbosestream << "Server: " << sha1_hex << " is " << filename
2459                                         << std::endl;
2460                 }
2461         }
2462 }
2463
2464 void Server::sendMediaAnnouncement(u16 peer_id)
2465 {
2466         DSTACK(FUNCTION_NAME);
2467
2468         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2469                 << std::endl;
2470
2471         // Make packet
2472         std::ostringstream os(std::ios_base::binary);
2473
2474         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2475         pkt << (u16) m_media.size();
2476
2477         for (UNORDERED_MAP<std::string, MediaInfo>::iterator i = m_media.begin();
2478                         i != m_media.end(); ++i) {
2479                 pkt << i->first << i->second.sha1_digest;
2480         }
2481
2482         pkt << g_settings->get("remote_media");
2483         Send(&pkt);
2484 }
2485
2486 struct SendableMedia
2487 {
2488         std::string name;
2489         std::string path;
2490         std::string data;
2491
2492         SendableMedia(const std::string &name_="", const std::string &path_="",
2493                       const std::string &data_=""):
2494                 name(name_),
2495                 path(path_),
2496                 data(data_)
2497         {}
2498 };
2499
2500 void Server::sendRequestedMedia(u16 peer_id,
2501                 const std::vector<std::string> &tosend)
2502 {
2503         DSTACK(FUNCTION_NAME);
2504
2505         verbosestream<<"Server::sendRequestedMedia(): "
2506                         <<"Sending files to client"<<std::endl;
2507
2508         /* Read files */
2509
2510         // Put 5kB in one bunch (this is not accurate)
2511         u32 bytes_per_bunch = 5000;
2512
2513         std::vector< std::vector<SendableMedia> > file_bunches;
2514         file_bunches.push_back(std::vector<SendableMedia>());
2515
2516         u32 file_size_bunch_total = 0;
2517
2518         for(std::vector<std::string>::const_iterator i = tosend.begin();
2519                         i != tosend.end(); ++i) {
2520                 const std::string &name = *i;
2521
2522                 if (m_media.find(name) == m_media.end()) {
2523                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2524                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2525                         continue;
2526                 }
2527
2528                 //TODO get path + name
2529                 std::string tpath = m_media[name].path;
2530
2531                 // Read data
2532                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2533                 if(fis.good() == false){
2534                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2535                                         <<tpath<<"\" for reading"<<std::endl;
2536                         continue;
2537                 }
2538                 std::ostringstream tmp_os(std::ios_base::binary);
2539                 bool bad = false;
2540                 for(;;) {
2541                         char buf[1024];
2542                         fis.read(buf, 1024);
2543                         std::streamsize len = fis.gcount();
2544                         tmp_os.write(buf, len);
2545                         file_size_bunch_total += len;
2546                         if(fis.eof())
2547                                 break;
2548                         if(!fis.good()) {
2549                                 bad = true;
2550                                 break;
2551                         }
2552                 }
2553                 if(bad) {
2554                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2555                                         <<name<<"\""<<std::endl;
2556                         continue;
2557                 }
2558                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2559                                 <<tname<<"\""<<std::endl;*/
2560                 // Put in list
2561                 file_bunches[file_bunches.size()-1].push_back(
2562                                 SendableMedia(name, tpath, tmp_os.str()));
2563
2564                 // Start next bunch if got enough data
2565                 if(file_size_bunch_total >= bytes_per_bunch) {
2566                         file_bunches.push_back(std::vector<SendableMedia>());
2567                         file_size_bunch_total = 0;
2568                 }
2569
2570         }
2571
2572         /* Create and send packets */
2573
2574         u16 num_bunches = file_bunches.size();
2575         for(u16 i = 0; i < num_bunches; i++) {
2576                 /*
2577                         u16 command
2578                         u16 total number of texture bunches
2579                         u16 index of this bunch
2580                         u32 number of files in this bunch
2581                         for each file {
2582                                 u16 length of name
2583                                 string name
2584                                 u32 length of data
2585                                 data
2586                         }
2587                 */
2588
2589                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2590                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2591
2592                 for(std::vector<SendableMedia>::iterator
2593                                 j = file_bunches[i].begin();
2594                                 j != file_bunches[i].end(); ++j) {
2595                         pkt << j->name;
2596                         pkt.putLongString(j->data);
2597                 }
2598
2599                 verbosestream << "Server::sendRequestedMedia(): bunch "
2600                                 << i << "/" << num_bunches
2601                                 << " files=" << file_bunches[i].size()
2602                                 << " size="  << pkt.getSize() << std::endl;
2603                 Send(&pkt);
2604         }
2605 }
2606
2607 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2608 {
2609         if(m_detached_inventories.count(name) == 0) {
2610                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2611                 return;
2612         }
2613         Inventory *inv = m_detached_inventories[name];
2614         std::ostringstream os(std::ios_base::binary);
2615
2616         os << serializeString(name);
2617         inv->serialize(os);
2618
2619         // Make data buffer
2620         std::string s = os.str();
2621
2622         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2623         pkt.putRawString(s.c_str(), s.size());
2624
2625         const std::string &check = m_detached_inventories_player[name];
2626         if (peer_id == PEER_ID_INEXISTENT) {
2627                 if (check == "")
2628                         return m_clients.sendToAll(&pkt);
2629                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2630                 if (p)
2631                         m_clients.send(p->peer_id, 0, &pkt, true);
2632         } else {
2633                 if (check == "" || getPlayerName(peer_id) == check)
2634                         Send(&pkt);
2635         }
2636 }
2637
2638 void Server::sendDetachedInventories(u16 peer_id)
2639 {
2640         DSTACK(FUNCTION_NAME);
2641
2642         for(std::map<std::string, Inventory*>::iterator
2643                         i = m_detached_inventories.begin();
2644                         i != m_detached_inventories.end(); ++i) {
2645                 const std::string &name = i->first;
2646                 //Inventory *inv = i->second;
2647                 sendDetachedInventory(name, peer_id);
2648         }
2649 }
2650
2651 /*
2652         Something random
2653 */
2654
2655 void Server::DiePlayer(u16 peer_id)
2656 {
2657         DSTACK(FUNCTION_NAME);
2658         PlayerSAO *playersao = getPlayerSAO(peer_id);
2659         // In some rare cases this can be NULL -- if the player is disconnected
2660         // when a Lua function modifies l_punch, for example
2661         if (!playersao)
2662                 return;
2663
2664         infostream << "Server::DiePlayer(): Player "
2665                         << playersao->getPlayer()->getName()
2666                         << " dies" << std::endl;
2667
2668         playersao->setHP(0);
2669
2670         // Trigger scripted stuff
2671         m_script->on_dieplayer(playersao);
2672
2673         SendPlayerHP(peer_id);
2674         SendDeathscreen(peer_id, false, v3f(0,0,0));
2675 }
2676
2677 void Server::RespawnPlayer(u16 peer_id)
2678 {
2679         DSTACK(FUNCTION_NAME);
2680
2681         PlayerSAO *playersao = getPlayerSAO(peer_id);
2682         assert(playersao);
2683
2684         infostream << "Server::RespawnPlayer(): Player "
2685                         << playersao->getPlayer()->getName()
2686                         << " respawns" << std::endl;
2687
2688         playersao->setHP(PLAYER_MAX_HP);
2689         playersao->setBreath(PLAYER_MAX_BREATH);
2690
2691         bool repositioned = m_script->on_respawnplayer(playersao);
2692         if (!repositioned) {
2693                 // setPos will send the new position to client
2694                 playersao->setPos(findSpawnPos());
2695         }
2696
2697         SendPlayerHP(peer_id);
2698 }
2699
2700
2701 void Server::DenySudoAccess(u16 peer_id)
2702 {
2703         DSTACK(FUNCTION_NAME);
2704
2705         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2706         Send(&pkt);
2707 }
2708
2709
2710 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2711                 const std::string &str_reason, bool reconnect)
2712 {
2713         if (proto_ver >= 25) {
2714                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2715         } else {
2716                 std::wstring wreason = utf8_to_wide(
2717                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2718                         accessDeniedStrings[(u8)reason]);
2719                 SendAccessDenied_Legacy(peer_id, wreason);
2720         }
2721
2722         m_clients.event(peer_id, CSE_SetDenied);
2723         m_con.DisconnectPeer(peer_id);
2724 }
2725
2726
2727 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2728 {
2729         DSTACK(FUNCTION_NAME);
2730
2731         SendAccessDenied(peer_id, reason, custom_reason);
2732         m_clients.event(peer_id, CSE_SetDenied);
2733         m_con.DisconnectPeer(peer_id);
2734 }
2735
2736 // 13/03/15: remove this function when protocol version 25 will become
2737 // the minimum version for MT users, maybe in 1 year
2738 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2739 {
2740         DSTACK(FUNCTION_NAME);
2741
2742         SendAccessDenied_Legacy(peer_id, reason);
2743         m_clients.event(peer_id, CSE_SetDenied);
2744         m_con.DisconnectPeer(peer_id);
2745 }
2746
2747 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2748 {
2749         DSTACK(FUNCTION_NAME);
2750
2751         if (!forSudoMode) {
2752                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2753
2754                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2755
2756                 // Right now, the auth mechs don't change between login and sudo mode.
2757                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2758                 client->allowed_sudo_mechs = sudo_auth_mechs;
2759
2760                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2761                                 << g_settings->getFloat("dedicated_server_step")
2762                                 << sudo_auth_mechs;
2763
2764                 Send(&resp_pkt);
2765                 m_clients.event(peer_id, CSE_AuthAccept);
2766         } else {
2767                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2768
2769                 // We only support SRP right now
2770                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2771
2772                 resp_pkt << sudo_auth_mechs;
2773                 Send(&resp_pkt);
2774                 m_clients.event(peer_id, CSE_SudoSuccess);
2775         }
2776 }
2777
2778 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2779 {
2780         DSTACK(FUNCTION_NAME);
2781         std::wstring message;
2782         {
2783                 /*
2784                         Clear references to playing sounds
2785                 */
2786                 for (UNORDERED_MAP<s32, ServerPlayingSound>::iterator
2787                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2788                         ServerPlayingSound &psound = i->second;
2789                         psound.clients.erase(peer_id);
2790                         if (psound.clients.empty())
2791                                 m_playing_sounds.erase(i++);
2792                         else
2793                                 ++i;
2794                 }
2795
2796                 RemotePlayer *player = m_env->getPlayer(peer_id);
2797
2798                 /* Run scripts and remove from environment */
2799                 if (player != NULL) {
2800                         PlayerSAO *playersao = player->getPlayerSAO();
2801                         assert(playersao);
2802
2803                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2804
2805                         playersao->disconnected();
2806                 }
2807
2808                 /*
2809                         Print out action
2810                 */
2811                 {
2812                         if(player != NULL && reason != CDR_DENY) {
2813                                 std::ostringstream os(std::ios_base::binary);
2814                                 std::vector<u16> clients = m_clients.getClientIDs();
2815
2816                                 for(std::vector<u16>::iterator i = clients.begin();
2817                                         i != clients.end(); ++i) {
2818                                         // Get player
2819                                         RemotePlayer *player = m_env->getPlayer(*i);
2820                                         if (!player)
2821                                                 continue;
2822
2823                                         // Get name of player
2824                                         os << player->getName() << " ";
2825                                 }
2826
2827                                 std::string name = player->getName();
2828                                 actionstream << name << " "
2829                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2830                                                 << " List of players: " << os.str() << std::endl;
2831                                 if (m_admin_chat)
2832                                         m_admin_chat->outgoing_queue.push_back(
2833                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2834                         }
2835                 }
2836                 {
2837                         MutexAutoLock env_lock(m_env_mutex);
2838                         m_clients.DeleteClient(peer_id);
2839                 }
2840         }
2841
2842         // Send leave chat message to all remaining clients
2843         if(message.length() != 0)
2844                 SendChatMessage(PEER_ID_INEXISTENT,message);
2845 }
2846
2847 void Server::UpdateCrafting(RemotePlayer *player)
2848 {
2849         DSTACK(FUNCTION_NAME);
2850
2851         // Get a preview for crafting
2852         ItemStack preview;
2853         InventoryLocation loc;
2854         loc.setPlayer(player->getName());
2855         std::vector<ItemStack> output_replacements;
2856         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2857         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2858                         (&player->inventory)->getList("craft"), loc);
2859
2860         // Put the new preview in
2861         InventoryList *plist = player->inventory.getList("craftpreview");
2862         sanity_check(plist);
2863         sanity_check(plist->getSize() >= 1);
2864         plist->changeItem(0, preview);
2865 }
2866
2867 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2868 {
2869         if (evt->type == CET_NICK_ADD) {
2870                 // The terminal informed us of its nick choice
2871                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2872                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2873                         errorstream << "You haven't set up an account." << std::endl
2874                                 << "Please log in using the client as '"
2875                                 << m_admin_nick << "' with a secure password." << std::endl
2876                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2877                                 << "and everybody can claim the user account instead of you," << std::endl
2878                                 << "giving them full control over this server." << std::endl;
2879                 }
2880         } else {
2881                 assert(evt->type == CET_CHAT);
2882                 handleAdminChat((ChatEventChat *)evt);
2883         }
2884 }
2885
2886 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2887         const std::wstring &wmessage, bool check_shout_priv, RemotePlayer *player)
2888 {
2889         // If something goes wrong, this player is to blame
2890         RollbackScopeActor rollback_scope(m_rollback,
2891                 std::string("player:") + name);
2892
2893         if (player) {
2894                 switch (player->canSendChatMessage()) {
2895                         case RPLAYER_CHATRESULT_FLOODING: {
2896                                 std::wstringstream ws;
2897                                 ws << L"You cannot send more messages. You are limited to "
2898                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2899                                    << L" messages per 10 seconds.";
2900                                 return ws.str();
2901                         }
2902                         case RPLAYER_CHATRESULT_KICK:
2903                                 DenyAccess_Legacy(player->peer_id,
2904                                                 L"You have been kicked due to message flooding.");
2905                                 return L"";
2906                         case RPLAYER_CHATRESULT_OK:
2907                                 break;
2908                         default:
2909                                 FATAL_ERROR("Unhandled chat filtering result found.");
2910                 }
2911         }
2912
2913         if (m_max_chatmessage_length > 0
2914                         && wmessage.length() > m_max_chatmessage_length) {
2915                 return L"Your message exceed the maximum chat message limit set on the server. "
2916                                 L"It was refused. Send a shorter message";
2917         }
2918
2919         // Run script hook, exit if script ate the chat message
2920         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2921                 return L"";
2922
2923         // Line to send
2924         std::wstring line;
2925         // Whether to send line to the player that sent the message, or to all players
2926         bool broadcast_line = true;
2927
2928         if (check_shout_priv && !checkPriv(name, "shout")) {
2929                 line += L"-!- You don't have permission to shout.";
2930                 broadcast_line = false;
2931         } else {
2932                 line += L"<";
2933                 line += wname;
2934                 line += L"> ";
2935                 line += wmessage;
2936         }
2937
2938         /*
2939                 Tell calling method to send the message to sender
2940         */
2941         if (!broadcast_line) {
2942                 return line;
2943         } else {
2944                 /*
2945                         Send the message to others
2946                 */
2947                 actionstream << "CHAT: " << wide_to_narrow(line) << std::endl;
2948
2949                 std::vector<u16> clients = m_clients.getClientIDs();
2950
2951                 /*
2952                         Send the message back to the inital sender
2953                         if they are using protocol version >= 29
2954                 */
2955
2956                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2957                 if (player && player->protocol_version >= 29)
2958                         peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2959
2960                 for (u16 i = 0; i < clients.size(); i++) {
2961                         u16 cid = clients[i];
2962                         if (cid != peer_id_to_avoid_sending)
2963                                 SendChatMessage(cid, line);
2964                 }
2965         }
2966         return L"";
2967 }
2968
2969 void Server::handleAdminChat(const ChatEventChat *evt)
2970 {
2971         std::string name = evt->nick;
2972         std::wstring wname = utf8_to_wide(name);
2973         std::wstring wmessage = evt->evt_msg;
2974
2975         std::wstring answer = handleChat(name, wname, wmessage);
2976
2977         // If asked to send answer to sender
2978         if (!answer.empty()) {
2979                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2980         }
2981 }
2982
2983 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2984 {
2985         RemoteClient *client = getClientNoEx(peer_id,state_min);
2986         if(!client)
2987                 throw ClientNotFoundException("Client not found");
2988
2989         return client;
2990 }
2991 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2992 {
2993         return m_clients.getClientNoEx(peer_id, state_min);
2994 }
2995
2996 std::string Server::getPlayerName(u16 peer_id)
2997 {
2998         RemotePlayer *player = m_env->getPlayer(peer_id);
2999         if (player == NULL)
3000                 return "[id="+itos(peer_id)+"]";
3001         return player->getName();
3002 }
3003
3004 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
3005 {
3006         RemotePlayer *player = m_env->getPlayer(peer_id);
3007         if (player == NULL)
3008                 return NULL;
3009         return player->getPlayerSAO();
3010 }
3011
3012 std::wstring Server::getStatusString()
3013 {
3014         std::wostringstream os(std::ios_base::binary);
3015         os<<L"# Server: ";
3016         // Version
3017         os<<L"version="<<narrow_to_wide(g_version_string);
3018         // Uptime
3019         os<<L", uptime="<<m_uptime.get();
3020         // Max lag estimate
3021         os<<L", max_lag="<<m_env->getMaxLagEstimate();
3022         // Information about clients
3023         bool first = true;
3024         os<<L", clients={";
3025         std::vector<u16> clients = m_clients.getClientIDs();
3026         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
3027                 // Get player
3028                 RemotePlayer *player = m_env->getPlayer(*i);
3029                 // Get name of player
3030                 std::wstring name = L"unknown";
3031                 if (player != NULL)
3032                         name = narrow_to_wide(player->getName());
3033                 // Add name to information string
3034                 if(!first)
3035                         os << L", ";
3036                 else
3037                         first = false;
3038                 os << name;
3039         }
3040         os << L"}";
3041         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
3042                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
3043         if(g_settings->get("motd") != "")
3044                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
3045         return os.str();
3046 }
3047
3048 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3049 {
3050         std::set<std::string> privs;
3051         m_script->getAuth(name, NULL, &privs);
3052         return privs;
3053 }
3054
3055 bool Server::checkPriv(const std::string &name, const std::string &priv)
3056 {
3057         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3058         return (privs.count(priv) != 0);
3059 }
3060
3061 void Server::reportPrivsModified(const std::string &name)
3062 {
3063         if(name == "") {
3064                 std::vector<u16> clients = m_clients.getClientIDs();
3065                 for(std::vector<u16>::iterator i = clients.begin();
3066                                 i != clients.end(); ++i) {
3067                         RemotePlayer *player = m_env->getPlayer(*i);
3068                         reportPrivsModified(player->getName());
3069                 }
3070         } else {
3071                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3072                 if (!player)
3073                         return;
3074                 SendPlayerPrivileges(player->peer_id);
3075                 PlayerSAO *sao = player->getPlayerSAO();
3076                 if(!sao)
3077                         return;
3078                 sao->updatePrivileges(
3079                                 getPlayerEffectivePrivs(name),
3080                                 isSingleplayer());
3081         }
3082 }
3083
3084 void Server::reportInventoryFormspecModified(const std::string &name)
3085 {
3086         RemotePlayer *player = m_env->getPlayer(name.c_str());
3087         if (!player)
3088                 return;
3089         SendPlayerInventoryFormspec(player->peer_id);
3090 }
3091
3092 void Server::setIpBanned(const std::string &ip, const std::string &name)
3093 {
3094         m_banmanager->add(ip, name);
3095 }
3096
3097 void Server::unsetIpBanned(const std::string &ip_or_name)
3098 {
3099         m_banmanager->remove(ip_or_name);
3100 }
3101
3102 std::string Server::getBanDescription(const std::string &ip_or_name)
3103 {
3104         return m_banmanager->getBanDescription(ip_or_name);
3105 }
3106
3107 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3108 {
3109         // m_env will be NULL if the server is initializing
3110         if (!m_env)
3111                 return;
3112
3113         if (m_admin_nick == name && !m_admin_nick.empty()) {
3114                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3115         }
3116
3117         RemotePlayer *player = m_env->getPlayer(name);
3118         if (!player) {
3119                 return;
3120         }
3121
3122         if (player->peer_id == PEER_ID_INEXISTENT)
3123                 return;
3124
3125         SendChatMessage(player->peer_id, msg);
3126 }
3127
3128 bool Server::showFormspec(const char *playername, const std::string &formspec,
3129         const std::string &formname)
3130 {
3131         // m_env will be NULL if the server is initializing
3132         if (!m_env)
3133                 return false;
3134
3135         RemotePlayer *player = m_env->getPlayer(playername);
3136         if (!player)
3137                 return false;
3138
3139         SendShowFormspecMessage(player->peer_id, formspec, formname);
3140         return true;
3141 }
3142
3143 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3144 {
3145         if (!player)
3146                 return -1;
3147
3148         u32 id = player->addHud(form);
3149
3150         SendHUDAdd(player->peer_id, id, form);
3151
3152         return id;
3153 }
3154
3155 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3156         if (!player)
3157                 return false;
3158
3159         HudElement* todel = player->removeHud(id);
3160
3161         if (!todel)
3162                 return false;
3163
3164         delete todel;
3165
3166         SendHUDRemove(player->peer_id, id);
3167         return true;
3168 }
3169
3170 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3171 {
3172         if (!player)
3173                 return false;
3174
3175         SendHUDChange(player->peer_id, id, stat, data);
3176         return true;
3177 }
3178
3179 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3180 {
3181         if (!player)
3182                 return false;
3183
3184         SendHUDSetFlags(player->peer_id, flags, mask);
3185         player->hud_flags &= ~mask;
3186         player->hud_flags |= flags;
3187
3188         PlayerSAO* playersao = player->getPlayerSAO();
3189
3190         if (playersao == NULL)
3191                 return false;
3192
3193         m_script->player_event(playersao, "hud_changed");
3194         return true;
3195 }
3196
3197 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3198 {
3199         if (!player)
3200                 return false;
3201
3202         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3203                 return false;
3204
3205         player->setHotbarItemcount(hotbar_itemcount);
3206         std::ostringstream os(std::ios::binary);
3207         writeS32(os, hotbar_itemcount);
3208         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3209         return true;
3210 }
3211
3212 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3213 {
3214         if (!player)
3215                 return;
3216
3217         player->setHotbarImage(name);
3218         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3219 }
3220
3221 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3222 {
3223         if (!player)
3224                 return "";
3225         return player->getHotbarImage();
3226 }
3227
3228 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3229 {
3230         if (!player)
3231                 return;
3232
3233         player->setHotbarSelectedImage(name);
3234         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3235 }
3236
3237 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3238                 v2s32 animation_frames[4], f32 frame_speed)
3239 {
3240         if (!player)
3241                 return false;
3242
3243         player->setLocalAnimations(animation_frames, frame_speed);
3244         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3245         return true;
3246 }
3247
3248 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3249 {
3250         if (!player)
3251                 return false;
3252
3253         player->eye_offset_first = first;
3254         player->eye_offset_third = third;
3255         SendEyeOffset(player->peer_id, first, third);
3256         return true;
3257 }
3258
3259 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3260         const std::string &type, const std::vector<std::string> &params,
3261         bool &clouds)
3262 {
3263         if (!player)
3264                 return false;
3265
3266         player->setSky(bgcolor, type, params, clouds);
3267         SendSetSky(player->peer_id, bgcolor, type, params, clouds);
3268         return true;
3269 }
3270
3271 bool Server::setClouds(RemotePlayer *player, float density,
3272         const video::SColor &color_bright,
3273         const video::SColor &color_ambient,
3274         float height,
3275         float thickness,
3276         const v2f &speed)
3277 {
3278         if (!player)
3279                 return false;
3280
3281         SendCloudParams(player->peer_id, density,
3282                         color_bright, color_ambient, height,
3283                         thickness, speed);
3284         return true;
3285 }
3286
3287 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3288         float ratio)
3289 {
3290         if (!player)
3291                 return false;
3292
3293         player->overrideDayNightRatio(do_override, ratio);
3294         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3295         return true;
3296 }
3297
3298 void Server::notifyPlayers(const std::wstring &msg)
3299 {
3300         SendChatMessage(PEER_ID_INEXISTENT,msg);
3301 }
3302
3303 void Server::spawnParticle(const std::string &playername, v3f pos,
3304         v3f velocity, v3f acceleration,
3305         float expirationtime, float size, bool
3306         collisiondetection, bool collision_removal,
3307         bool vertical, const std::string &texture,
3308         const struct TileAnimationParams &animation, u8 glow)
3309 {
3310         // m_env will be NULL if the server is initializing
3311         if (!m_env)
3312                 return;
3313
3314         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3315         if (playername != "") {
3316                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3317                 if (!player)
3318                         return;
3319                 peer_id = player->peer_id;
3320                 proto_ver = player->protocol_version;
3321         }
3322
3323         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3324                         expirationtime, size, collisiondetection,
3325                         collision_removal, vertical, texture, animation, glow);
3326 }
3327
3328 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3329         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3330         float minexptime, float maxexptime, float minsize, float maxsize,
3331         bool collisiondetection, bool collision_removal,
3332         ServerActiveObject *attached, bool vertical, const std::string &texture,
3333         const std::string &playername, const struct TileAnimationParams &animation,
3334         u8 glow)
3335 {
3336         // m_env will be NULL if the server is initializing
3337         if (!m_env)
3338                 return -1;
3339
3340         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3341         if (playername != "") {
3342                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3343                 if (!player)
3344                         return -1;
3345                 peer_id = player->peer_id;
3346                 proto_ver = player->protocol_version;
3347         }
3348
3349         u16 attached_id = attached ? attached->getId() : 0;
3350
3351         u32 id;
3352         if (attached_id == 0)
3353                 id = m_env->addParticleSpawner(spawntime);
3354         else
3355                 id = m_env->addParticleSpawner(spawntime, attached_id);
3356
3357         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3358                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3359                 minexptime, maxexptime, minsize, maxsize,
3360                 collisiondetection, collision_removal, attached_id, vertical,
3361                 texture, id, animation, glow);
3362
3363         return id;
3364 }
3365
3366 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3367 {
3368         // m_env will be NULL if the server is initializing
3369         if (!m_env)
3370                 throw ServerError("Can't delete particle spawners during initialisation!");
3371
3372         u16 peer_id = PEER_ID_INEXISTENT;
3373         if (playername != "") {
3374                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3375                 if (!player)
3376                         return;
3377                 peer_id = player->peer_id;
3378         }
3379
3380         m_env->deleteParticleSpawner(id);
3381         SendDeleteParticleSpawner(peer_id, id);
3382 }
3383
3384 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3385 {
3386         if(m_detached_inventories.count(name) > 0){
3387                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3388                 delete m_detached_inventories[name];
3389         } else {
3390                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3391         }
3392         Inventory *inv = new Inventory(m_itemdef);
3393         sanity_check(inv);
3394         m_detached_inventories[name] = inv;
3395         m_detached_inventories_player[name] = player;
3396         //TODO find a better way to do this
3397         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3398         return inv;
3399 }
3400
3401 // actions: time-reversed list
3402 // Return value: success/failure
3403 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3404                 std::list<std::string> *log)
3405 {
3406         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3407         ServerMap *map = (ServerMap*)(&m_env->getMap());
3408
3409         // Fail if no actions to handle
3410         if(actions.empty()){
3411                 log->push_back("Nothing to do.");
3412                 return false;
3413         }
3414
3415         int num_tried = 0;
3416         int num_failed = 0;
3417
3418         for(std::list<RollbackAction>::const_iterator
3419                         i = actions.begin();
3420                         i != actions.end(); ++i)
3421         {
3422                 const RollbackAction &action = *i;
3423                 num_tried++;
3424                 bool success = action.applyRevert(map, this, this);
3425                 if(!success){
3426                         num_failed++;
3427                         std::ostringstream os;
3428                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3429                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3430                         if(log)
3431                                 log->push_back(os.str());
3432                 }else{
3433                         std::ostringstream os;
3434                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3435                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3436                         if(log)
3437                                 log->push_back(os.str());
3438                 }
3439         }
3440
3441         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3442                         <<" failed"<<std::endl;
3443
3444         // Call it done if less than half failed
3445         return num_failed <= num_tried/2;
3446 }
3447
3448 // IGameDef interface
3449 // Under envlock
3450 IItemDefManager *Server::getItemDefManager()
3451 {
3452         return m_itemdef;
3453 }
3454
3455 INodeDefManager *Server::getNodeDefManager()
3456 {
3457         return m_nodedef;
3458 }
3459
3460 ICraftDefManager *Server::getCraftDefManager()
3461 {
3462         return m_craftdef;
3463 }
3464
3465 u16 Server::allocateUnknownNodeId(const std::string &name)
3466 {
3467         return m_nodedef->allocateDummy(name);
3468 }
3469
3470 MtEventManager *Server::getEventManager()
3471 {
3472         return m_event;
3473 }
3474
3475 IWritableItemDefManager *Server::getWritableItemDefManager()
3476 {
3477         return m_itemdef;
3478 }
3479
3480 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3481 {
3482         return m_nodedef;
3483 }
3484
3485 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3486 {
3487         return m_craftdef;
3488 }
3489
3490 const ModSpec *Server::getModSpec(const std::string &modname) const
3491 {
3492         std::vector<ModSpec>::const_iterator it;
3493         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3494                 const ModSpec &mod = *it;
3495                 if (mod.name == modname)
3496                         return &mod;
3497         }
3498         return NULL;
3499 }
3500
3501 void Server::getModNames(std::vector<std::string> &modlist)
3502 {
3503         std::vector<ModSpec>::iterator it;
3504         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3505                 modlist.push_back(it->name);
3506 }
3507
3508 std::string Server::getBuiltinLuaPath()
3509 {
3510         return porting::path_share + DIR_DELIM + "builtin";
3511 }
3512
3513 std::string Server::getModStoragePath() const
3514 {
3515         return m_path_world + DIR_DELIM + "mod_storage";
3516 }
3517
3518 v3f Server::findSpawnPos()
3519 {
3520         ServerMap &map = m_env->getServerMap();
3521         v3f nodeposf;
3522         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3523                 return nodeposf * BS;
3524         }
3525
3526         bool is_good = false;
3527
3528         // Try to find a good place a few times
3529         for(s32 i = 0; i < 4000 && !is_good; i++) {
3530                 s32 range = 1 + i;
3531                 // We're going to try to throw the player to this position
3532                 v2s16 nodepos2d = v2s16(
3533                         -range + (myrand() % (range * 2)),
3534                         -range + (myrand() % (range * 2)));
3535
3536                 // Get spawn level at point
3537                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3538                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3539                 // the mapgen to signify an unsuitable spawn position
3540                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3541                         continue;
3542
3543                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3544
3545                 s32 air_count = 0;
3546                 for (s32 i = 0; i < 10; i++) {
3547                         v3s16 blockpos = getNodeBlockPos(nodepos);
3548                         map.emergeBlock(blockpos, true);
3549                         content_t c = map.getNodeNoEx(nodepos).getContent();
3550                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3551                                 air_count++;
3552                                 if (air_count >= 2) {
3553                                         nodeposf = intToFloat(nodepos, BS);
3554                                         // Don't spawn the player outside map boundaries
3555                                         if (objectpos_over_limit(nodeposf))
3556                                                 continue;
3557                                         is_good = true;
3558                                         break;
3559                                 }
3560                         }
3561                         nodepos.Y++;
3562                 }
3563         }
3564
3565         return nodeposf;
3566 }
3567
3568 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3569 {
3570         m_shutdown_timer = delay;
3571         m_shutdown_msg = msg;
3572         m_shutdown_ask_reconnect = reconnect;
3573
3574         if (delay == 0.0f) {
3575         // No delay, shutdown immediately
3576                 m_shutdown_requested = true;
3577                 // only print to the infostream, a chat message saying 
3578                 // "Server Shutting Down" is sent when the server destructs.
3579                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3580         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3581         // Negative delay, cancel shutdown if requested
3582                 m_shutdown_timer = 0.0f;
3583                 m_shutdown_msg = "";
3584                 m_shutdown_ask_reconnect = false;
3585                 m_shutdown_requested = false;
3586                 std::wstringstream ws;
3587
3588                 ws << L"*** Server shutdown canceled.";
3589
3590                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3591                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3592         } else if (delay > 0.0f) {
3593         // Positive delay, tell the clients when the server will shut down
3594                 std::wstringstream ws;
3595
3596                 ws << L"*** Server shutting down in "
3597                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3598                                 << ".";
3599
3600                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3601                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3602         }
3603 }
3604
3605 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3606 {
3607         /*
3608                 Try to get an existing player
3609         */
3610         RemotePlayer *player = m_env->getPlayer(name);
3611
3612         // If player is already connected, cancel
3613         if (player != NULL && player->peer_id != 0) {
3614                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3615                 return NULL;
3616         }
3617
3618         /*
3619                 If player with the wanted peer_id already exists, cancel.
3620         */
3621         if (m_env->getPlayer(peer_id) != NULL) {
3622                 infostream<<"emergePlayer(): Player with wrong name but same"
3623                                 " peer_id already exists"<<std::endl;
3624                 return NULL;
3625         }
3626
3627         if (!player) {
3628                 player = new RemotePlayer(name, idef());
3629         }
3630
3631         bool newplayer = false;
3632
3633         // Load player
3634         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3635
3636         // Complete init with server parts
3637         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3638         player->protocol_version = proto_version;
3639
3640         /* Run scripts */
3641         if (newplayer) {
3642                 m_script->on_newplayer(playersao);
3643         }
3644
3645         return playersao;
3646 }
3647
3648 bool Server::registerModStorage(ModMetadata *storage)
3649 {
3650         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3651                 errorstream << "Unable to register same mod storage twice. Storage name: "
3652                                 << storage->getModName() << std::endl;
3653                 return false;
3654         }
3655
3656         m_mod_storages[storage->getModName()] = storage;
3657         return true;
3658 }
3659
3660 void Server::unregisterModStorage(const std::string &name)
3661 {
3662         UNORDERED_MAP<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3663         if (it != m_mod_storages.end()) {
3664                 // Save unconditionaly on unregistration
3665                 it->second->save(getModStoragePath());
3666                 m_mod_storages.erase(name);
3667         }
3668 }
3669
3670 void dedicated_server_loop(Server &server, bool &kill)
3671 {
3672         DSTACK(FUNCTION_NAME);
3673
3674         verbosestream<<"dedicated_server_loop()"<<std::endl;
3675
3676         IntervalLimiter m_profiler_interval;
3677
3678         static const float steplen = g_settings->getFloat("dedicated_server_step");
3679         static const float profiler_print_interval =
3680                         g_settings->getFloat("profiler_print_interval");
3681
3682         for(;;) {
3683                 // This is kind of a hack but can be done like this
3684                 // because server.step() is very light
3685                 {
3686                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3687                         sleep_ms((int)(steplen*1000.0));
3688                 }
3689                 server.step(steplen);
3690
3691                 if (server.getShutdownRequested() || kill)
3692                         break;
3693
3694                 /*
3695                         Profiler
3696                 */
3697                 if (profiler_print_interval != 0) {
3698                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3699                         {
3700                                 infostream<<"Profiler:"<<std::endl;
3701                                 g_profiler->print(infostream);
3702                                 g_profiler->clear();
3703                         }
3704                 }
3705         }
3706
3707         infostream << "Dedicated server quitting" << std::endl;
3708 #if USE_CURL
3709         if (g_settings->getBool("server_announce"))
3710                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3711                         server.m_bind_addr.getPort());
3712 #endif
3713 }