]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Remove one unused variable in Server::Receive function
[dragonfireclient.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "network/networkprotocol.h"
25 #include "network/serveropcodes.h"
26 #include "ban.h"
27 #include "environment.h"
28 #include "map.h"
29 #include "threading/mutex_auto_lock.h"
30 #include "constants.h"
31 #include "voxel.h"
32 #include "config.h"
33 #include "version.h"
34 #include "filesys.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "genericobject.h"
38 #include "settings.h"
39 #include "profiler.h"
40 #include "log.h"
41 #include "scripting_server.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "emerge.h"
46 #include "mapgen.h"
47 #include "mg_biome.h"
48 #include "content_mapnode.h"
49 #include "content_nodemeta.h"
50 #include "content_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         u16 peer_id;
1026         try {
1027                 NetworkPacket pkt;
1028                 m_con.Receive(&pkt);
1029                 peer_id = pkt.getPeerId();
1030                 ProcessData(&pkt);
1031         }
1032         catch(con::InvalidIncomingDataException &e) {
1033                 infostream<<"Server::Receive(): "
1034                                 "InvalidIncomingDataException: what()="
1035                                 <<e.what()<<std::endl;
1036         }
1037         catch(SerializationError &e) {
1038                 infostream<<"Server::Receive(): "
1039                                 "SerializationError: what()="
1040                                 <<e.what()<<std::endl;
1041         }
1042         catch(ClientStateError &e) {
1043                 errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1044                 DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect."
1045                                 L"Try reconnecting or updating your client");
1046         }
1047         catch(con::PeerNotFoundException &e) {
1048                 // Do nothing
1049         }
1050 }
1051
1052 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1053 {
1054         std::string playername = "";
1055         PlayerSAO *playersao = NULL;
1056         m_clients.lock();
1057         try {
1058                 RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_InitDone);
1059                 if (client != NULL) {
1060                         playername = client->getName();
1061                         playersao = emergePlayer(playername.c_str(), peer_id, client->net_proto_version);
1062                 }
1063         } catch (std::exception &e) {
1064                 m_clients.unlock();
1065                 throw;
1066         }
1067         m_clients.unlock();
1068
1069         RemotePlayer *player = m_env->getPlayer(playername.c_str());
1070
1071         // If failed, cancel
1072         if ((playersao == NULL) || (player == NULL)) {
1073                 if (player && player->peer_id != 0) {
1074                         actionstream << "Server: Failed to emerge player \"" << playername
1075                                         << "\" (player allocated to an another client)" << std::endl;
1076                         DenyAccess_Legacy(peer_id, L"Another client is connected with this "
1077                                         L"name. If your client closed unexpectedly, try again in "
1078                                         L"a minute.");
1079                 } else {
1080                         errorstream << "Server: " << playername << ": Failed to emerge player"
1081                                         << std::endl;
1082                         DenyAccess_Legacy(peer_id, L"Could not allocate player.");
1083                 }
1084                 return NULL;
1085         }
1086
1087         /*
1088                 Send complete position information
1089         */
1090         SendMovePlayer(peer_id);
1091
1092         // Send privileges
1093         SendPlayerPrivileges(peer_id);
1094
1095         // Send inventory formspec
1096         SendPlayerInventoryFormspec(peer_id);
1097
1098         // Send inventory
1099         SendInventory(playersao);
1100
1101         // Send HP or death screen
1102         if (playersao->isDead())
1103                 SendDeathscreen(peer_id, false, v3f(0,0,0));
1104         else
1105                 SendPlayerHPOrDie(playersao);
1106
1107         // Send Breath
1108         SendPlayerBreath(playersao);
1109
1110         // Note things in chat if not in simple singleplayer mode
1111         if (!m_simple_singleplayer_mode && g_settings->getBool("show_statusline_on_connect")) {
1112                 // Send information about server to player in chat
1113                 SendChatMessage(peer_id, ChatMessage(CHATMESSAGE_TYPE_SYSTEM, getStatusString()));
1114         }
1115         Address addr = getPeerAddress(player->peer_id);
1116         std::string ip_str = addr.serializeString();
1117         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1118         /*
1119                 Print out action
1120         */
1121         {
1122                 const std::vector<std::string> &names = m_clients.getPlayerNames();
1123
1124                 actionstream << player->getName() << " joins game. List of players: ";
1125
1126                 for (std::vector<std::string>::const_iterator i = names.begin();
1127                                 i != names.end(); ++i) {
1128                         actionstream << *i << " ";
1129                 }
1130
1131                 actionstream << player->getName() <<std::endl;
1132         }
1133         return playersao;
1134 }
1135
1136 inline void Server::handleCommand(NetworkPacket* pkt)
1137 {
1138         const ToServerCommandHandler& opHandle = toServerCommandTable[pkt->getCommand()];
1139         (this->*opHandle.handler)(pkt);
1140 }
1141
1142 void Server::ProcessData(NetworkPacket *pkt)
1143 {
1144         DSTACK(FUNCTION_NAME);
1145         // Environment is locked first.
1146         MutexAutoLock envlock(m_env_mutex);
1147
1148         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1149         u32 peer_id = pkt->getPeerId();
1150
1151         try {
1152                 Address address = getPeerAddress(peer_id);
1153                 std::string addr_s = address.serializeString();
1154
1155                 if(m_banmanager->isIpBanned(addr_s)) {
1156                         std::string ban_name = m_banmanager->getBanName(addr_s);
1157                         infostream << "Server: A banned client tried to connect from "
1158                                         << addr_s << "; banned name was "
1159                                         << ban_name << std::endl;
1160                         // This actually doesn't seem to transfer to the client
1161                         DenyAccess_Legacy(peer_id, L"Your ip is banned. Banned name was "
1162                                         + utf8_to_wide(ban_name));
1163                         return;
1164                 }
1165         }
1166         catch(con::PeerNotFoundException &e) {
1167                 /*
1168                  * no peer for this packet found
1169                  * most common reason is peer timeout, e.g. peer didn't
1170                  * respond for some time, your server was overloaded or
1171                  * things like that.
1172                  */
1173                 infostream << "Server::ProcessData(): Canceling: peer "
1174                                 << peer_id << " not found" << std::endl;
1175                 return;
1176         }
1177
1178         try {
1179                 ToServerCommand command = (ToServerCommand) pkt->getCommand();
1180
1181                 // Command must be handled into ToServerCommandHandler
1182                 if (command >= TOSERVER_NUM_MSG_TYPES) {
1183                         infostream << "Server: Ignoring unknown command "
1184                                          << command << std::endl;
1185                         return;
1186                 }
1187
1188                 if (toServerCommandTable[command].state == TOSERVER_STATE_NOT_CONNECTED) {
1189                         handleCommand(pkt);
1190                         return;
1191                 }
1192
1193                 u8 peer_ser_ver = getClient(peer_id, CS_InitDone)->serialization_version;
1194
1195                 if(peer_ser_ver == SER_FMT_VER_INVALID) {
1196                         errorstream << "Server::ProcessData(): Cancelling: Peer"
1197                                         " serialization format invalid or not initialized."
1198                                         " Skipping incoming command=" << command << std::endl;
1199                         return;
1200                 }
1201
1202                 /* Handle commands related to client startup */
1203                 if (toServerCommandTable[command].state == TOSERVER_STATE_STARTUP) {
1204                         handleCommand(pkt);
1205                         return;
1206                 }
1207
1208                 if (m_clients.getClientState(peer_id) < CS_Active) {
1209                         if (command == TOSERVER_PLAYERPOS) return;
1210
1211                         errorstream << "Got packet command: " << command << " for peer id "
1212                                         << peer_id << " but client isn't active yet. Dropping packet "
1213                                         << std::endl;
1214                         return;
1215                 }
1216
1217                 handleCommand(pkt);
1218         } catch (SendFailedException &e) {
1219                 errorstream << "Server::ProcessData(): SendFailedException: "
1220                                 << "what=" << e.what()
1221                                 << std::endl;
1222         } catch (PacketError &e) {
1223                 actionstream << "Server::ProcessData(): PacketError: "
1224                                 << "what=" << e.what()
1225                                 << std::endl;
1226         }
1227 }
1228
1229 void Server::setTimeOfDay(u32 time)
1230 {
1231         m_env->setTimeOfDay(time);
1232         m_time_of_day_send_timer = 0;
1233 }
1234
1235 void Server::onMapEditEvent(MapEditEvent *event)
1236 {
1237         if(m_ignore_map_edit_events)
1238                 return;
1239         if(m_ignore_map_edit_events_area.contains(event->getArea()))
1240                 return;
1241         MapEditEvent *e = event->clone();
1242         m_unsent_map_edit_queue.push(e);
1243 }
1244
1245 Inventory* Server::getInventory(const InventoryLocation &loc)
1246 {
1247         switch (loc.type) {
1248         case InventoryLocation::UNDEFINED:
1249         case InventoryLocation::CURRENT_PLAYER:
1250                 break;
1251         case InventoryLocation::PLAYER:
1252         {
1253                 RemotePlayer *player = dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
1254                 if(!player)
1255                         return NULL;
1256                 PlayerSAO *playersao = player->getPlayerSAO();
1257                 if(!playersao)
1258                         return NULL;
1259                 return playersao->getInventory();
1260         }
1261                 break;
1262         case InventoryLocation::NODEMETA:
1263         {
1264                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
1265                 if(!meta)
1266                         return NULL;
1267                 return meta->getInventory();
1268         }
1269                 break;
1270         case InventoryLocation::DETACHED:
1271         {
1272                 if(m_detached_inventories.count(loc.name) == 0)
1273                         return NULL;
1274                 return m_detached_inventories[loc.name];
1275         }
1276                 break;
1277         default:
1278                 sanity_check(false); // abort
1279                 break;
1280         }
1281         return NULL;
1282 }
1283 void Server::setInventoryModified(const InventoryLocation &loc, bool playerSend)
1284 {
1285         switch(loc.type){
1286         case InventoryLocation::UNDEFINED:
1287                 break;
1288         case InventoryLocation::PLAYER:
1289         {
1290                 if (!playerSend)
1291                         return;
1292
1293                 RemotePlayer *player =
1294                         dynamic_cast<RemotePlayer *>(m_env->getPlayer(loc.name.c_str()));
1295
1296                 if (!player)
1297                         return;
1298
1299                 PlayerSAO *playersao = player->getPlayerSAO();
1300                 if(!playersao)
1301                         return;
1302
1303                 SendInventory(playersao);
1304         }
1305                 break;
1306         case InventoryLocation::NODEMETA:
1307         {
1308                 v3s16 blockpos = getNodeBlockPos(loc.p);
1309
1310                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
1311                 if(block)
1312                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
1313
1314                 setBlockNotSent(blockpos);
1315         }
1316                 break;
1317         case InventoryLocation::DETACHED:
1318         {
1319                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
1320         }
1321                 break;
1322         default:
1323                 sanity_check(false); // abort
1324                 break;
1325         }
1326 }
1327
1328 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
1329 {
1330         std::vector<u16> clients = m_clients.getClientIDs();
1331         m_clients.lock();
1332         // Set the modified blocks unsent for all the clients
1333         for (std::vector<u16>::iterator i = clients.begin();
1334                  i != clients.end(); ++i) {
1335                         if (RemoteClient *client = m_clients.lockedGetClientNoEx(*i))
1336                                 client->SetBlocksNotSent(block);
1337         }
1338         m_clients.unlock();
1339 }
1340
1341 void Server::peerAdded(con::Peer *peer)
1342 {
1343         DSTACK(FUNCTION_NAME);
1344         verbosestream<<"Server::peerAdded(): peer->id="
1345                         <<peer->id<<std::endl;
1346
1347         con::PeerChange c;
1348         c.type = con::PEER_ADDED;
1349         c.peer_id = peer->id;
1350         c.timeout = false;
1351         m_peer_change_queue.push(c);
1352 }
1353
1354 void Server::deletingPeer(con::Peer *peer, bool timeout)
1355 {
1356         DSTACK(FUNCTION_NAME);
1357         verbosestream<<"Server::deletingPeer(): peer->id="
1358                         <<peer->id<<", timeout="<<timeout<<std::endl;
1359
1360         m_clients.event(peer->id, CSE_Disconnect);
1361         con::PeerChange c;
1362         c.type = con::PEER_REMOVED;
1363         c.peer_id = peer->id;
1364         c.timeout = timeout;
1365         m_peer_change_queue.push(c);
1366 }
1367
1368 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
1369 {
1370         *retval = m_con.getPeerStat(peer_id,type);
1371         if (*retval == -1) return false;
1372         return true;
1373 }
1374
1375 bool Server::getClientInfo(
1376                 u16          peer_id,
1377                 ClientState* state,
1378                 u32*         uptime,
1379                 u8*          ser_vers,
1380                 u16*         prot_vers,
1381                 u8*          major,
1382                 u8*          minor,
1383                 u8*          patch,
1384                 std::string* vers_string
1385         )
1386 {
1387         *state = m_clients.getClientState(peer_id);
1388         m_clients.lock();
1389         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id, CS_Invalid);
1390
1391         if (client == NULL) {
1392                 m_clients.unlock();
1393                 return false;
1394         }
1395
1396         *uptime = client->uptime();
1397         *ser_vers = client->serialization_version;
1398         *prot_vers = client->net_proto_version;
1399
1400         *major = client->getMajor();
1401         *minor = client->getMinor();
1402         *patch = client->getPatch();
1403         *vers_string = client->getPatch();
1404
1405         m_clients.unlock();
1406
1407         return true;
1408 }
1409
1410 void Server::handlePeerChanges()
1411 {
1412         while(m_peer_change_queue.size() > 0)
1413         {
1414                 con::PeerChange c = m_peer_change_queue.front();
1415                 m_peer_change_queue.pop();
1416
1417                 verbosestream<<"Server: Handling peer change: "
1418                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
1419                                 <<std::endl;
1420
1421                 switch(c.type)
1422                 {
1423                 case con::PEER_ADDED:
1424                         m_clients.CreateClient(c.peer_id);
1425                         break;
1426
1427                 case con::PEER_REMOVED:
1428                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
1429                         break;
1430
1431                 default:
1432                         FATAL_ERROR("Invalid peer change event received!");
1433                         break;
1434                 }
1435         }
1436 }
1437
1438 void Server::printToConsoleOnly(const std::string &text)
1439 {
1440         if (m_admin_chat) {
1441                 m_admin_chat->outgoing_queue.push_back(
1442                         new ChatEventChat("", utf8_to_wide(text)));
1443         } else {
1444                 std::cout << text << std::endl;
1445         }
1446 }
1447
1448 void Server::Send(NetworkPacket* pkt)
1449 {
1450         m_clients.send(pkt->getPeerId(),
1451                 clientCommandFactoryTable[pkt->getCommand()].channel,
1452                 pkt,
1453                 clientCommandFactoryTable[pkt->getCommand()].reliable);
1454 }
1455
1456 void Server::SendMovement(u16 peer_id)
1457 {
1458         DSTACK(FUNCTION_NAME);
1459         std::ostringstream os(std::ios_base::binary);
1460
1461         NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
1462
1463         pkt << g_settings->getFloat("movement_acceleration_default");
1464         pkt << g_settings->getFloat("movement_acceleration_air");
1465         pkt << g_settings->getFloat("movement_acceleration_fast");
1466         pkt << g_settings->getFloat("movement_speed_walk");
1467         pkt << g_settings->getFloat("movement_speed_crouch");
1468         pkt << g_settings->getFloat("movement_speed_fast");
1469         pkt << g_settings->getFloat("movement_speed_climb");
1470         pkt << g_settings->getFloat("movement_speed_jump");
1471         pkt << g_settings->getFloat("movement_liquid_fluidity");
1472         pkt << g_settings->getFloat("movement_liquid_fluidity_smooth");
1473         pkt << g_settings->getFloat("movement_liquid_sink");
1474         pkt << g_settings->getFloat("movement_gravity");
1475
1476         Send(&pkt);
1477 }
1478
1479 void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
1480 {
1481         if (!g_settings->getBool("enable_damage"))
1482                 return;
1483
1484         u16 peer_id   = playersao->getPeerID();
1485         bool is_alive = playersao->getHP() > 0;
1486
1487         if (is_alive)
1488                 SendPlayerHP(peer_id);
1489         else
1490                 DiePlayer(peer_id);
1491 }
1492
1493 void Server::SendHP(u16 peer_id, u8 hp)
1494 {
1495         DSTACK(FUNCTION_NAME);
1496
1497         NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
1498         pkt << hp;
1499         Send(&pkt);
1500 }
1501
1502 void Server::SendBreath(u16 peer_id, u16 breath)
1503 {
1504         DSTACK(FUNCTION_NAME);
1505
1506         NetworkPacket pkt(TOCLIENT_BREATH, 2, peer_id);
1507         pkt << (u16) breath;
1508         Send(&pkt);
1509 }
1510
1511 void Server::SendAccessDenied(u16 peer_id, AccessDeniedCode reason,
1512                 const std::string &custom_reason, bool reconnect)
1513 {
1514         assert(reason < SERVER_ACCESSDENIED_MAX);
1515
1516         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED, 1, peer_id);
1517         pkt << (u8)reason;
1518         if (reason == SERVER_ACCESSDENIED_CUSTOM_STRING)
1519                 pkt << custom_reason;
1520         else if (reason == SERVER_ACCESSDENIED_SHUTDOWN ||
1521                         reason == SERVER_ACCESSDENIED_CRASH)
1522                 pkt << custom_reason << (u8)reconnect;
1523         Send(&pkt);
1524 }
1525
1526 void Server::SendAccessDenied_Legacy(u16 peer_id,const std::wstring &reason)
1527 {
1528         DSTACK(FUNCTION_NAME);
1529
1530         NetworkPacket pkt(TOCLIENT_ACCESS_DENIED_LEGACY, 0, peer_id);
1531         pkt << reason;
1532         Send(&pkt);
1533 }
1534
1535 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
1536                 v3f camera_point_target)
1537 {
1538         DSTACK(FUNCTION_NAME);
1539
1540         NetworkPacket pkt(TOCLIENT_DEATHSCREEN, 1 + sizeof(v3f), peer_id);
1541         pkt << set_camera_point_target << camera_point_target;
1542         Send(&pkt);
1543 }
1544
1545 void Server::SendItemDef(u16 peer_id,
1546                 IItemDefManager *itemdef, u16 protocol_version)
1547 {
1548         DSTACK(FUNCTION_NAME);
1549
1550         NetworkPacket pkt(TOCLIENT_ITEMDEF, 0, peer_id);
1551
1552         /*
1553                 u16 command
1554                 u32 length of the next item
1555                 zlib-compressed serialized ItemDefManager
1556         */
1557         std::ostringstream tmp_os(std::ios::binary);
1558         itemdef->serialize(tmp_os, protocol_version);
1559         std::ostringstream tmp_os2(std::ios::binary);
1560         compressZlib(tmp_os.str(), tmp_os2);
1561         pkt.putLongString(tmp_os2.str());
1562
1563         // Make data buffer
1564         verbosestream << "Server: Sending item definitions to id(" << peer_id
1565                         << "): size=" << pkt.getSize() << std::endl;
1566
1567         Send(&pkt);
1568 }
1569
1570 void Server::SendNodeDef(u16 peer_id,
1571                 INodeDefManager *nodedef, u16 protocol_version)
1572 {
1573         DSTACK(FUNCTION_NAME);
1574
1575         NetworkPacket pkt(TOCLIENT_NODEDEF, 0, peer_id);
1576
1577         /*
1578                 u16 command
1579                 u32 length of the next item
1580                 zlib-compressed serialized NodeDefManager
1581         */
1582         std::ostringstream tmp_os(std::ios::binary);
1583         nodedef->serialize(tmp_os, protocol_version);
1584         std::ostringstream tmp_os2(std::ios::binary);
1585         compressZlib(tmp_os.str(), tmp_os2);
1586
1587         pkt.putLongString(tmp_os2.str());
1588
1589         // Make data buffer
1590         verbosestream << "Server: Sending node definitions to id(" << peer_id
1591                         << "): size=" << pkt.getSize() << std::endl;
1592
1593         Send(&pkt);
1594 }
1595
1596 /*
1597         Non-static send methods
1598 */
1599
1600 void Server::SendInventory(PlayerSAO* playerSAO)
1601 {
1602         DSTACK(FUNCTION_NAME);
1603
1604         UpdateCrafting(playerSAO->getPlayer());
1605
1606         /*
1607                 Serialize it
1608         */
1609
1610         NetworkPacket pkt(TOCLIENT_INVENTORY, 0, playerSAO->getPeerID());
1611
1612         std::ostringstream os;
1613         playerSAO->getInventory()->serialize(os);
1614
1615         std::string s = os.str();
1616
1617         pkt.putRawString(s.c_str(), s.size());
1618         Send(&pkt);
1619 }
1620
1621 void Server::SendChatMessage(u16 peer_id, const ChatMessage &message)
1622 {
1623         DSTACK(FUNCTION_NAME);
1624
1625         NetworkPacket legacypkt(TOCLIENT_CHAT_MESSAGE_OLD, 0, peer_id);
1626         legacypkt << message.message;
1627
1628         NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
1629         u8 version = 1;
1630         u8 type = message.type;
1631         pkt << version << type << std::wstring(L"") << message.message << message.timestamp;
1632
1633         if (peer_id != PEER_ID_INEXISTENT) {
1634                 RemotePlayer *player = m_env->getPlayer(peer_id);
1635                 if (!player)
1636                         return;
1637
1638                 if (player->protocol_version < 35)
1639                         Send(&legacypkt);
1640                 else
1641                         Send(&pkt);
1642         } else {
1643                 m_clients.sendToAllCompat(&pkt, &legacypkt, 35);
1644         }
1645 }
1646
1647 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
1648                                      const std::string &formname)
1649 {
1650         DSTACK(FUNCTION_NAME);
1651
1652         NetworkPacket pkt(TOCLIENT_SHOW_FORMSPEC, 0 , peer_id);
1653         if (formspec == "" ){
1654                 //the client should close the formspec
1655                 pkt.putLongString("");
1656         } else {
1657                 pkt.putLongString(FORMSPEC_VERSION_STRING + formspec);
1658         }
1659         pkt << formname;
1660
1661         Send(&pkt);
1662 }
1663
1664 // Spawns a particle on peer with peer_id
1665 void Server::SendSpawnParticle(u16 peer_id, u16 protocol_version,
1666                                 v3f pos, v3f velocity, v3f acceleration,
1667                                 float expirationtime, float size, bool collisiondetection,
1668                                 bool collision_removal,
1669                                 bool vertical, const std::string &texture,
1670                                 const struct TileAnimationParams &animation, u8 glow)
1671 {
1672         DSTACK(FUNCTION_NAME);
1673         static thread_local const float radius =
1674                         g_settings->getS16("max_block_send_distance") * MAP_BLOCKSIZE * BS;
1675
1676         if (peer_id == PEER_ID_INEXISTENT) {
1677                 std::vector<u16> clients = m_clients.getClientIDs();
1678
1679                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
1680                         RemotePlayer *player = m_env->getPlayer(*i);
1681                         if (!player)
1682                                 continue;
1683
1684                         PlayerSAO *sao = player->getPlayerSAO();
1685                         if (!sao)
1686                                 continue;
1687
1688                         // Do not send to distant clients
1689                         if (sao->getBasePosition().getDistanceFrom(pos * BS) > radius)
1690                                 continue;
1691
1692                         SendSpawnParticle(*i, player->protocol_version,
1693                                         pos, velocity, acceleration,
1694                                         expirationtime, size, collisiondetection,
1695                                         collision_removal, vertical, texture, animation, glow);
1696                 }
1697                 return;
1698         }
1699
1700         NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
1701
1702         pkt << pos << velocity << acceleration << expirationtime
1703                         << size << collisiondetection;
1704         pkt.putLongString(texture);
1705         pkt << vertical;
1706         pkt << collision_removal;
1707         // This is horrible but required (why are there two ways to serialize pkts?)
1708         std::ostringstream os(std::ios_base::binary);
1709         animation.serialize(os, protocol_version);
1710         pkt.putRawString(os.str());
1711         pkt << glow;
1712
1713         Send(&pkt);
1714 }
1715
1716 // Adds a ParticleSpawner on peer with peer_id
1717 void Server::SendAddParticleSpawner(u16 peer_id, u16 protocol_version,
1718         u16 amount, float spawntime, v3f minpos, v3f maxpos,
1719         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
1720         float minsize, float maxsize, bool collisiondetection, bool collision_removal,
1721         u16 attached_id, bool vertical, const std::string &texture, u32 id,
1722         const struct TileAnimationParams &animation, u8 glow)
1723 {
1724         DSTACK(FUNCTION_NAME);
1725         if (peer_id == PEER_ID_INEXISTENT) {
1726                 // This sucks and should be replaced:
1727                 std::vector<u16> clients = m_clients.getClientIDs();
1728                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
1729                         RemotePlayer *player = m_env->getPlayer(*i);
1730                         if (!player)
1731                                 continue;
1732                         SendAddParticleSpawner(*i, player->protocol_version,
1733                                         amount, spawntime, minpos, maxpos,
1734                                         minvel, maxvel, minacc, maxacc, minexptime, maxexptime,
1735                                         minsize, maxsize, collisiondetection, collision_removal,
1736                                         attached_id, vertical, texture, id, animation, glow);
1737                 }
1738                 return;
1739         }
1740
1741         NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 0, peer_id);
1742
1743         pkt << amount << spawntime << minpos << maxpos << minvel << maxvel
1744                         << minacc << maxacc << minexptime << maxexptime << minsize
1745                         << maxsize << collisiondetection;
1746
1747         pkt.putLongString(texture);
1748
1749         pkt << id << vertical;
1750         pkt << collision_removal;
1751         pkt << attached_id;
1752         // This is horrible but required
1753         std::ostringstream os(std::ios_base::binary);
1754         animation.serialize(os, protocol_version);
1755         pkt.putRawString(os.str());
1756         pkt << glow;
1757
1758         Send(&pkt);
1759 }
1760
1761 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
1762 {
1763         DSTACK(FUNCTION_NAME);
1764
1765         NetworkPacket pkt(TOCLIENT_DELETE_PARTICLESPAWNER_LEGACY, 2, peer_id);
1766
1767         // Ugly error in this packet
1768         pkt << (u16) id;
1769
1770         if (peer_id != PEER_ID_INEXISTENT) {
1771                 Send(&pkt);
1772         }
1773         else {
1774                 m_clients.sendToAll(&pkt);
1775         }
1776
1777 }
1778
1779 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
1780 {
1781         NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
1782
1783         pkt << id << (u8) form->type << form->pos << form->name << form->scale
1784                         << form->text << form->number << form->item << form->dir
1785                         << form->align << form->offset << form->world_pos << form->size;
1786
1787         Send(&pkt);
1788 }
1789
1790 void Server::SendHUDRemove(u16 peer_id, u32 id)
1791 {
1792         NetworkPacket pkt(TOCLIENT_HUDRM, 4, peer_id);
1793         pkt << id;
1794         Send(&pkt);
1795 }
1796
1797 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
1798 {
1799         NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
1800         pkt << id << (u8) stat;
1801
1802         switch (stat) {
1803                 case HUD_STAT_POS:
1804                 case HUD_STAT_SCALE:
1805                 case HUD_STAT_ALIGN:
1806                 case HUD_STAT_OFFSET:
1807                         pkt << *(v2f *) value;
1808                         break;
1809                 case HUD_STAT_NAME:
1810                 case HUD_STAT_TEXT:
1811                         pkt << *(std::string *) value;
1812                         break;
1813                 case HUD_STAT_WORLD_POS:
1814                         pkt << *(v3f *) value;
1815                         break;
1816                 case HUD_STAT_SIZE:
1817                         pkt << *(v2s32 *) value;
1818                         break;
1819                 case HUD_STAT_NUMBER:
1820                 case HUD_STAT_ITEM:
1821                 case HUD_STAT_DIR:
1822                 default:
1823                         pkt << *(u32 *) value;
1824                         break;
1825         }
1826
1827         Send(&pkt);
1828 }
1829
1830 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
1831 {
1832         NetworkPacket pkt(TOCLIENT_HUD_SET_FLAGS, 4 + 4, peer_id);
1833
1834         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
1835
1836         pkt << flags << mask;
1837
1838         Send(&pkt);
1839 }
1840
1841 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
1842 {
1843         NetworkPacket pkt(TOCLIENT_HUD_SET_PARAM, 0, peer_id);
1844         pkt << param << value;
1845         Send(&pkt);
1846 }
1847
1848 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
1849                 const std::string &type, const std::vector<std::string> &params,
1850                 bool &clouds)
1851 {
1852         NetworkPacket pkt(TOCLIENT_SET_SKY, 0, peer_id);
1853         pkt << bgcolor << type << (u16) params.size();
1854
1855         for(size_t i=0; i<params.size(); i++)
1856                 pkt << params[i];
1857
1858         pkt << clouds;
1859
1860         Send(&pkt);
1861 }
1862
1863 void Server::SendCloudParams(u16 peer_id, float density,
1864                 const video::SColor &color_bright,
1865                 const video::SColor &color_ambient,
1866                 float height,
1867                 float thickness,
1868                 const v2f &speed)
1869 {
1870         NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
1871         pkt << density << color_bright << color_ambient
1872                         << height << thickness << speed;
1873
1874         Send(&pkt);
1875 }
1876
1877 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
1878                 float ratio)
1879 {
1880         NetworkPacket pkt(TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO,
1881                         1 + 2, peer_id);
1882
1883         pkt << do_override << (u16) (ratio * 65535);
1884
1885         Send(&pkt);
1886 }
1887
1888 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
1889 {
1890         DSTACK(FUNCTION_NAME);
1891
1892         NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
1893         pkt << time << time_speed;
1894
1895         if (peer_id == PEER_ID_INEXISTENT) {
1896                 m_clients.sendToAll(&pkt);
1897         }
1898         else {
1899                 Send(&pkt);
1900         }
1901 }
1902
1903 void Server::SendPlayerHP(u16 peer_id)
1904 {
1905         DSTACK(FUNCTION_NAME);
1906         PlayerSAO *playersao = getPlayerSAO(peer_id);
1907         // In some rare case if the player is disconnected
1908         // while Lua call l_punch, for example, this can be NULL
1909         if (!playersao)
1910                 return;
1911
1912         SendHP(peer_id, playersao->getHP());
1913         m_script->player_event(playersao,"health_changed");
1914
1915         // Send to other clients
1916         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
1917         ActiveObjectMessage aom(playersao->getId(), true, str);
1918         playersao->m_messages_out.push(aom);
1919 }
1920
1921 void Server::SendPlayerBreath(PlayerSAO *sao)
1922 {
1923         DSTACK(FUNCTION_NAME);
1924         assert(sao);
1925
1926         m_script->player_event(sao, "breath_changed");
1927         SendBreath(sao->getPeerID(), sao->getBreath());
1928 }
1929
1930 void Server::SendMovePlayer(u16 peer_id)
1931 {
1932         DSTACK(FUNCTION_NAME);
1933         RemotePlayer *player = m_env->getPlayer(peer_id);
1934         assert(player);
1935         PlayerSAO *sao = player->getPlayerSAO();
1936         assert(sao);
1937
1938         NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
1939         pkt << sao->getBasePosition() << sao->getPitch() << sao->getYaw();
1940
1941         {
1942                 v3f pos = sao->getBasePosition();
1943                 verbosestream << "Server: Sending TOCLIENT_MOVE_PLAYER"
1944                                 << " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
1945                                 << " pitch=" << sao->getPitch()
1946                                 << " yaw=" << sao->getYaw()
1947                                 << std::endl;
1948         }
1949
1950         Send(&pkt);
1951 }
1952
1953 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
1954 {
1955         NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
1956                 peer_id);
1957
1958         pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
1959                         << animation_frames[3] << animation_speed;
1960
1961         Send(&pkt);
1962 }
1963
1964 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
1965 {
1966         NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
1967         pkt << first << third;
1968         Send(&pkt);
1969 }
1970 void Server::SendPlayerPrivileges(u16 peer_id)
1971 {
1972         RemotePlayer *player = m_env->getPlayer(peer_id);
1973         assert(player);
1974         if(player->peer_id == PEER_ID_INEXISTENT)
1975                 return;
1976
1977         std::set<std::string> privs;
1978         m_script->getAuth(player->getName(), NULL, &privs);
1979
1980         NetworkPacket pkt(TOCLIENT_PRIVILEGES, 0, peer_id);
1981         pkt << (u16) privs.size();
1982
1983         for(std::set<std::string>::const_iterator i = privs.begin();
1984                         i != privs.end(); ++i) {
1985                 pkt << (*i);
1986         }
1987
1988         Send(&pkt);
1989 }
1990
1991 void Server::SendPlayerInventoryFormspec(u16 peer_id)
1992 {
1993         RemotePlayer *player = m_env->getPlayer(peer_id);
1994         assert(player);
1995         if(player->peer_id == PEER_ID_INEXISTENT)
1996                 return;
1997
1998         NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
1999         pkt.putLongString(FORMSPEC_VERSION_STRING + player->inventory_formspec);
2000         Send(&pkt);
2001 }
2002
2003 u32 Server::SendActiveObjectRemoveAdd(u16 peer_id, const std::string &datas)
2004 {
2005         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD, datas.size(), peer_id);
2006         pkt.putRawString(datas.c_str(), datas.size());
2007         Send(&pkt);
2008         return pkt.getSize();
2009 }
2010
2011 void Server::SendActiveObjectMessages(u16 peer_id, const std::string &datas, bool reliable)
2012 {
2013         NetworkPacket pkt(TOCLIENT_ACTIVE_OBJECT_MESSAGES,
2014                         datas.size(), peer_id);
2015
2016         pkt.putRawString(datas.c_str(), datas.size());
2017
2018         m_clients.send(pkt.getPeerId(),
2019                         reliable ? clientCommandFactoryTable[pkt.getCommand()].channel : 1,
2020                         &pkt, reliable);
2021 }
2022
2023 void Server::SendCSMFlavourLimits(u16 peer_id)
2024 {
2025         NetworkPacket pkt(TOCLIENT_CSM_FLAVOUR_LIMITS,
2026                 sizeof(m_csm_flavour_limits) + sizeof(m_csm_noderange_limit), peer_id);
2027         pkt << m_csm_flavour_limits << m_csm_noderange_limit;
2028         Send(&pkt);
2029 }
2030
2031 s32 Server::playSound(const SimpleSoundSpec &spec,
2032                 const ServerSoundParams &params)
2033 {
2034         // Find out initial position of sound
2035         bool pos_exists = false;
2036         v3f pos = params.getPos(m_env, &pos_exists);
2037         // If position is not found while it should be, cancel sound
2038         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
2039                 return -1;
2040
2041         // Filter destination clients
2042         std::vector<u16> dst_clients;
2043         if(params.to_player != "")
2044         {
2045                 RemotePlayer *player = m_env->getPlayer(params.to_player.c_str());
2046                 if(!player){
2047                         infostream<<"Server::playSound: Player \""<<params.to_player
2048                                         <<"\" not found"<<std::endl;
2049                         return -1;
2050                 }
2051                 if(player->peer_id == PEER_ID_INEXISTENT){
2052                         infostream<<"Server::playSound: Player \""<<params.to_player
2053                                         <<"\" not connected"<<std::endl;
2054                         return -1;
2055                 }
2056                 dst_clients.push_back(player->peer_id);
2057         }
2058         else {
2059                 std::vector<u16> clients = m_clients.getClientIDs();
2060
2061                 for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2062                         RemotePlayer *player = m_env->getPlayer(*i);
2063                         if (!player)
2064                                 continue;
2065
2066                         PlayerSAO *sao = player->getPlayerSAO();
2067                         if (!sao)
2068                                 continue;
2069
2070                         if (pos_exists) {
2071                                 if(sao->getBasePosition().getDistanceFrom(pos) >
2072                                                 params.max_hear_distance)
2073                                         continue;
2074                         }
2075                         dst_clients.push_back(*i);
2076                 }
2077         }
2078
2079         if(dst_clients.empty())
2080                 return -1;
2081
2082         // Create the sound
2083         s32 id = m_next_sound_id++;
2084         // The sound will exist as a reference in m_playing_sounds
2085         m_playing_sounds[id] = ServerPlayingSound();
2086         ServerPlayingSound &psound = m_playing_sounds[id];
2087         psound.params = params;
2088         psound.spec = spec;
2089
2090         float gain = params.gain * spec.gain;
2091         NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
2092         pkt << id << spec.name << gain
2093                         << (u8) params.type << pos << params.object
2094                         << params.loop << params.fade << params.pitch;
2095
2096         // Backwards compability
2097         bool play_sound = gain > 0;
2098
2099         for (std::vector<u16>::iterator i = dst_clients.begin();
2100                         i != dst_clients.end(); ++i) {
2101                 if (play_sound || m_clients.getProtocolVersion(*i) >= 32) {
2102                         psound.clients.insert(*i);
2103                         m_clients.send(*i, 0, &pkt, true);
2104                 }
2105         }
2106         return id;
2107 }
2108 void Server::stopSound(s32 handle)
2109 {
2110         // Get sound reference
2111         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2112                 m_playing_sounds.find(handle);
2113         if (i == m_playing_sounds.end())
2114                 return;
2115         ServerPlayingSound &psound = i->second;
2116
2117         NetworkPacket pkt(TOCLIENT_STOP_SOUND, 4);
2118         pkt << handle;
2119
2120         for (std::unordered_set<u16>::const_iterator si = psound.clients.begin();
2121                         si != psound.clients.end(); ++si) {
2122                 // Send as reliable
2123                 m_clients.send(*si, 0, &pkt, true);
2124         }
2125         // Remove sound reference
2126         m_playing_sounds.erase(i);
2127 }
2128
2129 void Server::fadeSound(s32 handle, float step, float gain)
2130 {
2131         // Get sound reference
2132         std::unordered_map<s32, ServerPlayingSound>::iterator i =
2133                 m_playing_sounds.find(handle);
2134         if (i == m_playing_sounds.end())
2135                 return;
2136
2137         ServerPlayingSound &psound = i->second;
2138         psound.params.gain = gain;
2139
2140         NetworkPacket pkt(TOCLIENT_FADE_SOUND, 4);
2141         pkt << handle << step << gain;
2142
2143         // Backwards compability
2144         bool play_sound = gain > 0;
2145         ServerPlayingSound compat_psound = psound;
2146         compat_psound.clients.clear();
2147
2148         NetworkPacket compat_pkt(TOCLIENT_STOP_SOUND, 4);
2149         compat_pkt << handle;
2150
2151         for (std::unordered_set<u16>::iterator it = psound.clients.begin();
2152                         it != psound.clients.end();) {
2153                 if (m_clients.getProtocolVersion(*it) >= 32) {
2154                         // Send as reliable
2155                         m_clients.send(*it, 0, &pkt, true);
2156                         ++it;
2157                 } else {
2158                         compat_psound.clients.insert(*it);
2159                         // Stop old sound
2160                         m_clients.send(*it, 0, &compat_pkt, true);
2161                         psound.clients.erase(it++);
2162                 }
2163         }
2164
2165         // Remove sound reference
2166         if (!play_sound || psound.clients.size() == 0)
2167                 m_playing_sounds.erase(i);
2168
2169         if (play_sound && compat_psound.clients.size() > 0) {
2170                 // Play new sound volume on older clients
2171                 playSound(compat_psound.spec, compat_psound.params);
2172         }
2173 }
2174
2175 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
2176         std::vector<u16> *far_players, float far_d_nodes)
2177 {
2178         float maxd = far_d_nodes*BS;
2179         v3f p_f = intToFloat(p, BS);
2180
2181         NetworkPacket pkt(TOCLIENT_REMOVENODE, 6);
2182         pkt << p;
2183
2184         std::vector<u16> clients = m_clients.getClientIDs();
2185         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
2186                 if (far_players) {
2187                         // Get player
2188                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2189                                 PlayerSAO *sao = player->getPlayerSAO();
2190                                 if (!sao)
2191                                         continue;
2192
2193                                 // If player is far away, only set modified blocks not sent
2194                                 v3f player_pos = sao->getBasePosition();
2195                                 if (player_pos.getDistanceFrom(p_f) > maxd) {
2196                                         far_players->push_back(*i);
2197                                         continue;
2198                                 }
2199                         }
2200                 }
2201
2202                 // Send as reliable
2203                 m_clients.send(*i, 0, &pkt, true);
2204         }
2205 }
2206
2207 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
2208                 std::vector<u16> *far_players, float far_d_nodes,
2209                 bool remove_metadata)
2210 {
2211         float maxd = far_d_nodes*BS;
2212         v3f p_f = intToFloat(p, BS);
2213
2214         std::vector<u16> clients = m_clients.getClientIDs();
2215         for(std::vector<u16>::iterator i = clients.begin();     i != clients.end(); ++i) {
2216                 if (far_players) {
2217                         // Get player
2218                         if (RemotePlayer *player = m_env->getPlayer(*i)) {
2219                                 PlayerSAO *sao = player->getPlayerSAO();
2220                                 if (!sao)
2221                                         continue;
2222
2223                                 // If player is far away, only set modified blocks not sent
2224                                 v3f player_pos = sao->getBasePosition();
2225                                 if(player_pos.getDistanceFrom(p_f) > maxd) {
2226                                         far_players->push_back(*i);
2227                                         continue;
2228                                 }
2229                         }
2230                 }
2231
2232                 NetworkPacket pkt(TOCLIENT_ADDNODE, 6 + 2 + 1 + 1 + 1);
2233                 m_clients.lock();
2234                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
2235                 if (client != 0) {
2236                         pkt << p << n.param0 << n.param1 << n.param2
2237                                         << (u8) (remove_metadata ? 0 : 1);
2238                 }
2239                 m_clients.unlock();
2240
2241                 // Send as reliable
2242                 if (pkt.getSize() > 0)
2243                         m_clients.send(*i, 0, &pkt, true);
2244         }
2245 }
2246
2247 void Server::setBlockNotSent(v3s16 p)
2248 {
2249         std::vector<u16> clients = m_clients.getClientIDs();
2250         m_clients.lock();
2251         for(std::vector<u16>::iterator i = clients.begin();
2252                 i != clients.end(); ++i) {
2253                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2254                 client->SetBlockNotSent(p);
2255         }
2256         m_clients.unlock();
2257 }
2258
2259 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
2260 {
2261         DSTACK(FUNCTION_NAME);
2262
2263         v3s16 p = block->getPos();
2264
2265         /*
2266                 Create a packet with the block in the right format
2267         */
2268
2269         std::ostringstream os(std::ios_base::binary);
2270         block->serialize(os, ver, false);
2271         block->serializeNetworkSpecific(os);
2272         std::string s = os.str();
2273
2274         NetworkPacket pkt(TOCLIENT_BLOCKDATA, 2 + 2 + 2 + 2 + s.size(), peer_id);
2275
2276         pkt << p;
2277         pkt.putRawString(s.c_str(), s.size());
2278         Send(&pkt);
2279 }
2280
2281 void Server::SendBlocks(float dtime)
2282 {
2283         DSTACK(FUNCTION_NAME);
2284
2285         MutexAutoLock envlock(m_env_mutex);
2286         //TODO check if one big lock could be faster then multiple small ones
2287
2288         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
2289
2290         std::vector<PrioritySortedBlockTransfer> queue;
2291
2292         s32 total_sending = 0;
2293
2294         {
2295                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
2296
2297                 std::vector<u16> clients = m_clients.getClientIDs();
2298
2299                 m_clients.lock();
2300                 for(std::vector<u16>::iterator i = clients.begin();
2301                         i != clients.end(); ++i) {
2302                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i, CS_Active);
2303
2304                         if (client == NULL)
2305                                 continue;
2306
2307                         total_sending += client->SendingCount();
2308                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
2309                 }
2310                 m_clients.unlock();
2311         }
2312
2313         // Sort.
2314         // Lowest priority number comes first.
2315         // Lowest is most important.
2316         std::sort(queue.begin(), queue.end());
2317
2318         m_clients.lock();
2319         for(u32 i=0; i<queue.size(); i++)
2320         {
2321                 //TODO: Calculate limit dynamically
2322                 if(total_sending >= g_settings->getS32
2323                                 ("max_simultaneous_block_sends_server_total"))
2324                         break;
2325
2326                 PrioritySortedBlockTransfer q = queue[i];
2327
2328                 MapBlock *block = NULL;
2329                 try
2330                 {
2331                         block = m_env->getMap().getBlockNoCreate(q.pos);
2332                 }
2333                 catch(InvalidPositionException &e)
2334                 {
2335                         continue;
2336                 }
2337
2338                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id, CS_Active);
2339
2340                 if(!client)
2341                         continue;
2342
2343                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
2344
2345                 client->SentBlock(q.pos);
2346                 total_sending++;
2347         }
2348         m_clients.unlock();
2349 }
2350
2351 void Server::fillMediaCache()
2352 {
2353         DSTACK(FUNCTION_NAME);
2354
2355         infostream<<"Server: Calculating media file checksums"<<std::endl;
2356
2357         // Collect all media file paths
2358         std::vector<std::string> paths;
2359         for(std::vector<ModSpec>::iterator i = m_mods.begin();
2360                         i != m_mods.end(); ++i) {
2361                 const ModSpec &mod = *i;
2362                 paths.push_back(mod.path + DIR_DELIM + "textures");
2363                 paths.push_back(mod.path + DIR_DELIM + "sounds");
2364                 paths.push_back(mod.path + DIR_DELIM + "media");
2365                 paths.push_back(mod.path + DIR_DELIM + "models");
2366         }
2367         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
2368
2369         // Collect media file information from paths into cache
2370         for(std::vector<std::string>::iterator i = paths.begin();
2371                         i != paths.end(); ++i) {
2372                 std::string mediapath = *i;
2373                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
2374                 for (u32 j = 0; j < dirlist.size(); j++) {
2375                         if (dirlist[j].dir) // Ignode dirs
2376                                 continue;
2377                         std::string filename = dirlist[j].name;
2378                         // If name contains illegal characters, ignore the file
2379                         if (!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
2380                                 infostream<<"Server: ignoring illegal file name: \""
2381                                                 << filename << "\"" << std::endl;
2382                                 continue;
2383                         }
2384                         // If name is not in a supported format, ignore it
2385                         const char *supported_ext[] = {
2386                                 ".png", ".jpg", ".bmp", ".tga",
2387                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
2388                                 ".ogg",
2389                                 ".x", ".b3d", ".md2", ".obj",
2390                                 NULL
2391                         };
2392                         if (removeStringEnd(filename, supported_ext) == ""){
2393                                 infostream << "Server: ignoring unsupported file extension: \""
2394                                                 << filename << "\"" << std::endl;
2395                                 continue;
2396                         }
2397                         // Ok, attempt to load the file and add to cache
2398                         std::string filepath = mediapath + DIR_DELIM + filename;
2399                         // Read data
2400                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
2401                         if (!fis.good()) {
2402                                 errorstream << "Server::fillMediaCache(): Could not open \""
2403                                                 << filename << "\" for reading" << std::endl;
2404                                 continue;
2405                         }
2406                         std::ostringstream tmp_os(std::ios_base::binary);
2407                         bool bad = false;
2408                         for(;;) {
2409                                 char buf[1024];
2410                                 fis.read(buf, 1024);
2411                                 std::streamsize len = fis.gcount();
2412                                 tmp_os.write(buf, len);
2413                                 if (fis.eof())
2414                                         break;
2415                                 if (!fis.good()) {
2416                                         bad = true;
2417                                         break;
2418                                 }
2419                         }
2420                         if(bad) {
2421                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
2422                                                 << filename << "\"" << std::endl;
2423                                 continue;
2424                         }
2425                         if(tmp_os.str().length() == 0) {
2426                                 errorstream << "Server::fillMediaCache(): Empty file \""
2427                                                 << filepath << "\"" << std::endl;
2428                                 continue;
2429                         }
2430
2431                         SHA1 sha1;
2432                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
2433
2434                         unsigned char *digest = sha1.getDigest();
2435                         std::string sha1_base64 = base64_encode(digest, 20);
2436                         std::string sha1_hex = hex_encode((char*)digest, 20);
2437                         free(digest);
2438
2439                         // Put in list
2440                         m_media[filename] = MediaInfo(filepath, sha1_base64);
2441                         verbosestream << "Server: " << sha1_hex << " is " << filename
2442                                         << std::endl;
2443                 }
2444         }
2445 }
2446
2447 void Server::sendMediaAnnouncement(u16 peer_id)
2448 {
2449         DSTACK(FUNCTION_NAME);
2450
2451         verbosestream << "Server: Announcing files to id(" << peer_id << ")"
2452                 << std::endl;
2453
2454         // Make packet
2455         std::ostringstream os(std::ios_base::binary);
2456
2457         NetworkPacket pkt(TOCLIENT_ANNOUNCE_MEDIA, 0, peer_id);
2458         pkt << (u16) m_media.size();
2459
2460         for (std::unordered_map<std::string, MediaInfo>::iterator i = m_media.begin();
2461                         i != m_media.end(); ++i) {
2462                 pkt << i->first << i->second.sha1_digest;
2463         }
2464
2465         pkt << g_settings->get("remote_media");
2466         Send(&pkt);
2467 }
2468
2469 struct SendableMedia
2470 {
2471         std::string name;
2472         std::string path;
2473         std::string data;
2474
2475         SendableMedia(const std::string &name_="", const std::string &path_="",
2476                       const std::string &data_=""):
2477                 name(name_),
2478                 path(path_),
2479                 data(data_)
2480         {}
2481 };
2482
2483 void Server::sendRequestedMedia(u16 peer_id,
2484                 const std::vector<std::string> &tosend)
2485 {
2486         DSTACK(FUNCTION_NAME);
2487
2488         verbosestream<<"Server::sendRequestedMedia(): "
2489                         <<"Sending files to client"<<std::endl;
2490
2491         /* Read files */
2492
2493         // Put 5kB in one bunch (this is not accurate)
2494         u32 bytes_per_bunch = 5000;
2495
2496         std::vector< std::vector<SendableMedia> > file_bunches;
2497         file_bunches.push_back(std::vector<SendableMedia>());
2498
2499         u32 file_size_bunch_total = 0;
2500
2501         for(std::vector<std::string>::const_iterator i = tosend.begin();
2502                         i != tosend.end(); ++i) {
2503                 const std::string &name = *i;
2504
2505                 if (m_media.find(name) == m_media.end()) {
2506                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
2507                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
2508                         continue;
2509                 }
2510
2511                 //TODO get path + name
2512                 std::string tpath = m_media[name].path;
2513
2514                 // Read data
2515                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
2516                 if(fis.good() == false){
2517                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
2518                                         <<tpath<<"\" for reading"<<std::endl;
2519                         continue;
2520                 }
2521                 std::ostringstream tmp_os(std::ios_base::binary);
2522                 bool bad = false;
2523                 for(;;) {
2524                         char buf[1024];
2525                         fis.read(buf, 1024);
2526                         std::streamsize len = fis.gcount();
2527                         tmp_os.write(buf, len);
2528                         file_size_bunch_total += len;
2529                         if(fis.eof())
2530                                 break;
2531                         if(!fis.good()) {
2532                                 bad = true;
2533                                 break;
2534                         }
2535                 }
2536                 if(bad) {
2537                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
2538                                         <<name<<"\""<<std::endl;
2539                         continue;
2540                 }
2541                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
2542                                 <<tname<<"\""<<std::endl;*/
2543                 // Put in list
2544                 file_bunches[file_bunches.size()-1].push_back(
2545                                 SendableMedia(name, tpath, tmp_os.str()));
2546
2547                 // Start next bunch if got enough data
2548                 if(file_size_bunch_total >= bytes_per_bunch) {
2549                         file_bunches.push_back(std::vector<SendableMedia>());
2550                         file_size_bunch_total = 0;
2551                 }
2552
2553         }
2554
2555         /* Create and send packets */
2556
2557         u16 num_bunches = file_bunches.size();
2558         for(u16 i = 0; i < num_bunches; i++) {
2559                 /*
2560                         u16 command
2561                         u16 total number of texture bunches
2562                         u16 index of this bunch
2563                         u32 number of files in this bunch
2564                         for each file {
2565                                 u16 length of name
2566                                 string name
2567                                 u32 length of data
2568                                 data
2569                         }
2570                 */
2571
2572                 NetworkPacket pkt(TOCLIENT_MEDIA, 4 + 0, peer_id);
2573                 pkt << num_bunches << i << (u32) file_bunches[i].size();
2574
2575                 for(std::vector<SendableMedia>::iterator
2576                                 j = file_bunches[i].begin();
2577                                 j != file_bunches[i].end(); ++j) {
2578                         pkt << j->name;
2579                         pkt.putLongString(j->data);
2580                 }
2581
2582                 verbosestream << "Server::sendRequestedMedia(): bunch "
2583                                 << i << "/" << num_bunches
2584                                 << " files=" << file_bunches[i].size()
2585                                 << " size="  << pkt.getSize() << std::endl;
2586                 Send(&pkt);
2587         }
2588 }
2589
2590 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
2591 {
2592         if(m_detached_inventories.count(name) == 0) {
2593                 errorstream<<FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
2594                 return;
2595         }
2596         Inventory *inv = m_detached_inventories[name];
2597         std::ostringstream os(std::ios_base::binary);
2598
2599         os << serializeString(name);
2600         inv->serialize(os);
2601
2602         // Make data buffer
2603         std::string s = os.str();
2604
2605         NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
2606         pkt.putRawString(s.c_str(), s.size());
2607
2608         const std::string &check = m_detached_inventories_player[name];
2609         if (peer_id == PEER_ID_INEXISTENT) {
2610                 if (check == "")
2611                         return m_clients.sendToAll(&pkt);
2612                 RemotePlayer *p = m_env->getPlayer(check.c_str());
2613                 if (p)
2614                         m_clients.send(p->peer_id, 0, &pkt, true);
2615         } else {
2616                 if (check == "" || getPlayerName(peer_id) == check)
2617                         Send(&pkt);
2618         }
2619 }
2620
2621 void Server::sendDetachedInventories(u16 peer_id)
2622 {
2623         DSTACK(FUNCTION_NAME);
2624
2625         for(std::map<std::string, Inventory*>::iterator
2626                         i = m_detached_inventories.begin();
2627                         i != m_detached_inventories.end(); ++i) {
2628                 const std::string &name = i->first;
2629                 //Inventory *inv = i->second;
2630                 sendDetachedInventory(name, peer_id);
2631         }
2632 }
2633
2634 /*
2635         Something random
2636 */
2637
2638 void Server::DiePlayer(u16 peer_id)
2639 {
2640         DSTACK(FUNCTION_NAME);
2641         PlayerSAO *playersao = getPlayerSAO(peer_id);
2642         // In some rare cases this can be NULL -- if the player is disconnected
2643         // when a Lua function modifies l_punch, for example
2644         if (!playersao)
2645                 return;
2646
2647         infostream << "Server::DiePlayer(): Player "
2648                         << playersao->getPlayer()->getName()
2649                         << " dies" << std::endl;
2650
2651         playersao->setHP(0);
2652
2653         // Trigger scripted stuff
2654         m_script->on_dieplayer(playersao);
2655
2656         SendPlayerHP(peer_id);
2657         SendDeathscreen(peer_id, false, v3f(0,0,0));
2658 }
2659
2660 void Server::RespawnPlayer(u16 peer_id)
2661 {
2662         DSTACK(FUNCTION_NAME);
2663
2664         PlayerSAO *playersao = getPlayerSAO(peer_id);
2665         assert(playersao);
2666
2667         infostream << "Server::RespawnPlayer(): Player "
2668                         << playersao->getPlayer()->getName()
2669                         << " respawns" << std::endl;
2670
2671         playersao->setHP(PLAYER_MAX_HP);
2672         playersao->setBreath(PLAYER_MAX_BREATH);
2673
2674         bool repositioned = m_script->on_respawnplayer(playersao);
2675         if (!repositioned) {
2676                 // setPos will send the new position to client
2677                 playersao->setPos(findSpawnPos());
2678         }
2679
2680         SendPlayerHP(peer_id);
2681 }
2682
2683
2684 void Server::DenySudoAccess(u16 peer_id)
2685 {
2686         DSTACK(FUNCTION_NAME);
2687
2688         NetworkPacket pkt(TOCLIENT_DENY_SUDO_MODE, 0, peer_id);
2689         Send(&pkt);
2690 }
2691
2692
2693 void Server::DenyAccessVerCompliant(u16 peer_id, u16 proto_ver, AccessDeniedCode reason,
2694                 const std::string &str_reason, bool reconnect)
2695 {
2696         if (proto_ver >= 25) {
2697                 SendAccessDenied(peer_id, reason, str_reason, reconnect);
2698         } else {
2699                 std::wstring wreason = utf8_to_wide(
2700                         reason == SERVER_ACCESSDENIED_CUSTOM_STRING ? str_reason :
2701                         accessDeniedStrings[(u8)reason]);
2702                 SendAccessDenied_Legacy(peer_id, wreason);
2703         }
2704
2705         m_clients.event(peer_id, CSE_SetDenied);
2706         m_con.DisconnectPeer(peer_id);
2707 }
2708
2709
2710 void Server::DenyAccess(u16 peer_id, AccessDeniedCode reason, const std::string &custom_reason)
2711 {
2712         DSTACK(FUNCTION_NAME);
2713
2714         SendAccessDenied(peer_id, reason, custom_reason);
2715         m_clients.event(peer_id, CSE_SetDenied);
2716         m_con.DisconnectPeer(peer_id);
2717 }
2718
2719 // 13/03/15: remove this function when protocol version 25 will become
2720 // the minimum version for MT users, maybe in 1 year
2721 void Server::DenyAccess_Legacy(u16 peer_id, const std::wstring &reason)
2722 {
2723         DSTACK(FUNCTION_NAME);
2724
2725         SendAccessDenied_Legacy(peer_id, reason);
2726         m_clients.event(peer_id, CSE_SetDenied);
2727         m_con.DisconnectPeer(peer_id);
2728 }
2729
2730 void Server::acceptAuth(u16 peer_id, bool forSudoMode)
2731 {
2732         DSTACK(FUNCTION_NAME);
2733
2734         if (!forSudoMode) {
2735                 RemoteClient* client = getClient(peer_id, CS_Invalid);
2736
2737                 NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
2738
2739                 // Right now, the auth mechs don't change between login and sudo mode.
2740                 u32 sudo_auth_mechs = client->allowed_auth_mechs;
2741                 client->allowed_sudo_mechs = sudo_auth_mechs;
2742
2743                 resp_pkt << v3f(0,0,0) << (u64) m_env->getServerMap().getSeed()
2744                                 << g_settings->getFloat("dedicated_server_step")
2745                                 << sudo_auth_mechs;
2746
2747                 Send(&resp_pkt);
2748                 m_clients.event(peer_id, CSE_AuthAccept);
2749         } else {
2750                 NetworkPacket resp_pkt(TOCLIENT_ACCEPT_SUDO_MODE, 1 + 6 + 8 + 4, peer_id);
2751
2752                 // We only support SRP right now
2753                 u32 sudo_auth_mechs = AUTH_MECHANISM_FIRST_SRP;
2754
2755                 resp_pkt << sudo_auth_mechs;
2756                 Send(&resp_pkt);
2757                 m_clients.event(peer_id, CSE_SudoSuccess);
2758         }
2759 }
2760
2761 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
2762 {
2763         DSTACK(FUNCTION_NAME);
2764         std::wstring message;
2765         {
2766                 /*
2767                         Clear references to playing sounds
2768                 */
2769                 for (std::unordered_map<s32, ServerPlayingSound>::iterator
2770                                  i = m_playing_sounds.begin(); i != m_playing_sounds.end();) {
2771                         ServerPlayingSound &psound = i->second;
2772                         psound.clients.erase(peer_id);
2773                         if (psound.clients.empty())
2774                                 m_playing_sounds.erase(i++);
2775                         else
2776                                 ++i;
2777                 }
2778
2779                 RemotePlayer *player = m_env->getPlayer(peer_id);
2780
2781                 /* Run scripts and remove from environment */
2782                 if (player != NULL) {
2783                         PlayerSAO *playersao = player->getPlayerSAO();
2784                         assert(playersao);
2785
2786                         // inform connected clients
2787                         NetworkPacket notice(TOCLIENT_UPDATE_PLAYER_LIST, 0, PEER_ID_INEXISTENT);
2788                         // (u16) 1 + std::string represents a vector serialization representation
2789                         notice << (u8) PLAYER_LIST_REMOVE  << (u16) 1 << std::string(playersao->getPlayer()->getName());
2790                         m_clients.sendToAll(&notice);
2791                         // run scripts
2792                         m_script->on_leaveplayer(playersao, reason == CDR_TIMEOUT);
2793
2794                         playersao->disconnected();
2795                 }
2796
2797                 /*
2798                         Print out action
2799                 */
2800                 {
2801                         if(player != NULL && reason != CDR_DENY) {
2802                                 std::ostringstream os(std::ios_base::binary);
2803                                 std::vector<u16> clients = m_clients.getClientIDs();
2804
2805                                 for(std::vector<u16>::iterator i = clients.begin();
2806                                         i != clients.end(); ++i) {
2807                                         // Get player
2808                                         RemotePlayer *player = m_env->getPlayer(*i);
2809                                         if (!player)
2810                                                 continue;
2811
2812                                         // Get name of player
2813                                         os << player->getName() << " ";
2814                                 }
2815
2816                                 std::string name = player->getName();
2817                                 actionstream << name << " "
2818                                                 << (reason == CDR_TIMEOUT ? "times out." : "leaves game.")
2819                                                 << " List of players: " << os.str() << std::endl;
2820                                 if (m_admin_chat)
2821                                         m_admin_chat->outgoing_queue.push_back(
2822                                                 new ChatEventNick(CET_NICK_REMOVE, name));
2823                         }
2824                 }
2825                 {
2826                         MutexAutoLock env_lock(m_env_mutex);
2827                         m_clients.DeleteClient(peer_id);
2828                 }
2829         }
2830
2831         // Send leave chat message to all remaining clients
2832         if (!message.empty()) {
2833                 SendChatMessage(PEER_ID_INEXISTENT,
2834                                 ChatMessage(CHATMESSAGE_TYPE_ANNOUNCE, message));
2835         }
2836 }
2837
2838 void Server::UpdateCrafting(RemotePlayer *player)
2839 {
2840         DSTACK(FUNCTION_NAME);
2841
2842         // Get a preview for crafting
2843         ItemStack preview;
2844         InventoryLocation loc;
2845         loc.setPlayer(player->getName());
2846         std::vector<ItemStack> output_replacements;
2847         getCraftingResult(&player->inventory, preview, output_replacements, false, this);
2848         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(),
2849                         (&player->inventory)->getList("craft"), loc);
2850
2851         // Put the new preview in
2852         InventoryList *plist = player->inventory.getList("craftpreview");
2853         sanity_check(plist);
2854         sanity_check(plist->getSize() >= 1);
2855         plist->changeItem(0, preview);
2856 }
2857
2858 void Server::handleChatInterfaceEvent(ChatEvent *evt)
2859 {
2860         if (evt->type == CET_NICK_ADD) {
2861                 // The terminal informed us of its nick choice
2862                 m_admin_nick = ((ChatEventNick *)evt)->nick;
2863                 if (!m_script->getAuth(m_admin_nick, NULL, NULL)) {
2864                         errorstream << "You haven't set up an account." << std::endl
2865                                 << "Please log in using the client as '"
2866                                 << m_admin_nick << "' with a secure password." << std::endl
2867                                 << "Until then, you can't execute admin tasks via the console," << std::endl
2868                                 << "and everybody can claim the user account instead of you," << std::endl
2869                                 << "giving them full control over this server." << std::endl;
2870                 }
2871         } else {
2872                 assert(evt->type == CET_CHAT);
2873                 handleAdminChat((ChatEventChat *)evt);
2874         }
2875 }
2876
2877 std::wstring Server::handleChat(const std::string &name, const std::wstring &wname,
2878         std::wstring wmessage, bool check_shout_priv, RemotePlayer *player)
2879 {
2880         // If something goes wrong, this player is to blame
2881         RollbackScopeActor rollback_scope(m_rollback,
2882                 std::string("player:") + name);
2883
2884         if (g_settings->getBool("strip_color_codes"))
2885                 wmessage = unescape_enriched(wmessage);
2886
2887         if (player) {
2888                 switch (player->canSendChatMessage()) {
2889                         case RPLAYER_CHATRESULT_FLOODING: {
2890                                 std::wstringstream ws;
2891                                 ws << L"You cannot send more messages. You are limited to "
2892                                    << g_settings->getFloat("chat_message_limit_per_10sec")
2893                                    << L" messages per 10 seconds.";
2894                                 return ws.str();
2895                         }
2896                         case RPLAYER_CHATRESULT_KICK:
2897                                 DenyAccess_Legacy(player->peer_id,
2898                                                 L"You have been kicked due to message flooding.");
2899                                 return L"";
2900                         case RPLAYER_CHATRESULT_OK:
2901                                 break;
2902                         default:
2903                                 FATAL_ERROR("Unhandled chat filtering result found.");
2904                 }
2905         }
2906
2907         if (m_max_chatmessage_length > 0
2908                         && wmessage.length() > m_max_chatmessage_length) {
2909                 return L"Your message exceed the maximum chat message limit set on the server. "
2910                                 L"It was refused. Send a shorter message";
2911         }
2912
2913         // Run script hook, exit if script ate the chat message
2914         if (m_script->on_chat_message(name, wide_to_utf8(wmessage)))
2915                 return L"";
2916
2917         // Line to send
2918         std::wstring line;
2919         // Whether to send line to the player that sent the message, or to all players
2920         bool broadcast_line = true;
2921
2922         if (check_shout_priv && !checkPriv(name, "shout")) {
2923                 line += L"-!- You don't have permission to shout.";
2924                 broadcast_line = false;
2925         } else {
2926                 line += L"<";
2927                 line += wname;
2928                 line += L"> ";
2929                 line += wmessage;
2930         }
2931
2932         /*
2933                 Tell calling method to send the message to sender
2934         */
2935         if (!broadcast_line) {
2936                 return line;
2937         } else {
2938                 /*
2939                         Send the message to others
2940                 */
2941                 actionstream << "CHAT: " << wide_to_narrow(unescape_enriched(line)) << std::endl;
2942
2943                 std::vector<u16> clients = m_clients.getClientIDs();
2944
2945                 /*
2946                         Send the message back to the inital sender
2947                         if they are using protocol version >= 29
2948                 */
2949
2950                 u16 peer_id_to_avoid_sending = (player ? player->peer_id : PEER_ID_INEXISTENT);
2951                 if (player && player->protocol_version >= 29)
2952                         peer_id_to_avoid_sending = PEER_ID_INEXISTENT;
2953
2954                 for (u16 i = 0; i < clients.size(); i++) {
2955                         u16 cid = clients[i];
2956                         if (cid != peer_id_to_avoid_sending)
2957                                 SendChatMessage(cid, ChatMessage(line));
2958                 }
2959         }
2960         return L"";
2961 }
2962
2963 void Server::handleAdminChat(const ChatEventChat *evt)
2964 {
2965         std::string name = evt->nick;
2966         std::wstring wname = utf8_to_wide(name);
2967         std::wstring wmessage = evt->evt_msg;
2968
2969         std::wstring answer = handleChat(name, wname, wmessage);
2970
2971         // If asked to send answer to sender
2972         if (!answer.empty()) {
2973                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", answer));
2974         }
2975 }
2976
2977 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
2978 {
2979         RemoteClient *client = getClientNoEx(peer_id,state_min);
2980         if(!client)
2981                 throw ClientNotFoundException("Client not found");
2982
2983         return client;
2984 }
2985 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
2986 {
2987         return m_clients.getClientNoEx(peer_id, state_min);
2988 }
2989
2990 std::string Server::getPlayerName(u16 peer_id)
2991 {
2992         RemotePlayer *player = m_env->getPlayer(peer_id);
2993         if (player == NULL)
2994                 return "[id="+itos(peer_id)+"]";
2995         return player->getName();
2996 }
2997
2998 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
2999 {
3000         RemotePlayer *player = m_env->getPlayer(peer_id);
3001         if (player == NULL)
3002                 return NULL;
3003         return player->getPlayerSAO();
3004 }
3005
3006 std::wstring Server::getStatusString()
3007 {
3008         std::wostringstream os(std::ios_base::binary);
3009         os<<L"# Server: ";
3010         // Version
3011         os<<L"version="<<narrow_to_wide(g_version_string);
3012         // Uptime
3013         os<<L", uptime="<<m_uptime.get();
3014         // Max lag estimate
3015         os<<L", max_lag="<<m_env->getMaxLagEstimate();
3016         // Information about clients
3017         bool first = true;
3018         os<<L", clients={";
3019         std::vector<u16> clients = m_clients.getClientIDs();
3020         for (std::vector<u16>::iterator i = clients.begin(); i != clients.end(); ++i) {
3021                 // Get player
3022                 RemotePlayer *player = m_env->getPlayer(*i);
3023                 // Get name of player
3024                 std::wstring name = L"unknown";
3025                 if (player != NULL)
3026                         name = narrow_to_wide(player->getName());
3027                 // Add name to information string
3028                 if(!first)
3029                         os << L", ";
3030                 else
3031                         first = false;
3032                 os << name;
3033         }
3034         os << L"}";
3035         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
3036                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
3037         if(g_settings->get("motd") != "")
3038                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
3039         return os.str();
3040 }
3041
3042 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
3043 {
3044         std::set<std::string> privs;
3045         m_script->getAuth(name, NULL, &privs);
3046         return privs;
3047 }
3048
3049 bool Server::checkPriv(const std::string &name, const std::string &priv)
3050 {
3051         std::set<std::string> privs = getPlayerEffectivePrivs(name);
3052         return (privs.count(priv) != 0);
3053 }
3054
3055 void Server::reportPrivsModified(const std::string &name)
3056 {
3057         if(name == "") {
3058                 std::vector<u16> clients = m_clients.getClientIDs();
3059                 for(std::vector<u16>::iterator i = clients.begin();
3060                                 i != clients.end(); ++i) {
3061                         RemotePlayer *player = m_env->getPlayer(*i);
3062                         reportPrivsModified(player->getName());
3063                 }
3064         } else {
3065                 RemotePlayer *player = m_env->getPlayer(name.c_str());
3066                 if (!player)
3067                         return;
3068                 SendPlayerPrivileges(player->peer_id);
3069                 PlayerSAO *sao = player->getPlayerSAO();
3070                 if(!sao)
3071                         return;
3072                 sao->updatePrivileges(
3073                                 getPlayerEffectivePrivs(name),
3074                                 isSingleplayer());
3075         }
3076 }
3077
3078 void Server::reportInventoryFormspecModified(const std::string &name)
3079 {
3080         RemotePlayer *player = m_env->getPlayer(name.c_str());
3081         if (!player)
3082                 return;
3083         SendPlayerInventoryFormspec(player->peer_id);
3084 }
3085
3086 void Server::setIpBanned(const std::string &ip, const std::string &name)
3087 {
3088         m_banmanager->add(ip, name);
3089 }
3090
3091 void Server::unsetIpBanned(const std::string &ip_or_name)
3092 {
3093         m_banmanager->remove(ip_or_name);
3094 }
3095
3096 std::string Server::getBanDescription(const std::string &ip_or_name)
3097 {
3098         return m_banmanager->getBanDescription(ip_or_name);
3099 }
3100
3101 void Server::notifyPlayer(const char *name, const std::wstring &msg)
3102 {
3103         // m_env will be NULL if the server is initializing
3104         if (!m_env)
3105                 return;
3106
3107         if (m_admin_nick == name && !m_admin_nick.empty()) {
3108                 m_admin_chat->outgoing_queue.push_back(new ChatEventChat("", msg));
3109         }
3110
3111         RemotePlayer *player = m_env->getPlayer(name);
3112         if (!player) {
3113                 return;
3114         }
3115
3116         if (player->peer_id == PEER_ID_INEXISTENT)
3117                 return;
3118
3119         SendChatMessage(player->peer_id, ChatMessage(msg));
3120 }
3121
3122 bool Server::showFormspec(const char *playername, const std::string &formspec,
3123         const std::string &formname)
3124 {
3125         // m_env will be NULL if the server is initializing
3126         if (!m_env)
3127                 return false;
3128
3129         RemotePlayer *player = m_env->getPlayer(playername);
3130         if (!player)
3131                 return false;
3132
3133         SendShowFormspecMessage(player->peer_id, formspec, formname);
3134         return true;
3135 }
3136
3137 u32 Server::hudAdd(RemotePlayer *player, HudElement *form)
3138 {
3139         if (!player)
3140                 return -1;
3141
3142         u32 id = player->addHud(form);
3143
3144         SendHUDAdd(player->peer_id, id, form);
3145
3146         return id;
3147 }
3148
3149 bool Server::hudRemove(RemotePlayer *player, u32 id) {
3150         if (!player)
3151                 return false;
3152
3153         HudElement* todel = player->removeHud(id);
3154
3155         if (!todel)
3156                 return false;
3157
3158         delete todel;
3159
3160         SendHUDRemove(player->peer_id, id);
3161         return true;
3162 }
3163
3164 bool Server::hudChange(RemotePlayer *player, u32 id, HudElementStat stat, void *data)
3165 {
3166         if (!player)
3167                 return false;
3168
3169         SendHUDChange(player->peer_id, id, stat, data);
3170         return true;
3171 }
3172
3173 bool Server::hudSetFlags(RemotePlayer *player, u32 flags, u32 mask)
3174 {
3175         if (!player)
3176                 return false;
3177
3178         SendHUDSetFlags(player->peer_id, flags, mask);
3179         player->hud_flags &= ~mask;
3180         player->hud_flags |= flags;
3181
3182         PlayerSAO* playersao = player->getPlayerSAO();
3183
3184         if (playersao == NULL)
3185                 return false;
3186
3187         m_script->player_event(playersao, "hud_changed");
3188         return true;
3189 }
3190
3191 bool Server::hudSetHotbarItemcount(RemotePlayer *player, s32 hotbar_itemcount)
3192 {
3193         if (!player)
3194                 return false;
3195
3196         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
3197                 return false;
3198
3199         player->setHotbarItemcount(hotbar_itemcount);
3200         std::ostringstream os(std::ios::binary);
3201         writeS32(os, hotbar_itemcount);
3202         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
3203         return true;
3204 }
3205
3206 void Server::hudSetHotbarImage(RemotePlayer *player, std::string name)
3207 {
3208         if (!player)
3209                 return;
3210
3211         player->setHotbarImage(name);
3212         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
3213 }
3214
3215 std::string Server::hudGetHotbarImage(RemotePlayer *player)
3216 {
3217         if (!player)
3218                 return "";
3219         return player->getHotbarImage();
3220 }
3221
3222 void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name)
3223 {
3224         if (!player)
3225                 return;
3226
3227         player->setHotbarSelectedImage(name);
3228         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
3229 }
3230
3231 bool Server::setLocalPlayerAnimations(RemotePlayer *player,
3232                 v2s32 animation_frames[4], f32 frame_speed)
3233 {
3234         if (!player)
3235                 return false;
3236
3237         player->setLocalAnimations(animation_frames, frame_speed);
3238         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
3239         return true;
3240 }
3241
3242 bool Server::setPlayerEyeOffset(RemotePlayer *player, v3f first, v3f third)
3243 {
3244         if (!player)
3245                 return false;
3246
3247         player->eye_offset_first = first;
3248         player->eye_offset_third = third;
3249         SendEyeOffset(player->peer_id, first, third);
3250         return true;
3251 }
3252
3253 bool Server::setSky(RemotePlayer *player, const video::SColor &bgcolor,
3254         const std::string &type, const std::vector<std::string> &params,
3255         bool &clouds)
3256 {
3257         if (!player)
3258                 return false;
3259
3260         player->setSky(bgcolor, type, params, clouds);
3261         SendSetSky(player->peer_id, bgcolor, type, params, clouds);
3262         return true;
3263 }
3264
3265 bool Server::setClouds(RemotePlayer *player, float density,
3266         const video::SColor &color_bright,
3267         const video::SColor &color_ambient,
3268         float height,
3269         float thickness,
3270         const v2f &speed)
3271 {
3272         if (!player)
3273                 return false;
3274
3275         SendCloudParams(player->peer_id, density,
3276                         color_bright, color_ambient, height,
3277                         thickness, speed);
3278         return true;
3279 }
3280
3281 bool Server::overrideDayNightRatio(RemotePlayer *player, bool do_override,
3282         float ratio)
3283 {
3284         if (!player)
3285                 return false;
3286
3287         player->overrideDayNightRatio(do_override, ratio);
3288         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
3289         return true;
3290 }
3291
3292 void Server::notifyPlayers(const std::wstring &msg)
3293 {
3294         SendChatMessage(PEER_ID_INEXISTENT, ChatMessage(msg));
3295 }
3296
3297 void Server::spawnParticle(const std::string &playername, v3f pos,
3298         v3f velocity, v3f acceleration,
3299         float expirationtime, float size, bool
3300         collisiondetection, bool collision_removal,
3301         bool vertical, const std::string &texture,
3302         const struct TileAnimationParams &animation, u8 glow)
3303 {
3304         // m_env will be NULL if the server is initializing
3305         if (!m_env)
3306                 return;
3307
3308         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3309         if (playername != "") {
3310                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3311                 if (!player)
3312                         return;
3313                 peer_id = player->peer_id;
3314                 proto_ver = player->protocol_version;
3315         }
3316
3317         SendSpawnParticle(peer_id, proto_ver, pos, velocity, acceleration,
3318                         expirationtime, size, collisiondetection,
3319                         collision_removal, vertical, texture, animation, glow);
3320 }
3321
3322 u32 Server::addParticleSpawner(u16 amount, float spawntime,
3323         v3f minpos, v3f maxpos, v3f minvel, v3f maxvel, v3f minacc, v3f maxacc,
3324         float minexptime, float maxexptime, float minsize, float maxsize,
3325         bool collisiondetection, bool collision_removal,
3326         ServerActiveObject *attached, bool vertical, const std::string &texture,
3327         const std::string &playername, const struct TileAnimationParams &animation,
3328         u8 glow)
3329 {
3330         // m_env will be NULL if the server is initializing
3331         if (!m_env)
3332                 return -1;
3333
3334         u16 peer_id = PEER_ID_INEXISTENT, proto_ver = 0;
3335         if (playername != "") {
3336                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3337                 if (!player)
3338                         return -1;
3339                 peer_id = player->peer_id;
3340                 proto_ver = player->protocol_version;
3341         }
3342
3343         u16 attached_id = attached ? attached->getId() : 0;
3344
3345         u32 id;
3346         if (attached_id == 0)
3347                 id = m_env->addParticleSpawner(spawntime);
3348         else
3349                 id = m_env->addParticleSpawner(spawntime, attached_id);
3350
3351         SendAddParticleSpawner(peer_id, proto_ver, amount, spawntime,
3352                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
3353                 minexptime, maxexptime, minsize, maxsize,
3354                 collisiondetection, collision_removal, attached_id, vertical,
3355                 texture, id, animation, glow);
3356
3357         return id;
3358 }
3359
3360 void Server::deleteParticleSpawner(const std::string &playername, u32 id)
3361 {
3362         // m_env will be NULL if the server is initializing
3363         if (!m_env)
3364                 throw ServerError("Can't delete particle spawners during initialisation!");
3365
3366         u16 peer_id = PEER_ID_INEXISTENT;
3367         if (playername != "") {
3368                 RemotePlayer *player = m_env->getPlayer(playername.c_str());
3369                 if (!player)
3370                         return;
3371                 peer_id = player->peer_id;
3372         }
3373
3374         m_env->deleteParticleSpawner(id);
3375         SendDeleteParticleSpawner(peer_id, id);
3376 }
3377
3378 Inventory* Server::createDetachedInventory(const std::string &name, const std::string &player)
3379 {
3380         if(m_detached_inventories.count(name) > 0){
3381                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
3382                 delete m_detached_inventories[name];
3383         } else {
3384                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
3385         }
3386         Inventory *inv = new Inventory(m_itemdef);
3387         sanity_check(inv);
3388         m_detached_inventories[name] = inv;
3389         m_detached_inventories_player[name] = player;
3390         //TODO find a better way to do this
3391         sendDetachedInventory(name,PEER_ID_INEXISTENT);
3392         return inv;
3393 }
3394
3395 // actions: time-reversed list
3396 // Return value: success/failure
3397 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
3398                 std::list<std::string> *log)
3399 {
3400         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
3401         ServerMap *map = (ServerMap*)(&m_env->getMap());
3402
3403         // Fail if no actions to handle
3404         if(actions.empty()){
3405                 log->push_back("Nothing to do.");
3406                 return false;
3407         }
3408
3409         int num_tried = 0;
3410         int num_failed = 0;
3411
3412         for(std::list<RollbackAction>::const_iterator
3413                         i = actions.begin();
3414                         i != actions.end(); ++i)
3415         {
3416                 const RollbackAction &action = *i;
3417                 num_tried++;
3418                 bool success = action.applyRevert(map, this, this);
3419                 if(!success){
3420                         num_failed++;
3421                         std::ostringstream os;
3422                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
3423                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3424                         if(log)
3425                                 log->push_back(os.str());
3426                 }else{
3427                         std::ostringstream os;
3428                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
3429                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
3430                         if(log)
3431                                 log->push_back(os.str());
3432                 }
3433         }
3434
3435         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
3436                         <<" failed"<<std::endl;
3437
3438         // Call it done if less than half failed
3439         return num_failed <= num_tried/2;
3440 }
3441
3442 // IGameDef interface
3443 // Under envlock
3444 IItemDefManager *Server::getItemDefManager()
3445 {
3446         return m_itemdef;
3447 }
3448
3449 INodeDefManager *Server::getNodeDefManager()
3450 {
3451         return m_nodedef;
3452 }
3453
3454 ICraftDefManager *Server::getCraftDefManager()
3455 {
3456         return m_craftdef;
3457 }
3458
3459 u16 Server::allocateUnknownNodeId(const std::string &name)
3460 {
3461         return m_nodedef->allocateDummy(name);
3462 }
3463
3464 MtEventManager *Server::getEventManager()
3465 {
3466         return m_event;
3467 }
3468
3469 IWritableItemDefManager *Server::getWritableItemDefManager()
3470 {
3471         return m_itemdef;
3472 }
3473
3474 IWritableNodeDefManager *Server::getWritableNodeDefManager()
3475 {
3476         return m_nodedef;
3477 }
3478
3479 IWritableCraftDefManager *Server::getWritableCraftDefManager()
3480 {
3481         return m_craftdef;
3482 }
3483
3484 const ModSpec *Server::getModSpec(const std::string &modname) const
3485 {
3486         std::vector<ModSpec>::const_iterator it;
3487         for (it = m_mods.begin(); it != m_mods.end(); ++it) {
3488                 const ModSpec &mod = *it;
3489                 if (mod.name == modname)
3490                         return &mod;
3491         }
3492         return NULL;
3493 }
3494
3495 void Server::getModNames(std::vector<std::string> &modlist)
3496 {
3497         std::vector<ModSpec>::iterator it;
3498         for (it = m_mods.begin(); it != m_mods.end(); ++it)
3499                 modlist.push_back(it->name);
3500 }
3501
3502 std::string Server::getBuiltinLuaPath()
3503 {
3504         return porting::path_share + DIR_DELIM + "builtin";
3505 }
3506
3507 std::string Server::getModStoragePath() const
3508 {
3509         return m_path_world + DIR_DELIM + "mod_storage";
3510 }
3511
3512 v3f Server::findSpawnPos()
3513 {
3514         ServerMap &map = m_env->getServerMap();
3515         v3f nodeposf;
3516         if (g_settings->getV3FNoEx("static_spawnpoint", nodeposf)) {
3517                 return nodeposf * BS;
3518         }
3519
3520         bool is_good = false;
3521         // Limit spawn range to mapgen edges (determined by 'mapgen_limit')
3522         s32 range_max = map.getMapgenParams()->getSpawnRangeMax();
3523
3524         // Try to find a good place a few times
3525         for(s32 i = 0; i < 4000 && !is_good; i++) {
3526                 s32 range = MYMIN(1 + i, range_max);
3527                 // We're going to try to throw the player to this position
3528                 v2s16 nodepos2d = v2s16(
3529                         -range + (myrand() % (range * 2)),
3530                         -range + (myrand() % (range * 2)));
3531
3532                 // Get spawn level at point
3533                 s16 spawn_level = m_emerge->getSpawnLevelAtPoint(nodepos2d);
3534                 // Continue if MAX_MAP_GENERATION_LIMIT was returned by
3535                 // the mapgen to signify an unsuitable spawn position
3536                 if (spawn_level == MAX_MAP_GENERATION_LIMIT)
3537                         continue;
3538
3539                 v3s16 nodepos(nodepos2d.X, spawn_level, nodepos2d.Y);
3540
3541                 s32 air_count = 0;
3542                 for (s32 i = 0; i < 10; i++) {
3543                         v3s16 blockpos = getNodeBlockPos(nodepos);
3544                         map.emergeBlock(blockpos, true);
3545                         content_t c = map.getNodeNoEx(nodepos).getContent();
3546                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
3547                                 air_count++;
3548                                 if (air_count >= 2) {
3549                                         nodeposf = intToFloat(nodepos, BS);
3550                                         // Don't spawn the player outside map boundaries
3551                                         if (objectpos_over_limit(nodeposf))
3552                                                 continue;
3553                                         is_good = true;
3554                                         break;
3555                                 }
3556                         }
3557                         nodepos.Y++;
3558                 }
3559         }
3560
3561         return nodeposf;
3562 }
3563
3564 void Server::requestShutdown(const std::string &msg, bool reconnect, float delay)
3565 {
3566         m_shutdown_timer = delay;
3567         m_shutdown_msg = msg;
3568         m_shutdown_ask_reconnect = reconnect;
3569
3570         if (delay == 0.0f) {
3571         // No delay, shutdown immediately
3572                 m_shutdown_requested = true;
3573                 // only print to the infostream, a chat message saying
3574                 // "Server Shutting Down" is sent when the server destructs.
3575                 infostream << "*** Immediate Server shutdown requested." << std::endl;
3576         } else if (delay < 0.0f && m_shutdown_timer > 0.0f) {
3577         // Negative delay, cancel shutdown if requested
3578                 m_shutdown_timer = 0.0f;
3579                 m_shutdown_msg = "";
3580                 m_shutdown_ask_reconnect = false;
3581                 m_shutdown_requested = false;
3582                 std::wstringstream ws;
3583
3584                 ws << L"*** Server shutdown canceled.";
3585
3586                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3587                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3588         } else if (delay > 0.0f) {
3589         // Positive delay, tell the clients when the server will shut down
3590                 std::wstringstream ws;
3591
3592                 ws << L"*** Server shutting down in "
3593                                 << duration_to_string(myround(m_shutdown_timer)).c_str()
3594                                 << ".";
3595
3596                 infostream << wide_to_utf8(ws.str()).c_str() << std::endl;
3597                 SendChatMessage(PEER_ID_INEXISTENT, ws.str());
3598         }
3599 }
3600
3601 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version)
3602 {
3603         /*
3604                 Try to get an existing player
3605         */
3606         RemotePlayer *player = m_env->getPlayer(name);
3607
3608         // If player is already connected, cancel
3609         if (player != NULL && player->peer_id != 0) {
3610                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
3611                 return NULL;
3612         }
3613
3614         /*
3615                 If player with the wanted peer_id already exists, cancel.
3616         */
3617         if (m_env->getPlayer(peer_id) != NULL) {
3618                 infostream<<"emergePlayer(): Player with wrong name but same"
3619                                 " peer_id already exists"<<std::endl;
3620                 return NULL;
3621         }
3622
3623         if (!player) {
3624                 player = new RemotePlayer(name, idef());
3625         }
3626
3627         bool newplayer = false;
3628
3629         // Load player
3630         PlayerSAO *playersao = m_env->loadPlayer(player, &newplayer, peer_id, isSingleplayer());
3631
3632         // Complete init with server parts
3633         playersao->finalize(player, getPlayerEffectivePrivs(player->getName()));
3634         player->protocol_version = proto_version;
3635
3636         /* Run scripts */
3637         if (newplayer) {
3638                 m_script->on_newplayer(playersao);
3639         }
3640
3641         return playersao;
3642 }
3643
3644 bool Server::registerModStorage(ModMetadata *storage)
3645 {
3646         if (m_mod_storages.find(storage->getModName()) != m_mod_storages.end()) {
3647                 errorstream << "Unable to register same mod storage twice. Storage name: "
3648                                 << storage->getModName() << std::endl;
3649                 return false;
3650         }
3651
3652         m_mod_storages[storage->getModName()] = storage;
3653         return true;
3654 }
3655
3656 void Server::unregisterModStorage(const std::string &name)
3657 {
3658         std::unordered_map<std::string, ModMetadata *>::const_iterator it = m_mod_storages.find(name);
3659         if (it != m_mod_storages.end()) {
3660                 // Save unconditionaly on unregistration
3661                 it->second->save(getModStoragePath());
3662                 m_mod_storages.erase(name);
3663         }
3664 }
3665
3666 void dedicated_server_loop(Server &server, bool &kill)
3667 {
3668         DSTACK(FUNCTION_NAME);
3669
3670         verbosestream<<"dedicated_server_loop()"<<std::endl;
3671
3672         IntervalLimiter m_profiler_interval;
3673
3674         static thread_local const float steplen =
3675                         g_settings->getFloat("dedicated_server_step");
3676         static thread_local const float profiler_print_interval =
3677                         g_settings->getFloat("profiler_print_interval");
3678
3679         for(;;) {
3680                 // This is kind of a hack but can be done like this
3681                 // because server.step() is very light
3682                 {
3683                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
3684                         sleep_ms((int)(steplen*1000.0));
3685                 }
3686                 server.step(steplen);
3687
3688                 if (server.getShutdownRequested() || kill)
3689                         break;
3690
3691                 /*
3692                         Profiler
3693                 */
3694                 if (profiler_print_interval != 0) {
3695                         if(m_profiler_interval.step(steplen, profiler_print_interval))
3696                         {
3697                                 infostream<<"Profiler:"<<std::endl;
3698                                 g_profiler->print(infostream);
3699                                 g_profiler->clear();
3700                         }
3701                 }
3702         }
3703
3704         infostream << "Dedicated server quitting" << std::endl;
3705 #if USE_CURL
3706         if (g_settings->getBool("server_announce"))
3707                 ServerList::sendAnnounce(ServerList::AA_DELETE,
3708                         server.m_bind_addr.getPort());
3709 #endif
3710 }