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