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