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