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