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