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