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