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