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