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