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