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