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