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