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