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