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