]> git.lizzy.rs Git - dragonfireclient.git/blob - src/server.cpp
Fix heart + bubble bar size on different texture packs
[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 "clientserver.h"
25 #include "ban.h"
26 #include "environment.h"
27 #include "map.h"
28 #include "jthread/jmutexautolock.h"
29 #include "main.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 "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 "sha1.h"
54 #include "base64.h"
55 #include "tool.h"
56 #include "sound.h" // dummySoundManager
57 #include "event_manager.h"
58 #include "hex.h"
59 #include "serverlist.h"
60 #include "util/string.h"
61 #include "util/pointedthing.h"
62 #include "util/mathconstants.h"
63 #include "rollback.h"
64 #include "util/serialize.h"
65 #include "util/thread.h"
66 #include "defaultsettings.h"
67
68 class ClientNotFoundException : public BaseException
69 {
70 public:
71         ClientNotFoundException(const char *s):
72                 BaseException(s)
73         {}
74 };
75
76 class ServerThread : public JThread
77 {
78         Server *m_server;
79
80 public:
81
82         ServerThread(Server *server):
83                 JThread(),
84                 m_server(server)
85         {
86         }
87
88         void * Thread();
89 };
90
91 void * ServerThread::Thread()
92 {
93         log_register_thread("ServerThread");
94
95         DSTACK(__FUNCTION_NAME);
96         BEGIN_DEBUG_EXCEPTION_HANDLER
97
98         m_server->AsyncRunStep(true);
99
100         ThreadStarted();
101
102         porting::setThreadName("ServerThread");
103
104         while(!StopRequested())
105         {
106                 try{
107                         //TimeTaker timer("AsyncRunStep() + Receive()");
108
109                         m_server->AsyncRunStep();
110
111                         m_server->Receive();
112
113                 }
114                 catch(con::NoIncomingDataException &e)
115                 {
116                 }
117                 catch(con::PeerNotFoundException &e)
118                 {
119                         infostream<<"Server: PeerNotFoundException"<<std::endl;
120                 }
121                 catch(ClientNotFoundException &e)
122                 {
123                 }
124                 catch(con::ConnectionBindFailed &e)
125                 {
126                         m_server->setAsyncFatalError(e.what());
127                 }
128                 catch(LuaError &e)
129                 {
130                         m_server->setAsyncFatalError(e.what());
131                 }
132         }
133
134         END_DEBUG_EXCEPTION_HANDLER(errorstream)
135
136         return NULL;
137 }
138
139 v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
140 {
141         if(pos_exists) *pos_exists = false;
142         switch(type){
143         case SSP_LOCAL:
144                 return v3f(0,0,0);
145         case SSP_POSITIONAL:
146                 if(pos_exists) *pos_exists = true;
147                 return pos;
148         case SSP_OBJECT: {
149                 if(object == 0)
150                         return v3f(0,0,0);
151                 ServerActiveObject *sao = env->getActiveObject(object);
152                 if(!sao)
153                         return v3f(0,0,0);
154                 if(pos_exists) *pos_exists = true;
155                 return sao->getBasePosition(); }
156         }
157         return v3f(0,0,0);
158 }
159
160
161
162 /*
163         Server
164 */
165
166 Server::Server(
167                 const std::string &path_world,
168                 const SubgameSpec &gamespec,
169                 bool simple_singleplayer_mode,
170                 bool ipv6
171         ):
172         m_path_world(path_world),
173         m_gamespec(gamespec),
174         m_simple_singleplayer_mode(simple_singleplayer_mode),
175         m_async_fatal_error(""),
176         m_env(NULL),
177         m_con(PROTOCOL_ID,
178                         512,
179                         CONNECTION_TIMEOUT,
180                         ipv6,
181                         this),
182         m_banmanager(NULL),
183         m_rollback(NULL),
184         m_rollback_sink_enabled(true),
185         m_enable_rollback_recording(false),
186         m_emerge(NULL),
187         m_script(NULL),
188         m_itemdef(createItemDefManager()),
189         m_nodedef(createNodeDefManager()),
190         m_craftdef(createCraftDefManager()),
191         m_event(new EventManager()),
192         m_thread(NULL),
193         m_time_of_day_send_timer(0),
194         m_uptime(0),
195         m_clients(&m_con),
196         m_shutdown_requested(false),
197         m_ignore_map_edit_events(false),
198         m_ignore_map_edit_events_peer_id(0)
199
200 {
201         m_liquid_transform_timer = 0.0;
202         m_liquid_transform_every = 1.0;
203         m_print_info_timer = 0.0;
204         m_masterserver_timer = 0.0;
205         m_objectdata_timer = 0.0;
206         m_emergethread_trigger_timer = 0.0;
207         m_savemap_timer = 0.0;
208
209         m_step_dtime = 0.0;
210         m_lag = g_settings->getFloat("dedicated_server_step");
211
212         if(path_world == "")
213                 throw ServerError("Supplied empty world path");
214
215         if(!gamespec.isValid())
216                 throw ServerError("Supplied invalid gamespec");
217
218         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
219         if(m_simple_singleplayer_mode)
220                 infostream<<" in simple singleplayer mode"<<std::endl;
221         else
222                 infostream<<std::endl;
223         infostream<<"- world:  "<<m_path_world<<std::endl;
224         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
225
226         // Initialize default settings and override defaults with those provided
227         // by the game
228         set_default_settings(g_settings);
229         Settings gamedefaults;
230         getGameMinetestConfig(gamespec.path, gamedefaults);
231         override_default_settings(g_settings, &gamedefaults);
232
233         // Create server thread
234         m_thread = new ServerThread(this);
235
236         // Create emerge manager
237         m_emerge = new EmergeManager(this);
238
239         // Create world if it doesn't exist
240         if(!initializeWorld(m_path_world, m_gamespec.id))
241                 throw ServerError("Failed to initialize world");
242
243         // Create ban manager
244         std::string ban_path = m_path_world+DIR_DELIM+"ipban.txt";
245         m_banmanager = new BanManager(ban_path);
246
247         // Create rollback manager
248         std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
249         m_rollback = createRollbackManager(rollback_path, this);
250
251         ModConfiguration modconf(m_path_world);
252         m_mods = modconf.getMods();
253         std::vector<ModSpec> unsatisfied_mods = modconf.getUnsatisfiedMods();
254         // complain about mods with unsatisfied dependencies
255         if(!modconf.isConsistent())
256         {
257                 for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
258                         it != unsatisfied_mods.end(); ++it)
259                 {
260                         ModSpec mod = *it;
261                         errorstream << "mod \"" << mod.name << "\" has unsatisfied dependencies: ";
262                         for(std::set<std::string>::iterator dep_it = mod.unsatisfied_depends.begin();
263                                 dep_it != mod.unsatisfied_depends.end(); ++dep_it)
264                                 errorstream << " \"" << *dep_it << "\"";
265                         errorstream << std::endl;
266                 }
267         }
268
269         Settings worldmt_settings;
270         std::string worldmt = m_path_world + DIR_DELIM + "world.mt";
271         worldmt_settings.readConfigFile(worldmt.c_str());
272         std::vector<std::string> names = worldmt_settings.getNames();
273         std::set<std::string> load_mod_names;
274         for(std::vector<std::string>::iterator it = names.begin();
275                 it != names.end(); ++it)
276         {
277                 std::string name = *it;
278                 if(name.compare(0,9,"load_mod_")==0 && worldmt_settings.getBool(name))
279                         load_mod_names.insert(name.substr(9));
280         }
281         // complain about mods declared to be loaded, but not found
282         for(std::vector<ModSpec>::iterator it = m_mods.begin();
283                         it != m_mods.end(); ++it)
284                 load_mod_names.erase((*it).name);
285         for(std::vector<ModSpec>::iterator it = unsatisfied_mods.begin();
286                         it != unsatisfied_mods.end(); ++it)
287                 load_mod_names.erase((*it).name);
288         if(!load_mod_names.empty())
289         {
290                 errorstream << "The following mods could not be found:";
291                 for(std::set<std::string>::iterator it = load_mod_names.begin();
292                         it != load_mod_names.end(); ++it)
293                         errorstream << " \"" << (*it) << "\"";
294                 errorstream << std::endl;
295         }
296
297         // Path to builtin.lua
298         std::string builtinpath = getBuiltinLuaPath() + DIR_DELIM + "builtin.lua";
299
300         // Lock environment
301         JMutexAutoLock envlock(m_env_mutex);
302
303         // Initialize scripting
304         infostream<<"Server: Initializing Lua"<<std::endl;
305
306         m_script = new GameScripting(this);
307
308
309         // Load and run builtin.lua
310         infostream<<"Server: Loading builtin.lua [\""
311                         <<builtinpath<<"\"]"<<std::endl;
312         bool success = m_script->loadMod(builtinpath, "__builtin");
313         if(!success){
314                 errorstream<<"Server: Failed to load and run "
315                                 <<builtinpath<<std::endl;
316                 throw ModError("Failed to load and run "+builtinpath);
317         }
318         // Print 'em
319         infostream<<"Server: Loading mods: ";
320         for(std::vector<ModSpec>::iterator i = m_mods.begin();
321                         i != m_mods.end(); i++){
322                 const ModSpec &mod = *i;
323                 infostream<<mod.name<<" ";
324         }
325         infostream<<std::endl;
326         // Load and run "mod" scripts
327         for(std::vector<ModSpec>::iterator i = m_mods.begin();
328                         i != m_mods.end(); i++){
329                 const ModSpec &mod = *i;
330                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
331                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
332                                 <<scriptpath<<"\"]"<<std::endl;
333                 bool success = m_script->loadMod(scriptpath, mod.name);
334                 if(!success){
335                         errorstream<<"Server: Failed to load and run "
336                                         <<scriptpath<<std::endl;
337                         throw ModError("Failed to load and run "+scriptpath);
338                 }
339         }
340
341         // Read Textures and calculate sha1 sums
342         fillMediaCache();
343
344         // Apply item aliases in the node definition manager
345         m_nodedef->updateAliases(m_itemdef);
346
347         // Load the mapgen params from global settings now after any
348         // initial overrides have been set by the mods
349         m_emerge->loadMapgenParams();
350
351         // Initialize Environment
352         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
353         m_env = new ServerEnvironment(servermap, m_script, this);
354
355         m_clients.setEnv(m_env);
356
357         // Run some callbacks after the MG params have been set up but before activation
358         m_script->environment_OnMapgenInit(&m_emerge->params);
359
360         // Initialize mapgens
361         m_emerge->initMapgens();
362
363         // Give environment reference to scripting api
364         m_script->initializeEnvironment(m_env);
365
366         // Register us to receive map edit events
367         servermap->addEventReceiver(this);
368
369         // If file exists, load environment metadata
370         if(fs::PathExists(m_path_world+DIR_DELIM+"env_meta.txt"))
371         {
372                 infostream<<"Server: Loading environment metadata"<<std::endl;
373                 m_env->loadMeta(m_path_world);
374         }
375
376         // Load players
377         infostream<<"Server: Loading players"<<std::endl;
378         m_env->deSerializePlayers(m_path_world);
379
380         /*
381                 Add some test ActiveBlockModifiers to environment
382         */
383         add_legacy_abms(m_env, m_nodedef);
384
385         m_liquid_transform_every = g_settings->getFloat("liquid_update");
386 }
387
388 Server::~Server()
389 {
390         infostream<<"Server destructing"<<std::endl;
391
392         /*
393                 Send shutdown message
394         */
395         {
396                 std::wstring line = L"*** Server shutting down";
397                 SendChatMessage(PEER_ID_INEXISTENT, line);
398         }
399
400         {
401                 JMutexAutoLock envlock(m_env_mutex);
402
403                 /*
404                         Execute script shutdown hooks
405                 */
406                 m_script->on_shutdown();
407         }
408
409         {
410                 JMutexAutoLock envlock(m_env_mutex);
411
412                 /*
413                         Save players
414                 */
415                 infostream<<"Server: Saving players"<<std::endl;
416                 m_env->serializePlayers(m_path_world);
417
418                 /*
419                         Save environment metadata
420                 */
421                 infostream<<"Server: Saving environment metadata"<<std::endl;
422                 m_env->saveMeta(m_path_world);
423         }
424
425         /*
426                 Stop threads
427         */
428         stop();
429         delete m_thread;
430
431         // stop all emerge threads before deleting players that may have
432         // requested blocks to be emerged
433         m_emerge->stopThreads();
434
435         // Delete things in the reverse order of creation
436         delete m_env;
437
438         // N.B. the EmergeManager should be deleted after the Environment since Map
439         // depends on EmergeManager to write its current params to the map meta
440         delete m_emerge;
441         delete m_rollback;
442         delete m_banmanager;
443         delete m_event;
444         delete m_itemdef;
445         delete m_nodedef;
446         delete m_craftdef;
447
448         // Deinitialize scripting
449         infostream<<"Server: Deinitializing scripting"<<std::endl;
450         delete m_script;
451
452         // Delete detached inventories
453         {
454                 for(std::map<std::string, Inventory*>::iterator
455                                 i = m_detached_inventories.begin();
456                                 i != m_detached_inventories.end(); i++){
457                         delete i->second;
458                 }
459         }
460 }
461
462 void Server::start(Address bind_addr)
463 {
464         DSTACK(__FUNCTION_NAME);
465         infostream<<"Starting server on "
466                         << bind_addr.serializeString() <<"..."<<std::endl;
467
468         // Stop thread if already running
469         m_thread->Stop();
470
471         // Initialize connection
472         m_con.SetTimeoutMs(30);
473         m_con.Serve(bind_addr);
474
475         // Start thread
476         m_thread->Start();
477
478         // ASCII art for the win!
479         actionstream
480         <<"        .__               __                   __   "<<std::endl
481         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
482         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
483         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
484         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
485         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
486         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
487         actionstream<<"Server for gameid=\""<<m_gamespec.id
488                         <<"\" listening on "<<bind_addr.serializeString()<<":"
489                         <<bind_addr.getPort() << "."<<std::endl;
490 }
491
492 void Server::stop()
493 {
494         DSTACK(__FUNCTION_NAME);
495
496         infostream<<"Server: Stopping and waiting threads"<<std::endl;
497
498         // Stop threads (set run=false first so both start stopping)
499         m_thread->Stop();
500         //m_emergethread.setRun(false);
501         m_thread->Wait();
502         //m_emergethread.stop();
503
504         infostream<<"Server: Threads stopped"<<std::endl;
505 }
506
507 void Server::step(float dtime)
508 {
509         DSTACK(__FUNCTION_NAME);
510         // Limit a bit
511         if(dtime > 2.0)
512                 dtime = 2.0;
513         {
514                 JMutexAutoLock lock(m_step_dtime_mutex);
515                 m_step_dtime += dtime;
516         }
517         // Throw if fatal error occurred in thread
518         std::string async_err = m_async_fatal_error.get();
519         if(async_err != ""){
520                 throw ServerError(async_err);
521         }
522 }
523
524 void Server::AsyncRunStep(bool initial_step)
525 {
526         DSTACK(__FUNCTION_NAME);
527
528         g_profiler->add("Server::AsyncRunStep (num)", 1);
529
530         float dtime;
531         {
532                 JMutexAutoLock lock1(m_step_dtime_mutex);
533                 dtime = m_step_dtime;
534         }
535
536         {
537                 // Send blocks to clients
538                 SendBlocks(dtime);
539         }
540
541         if((dtime < 0.001) && (initial_step == false))
542                 return;
543
544         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
545
546         //infostream<<"Server steps "<<dtime<<std::endl;
547         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
548
549         {
550                 JMutexAutoLock lock1(m_step_dtime_mutex);
551                 m_step_dtime -= dtime;
552         }
553
554         /*
555                 Update uptime
556         */
557         {
558                 m_uptime.set(m_uptime.get() + dtime);
559         }
560
561         handlePeerChanges();
562
563         /*
564                 Update time of day and overall game time
565         */
566         {
567                 JMutexAutoLock envlock(m_env_mutex);
568
569                 m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
570
571                 /*
572                         Send to clients at constant intervals
573                 */
574
575                 m_time_of_day_send_timer -= dtime;
576                 if(m_time_of_day_send_timer < 0.0)
577                 {
578                         m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
579                         u16 time = m_env->getTimeOfDay();
580                         float time_speed = g_settings->getFloat("time_speed");
581                         SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
582                 }
583         }
584
585         {
586                 JMutexAutoLock lock(m_env_mutex);
587                 // Figure out and report maximum lag to environment
588                 float max_lag = m_env->getMaxLagEstimate();
589                 max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
590                 if(dtime > max_lag){
591                         if(dtime > 0.1 && dtime > max_lag * 2.0)
592                                 infostream<<"Server: Maximum lag peaked to "<<dtime
593                                                 <<" s"<<std::endl;
594                         max_lag = dtime;
595                 }
596                 m_env->reportMaxLagEstimate(max_lag);
597                 // Step environment
598                 ScopeProfiler sp(g_profiler, "SEnv step");
599                 ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
600                 m_env->step(dtime);
601         }
602
603         const float map_timer_and_unload_dtime = 2.92;
604         if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
605         {
606                 JMutexAutoLock lock(m_env_mutex);
607                 // Run Map's timers and unload unused data
608                 ScopeProfiler sp(g_profiler, "Server: map timer and unload");
609                 m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
610                                 g_settings->getFloat("server_unload_unused_data_timeout"));
611         }
612
613         /*
614                 Do background stuff
615         */
616
617         /*
618                 Handle players
619         */
620         {
621                 JMutexAutoLock lock(m_env_mutex);
622
623                 std::list<u16> clientids = m_clients.getClientIDs();
624
625                 ScopeProfiler sp(g_profiler, "Server: handle players");
626
627                 for(std::list<u16>::iterator
628                         i = clientids.begin();
629                         i != clientids.end(); ++i)
630                 {
631                         PlayerSAO *playersao = getPlayerSAO(*i);
632                         if(playersao == NULL)
633                                 continue;
634
635                         /*
636                                 Handle player HPs (die if hp=0)
637                         */
638                         if(playersao->m_hp_not_sent && g_settings->getBool("enable_damage"))
639                         {
640                                 if(playersao->getHP() == 0)
641                                         DiePlayer(*i);
642                                 else
643                                         SendPlayerHP(*i);
644                         }
645
646                         /*
647                                 Send player breath if changed
648                         */
649                         if(playersao->m_breath_not_sent) {
650                                 SendPlayerBreath(*i);
651                         }
652
653                         /*
654                                 Send player inventories if necessary
655                         */
656                         if(playersao->m_moved){
657                                 SendMovePlayer(*i);
658                                 playersao->m_moved = false;
659                         }
660                         if(playersao->m_inventory_not_sent){
661                                 UpdateCrafting(*i);
662                                 SendInventory(*i);
663                         }
664                 }
665         }
666
667         /* Transform liquids */
668         m_liquid_transform_timer += dtime;
669         if(m_liquid_transform_timer >= m_liquid_transform_every)
670         {
671                 m_liquid_transform_timer -= m_liquid_transform_every;
672
673                 JMutexAutoLock lock(m_env_mutex);
674
675                 ScopeProfiler sp(g_profiler, "Server: liquid transform");
676
677                 std::map<v3s16, MapBlock*> modified_blocks;
678                 m_env->getMap().transformLiquids(modified_blocks);
679 #if 0
680                 /*
681                         Update lighting
682                 */
683                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
684                 ServerMap &map = ((ServerMap&)m_env->getMap());
685                 map.updateLighting(modified_blocks, lighting_modified_blocks);
686
687                 // Add blocks modified by lighting to modified_blocks
688                 for(core::map<v3s16, MapBlock*>::Iterator
689                                 i = lighting_modified_blocks.getIterator();
690                                 i.atEnd() == false; i++)
691                 {
692                         MapBlock *block = i.getNode()->getValue();
693                         modified_blocks.insert(block->getPos(), block);
694                 }
695 #endif
696                 /*
697                         Set the modified blocks unsent for all the clients
698                 */
699                 if(modified_blocks.size() > 0)
700                 {
701                         SetBlocksNotSent(modified_blocks);
702                 }
703         }
704         m_clients.step(dtime);
705
706         m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
707 #if USE_CURL
708         // send masterserver announce
709         {
710                 float &counter = m_masterserver_timer;
711                 if(!isSingleplayer() && (!counter || counter >= 300.0) &&
712                                 g_settings->getBool("server_announce") == true)
713                 {
714                         ServerList::sendAnnounce(!counter ? "start" : "update",
715                                                                                 m_clients.getPlayerNames(),
716                                                                                 m_uptime.get(),
717                                                                                 m_env->getGameTime(),
718                                                                                 m_lag,
719                                                                                 m_gamespec.id,
720                                                                                 m_mods);
721                         counter = 0.01;
722                 }
723                 counter += dtime;
724         }
725 #endif
726
727         /*
728                 Check added and deleted active objects
729         */
730         {
731                 //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
732                 JMutexAutoLock envlock(m_env_mutex);
733
734                 m_clients.Lock();
735                 std::map<u16, RemoteClient*> clients = m_clients.getClientList();
736                 ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
737
738                 // Radius inside which objects are active
739                 s16 radius = g_settings->getS16("active_object_send_range_blocks");
740                 radius *= MAP_BLOCKSIZE;
741
742                 for(std::map<u16, RemoteClient*>::iterator
743                         i = clients.begin();
744                         i != clients.end(); ++i)
745                 {
746                         RemoteClient *client = i->second;
747
748                         // If definitions and textures have not been sent, don't
749                         // send objects either
750                         if (client->getState() < DefinitionsSent)
751                                 continue;
752
753                         Player *player = m_env->getPlayer(client->peer_id);
754                         if(player==NULL)
755                         {
756                                 // This can happen if the client timeouts somehow
757                                 /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
758                                                 <<client->peer_id
759                                                 <<" has no associated player"<<std::endl;*/
760                                 continue;
761                         }
762                         v3s16 pos = floatToInt(player->getPosition(), BS);
763
764                         std::set<u16> removed_objects;
765                         std::set<u16> added_objects;
766                         m_env->getRemovedActiveObjects(pos, radius,
767                                         client->m_known_objects, removed_objects);
768                         m_env->getAddedActiveObjects(pos, radius,
769                                         client->m_known_objects, added_objects);
770
771                         // Ignore if nothing happened
772                         if(removed_objects.size() == 0 && added_objects.size() == 0)
773                         {
774                                 //infostream<<"active objects: none changed"<<std::endl;
775                                 continue;
776                         }
777
778                         std::string data_buffer;
779
780                         char buf[4];
781
782                         // Handle removed objects
783                         writeU16((u8*)buf, removed_objects.size());
784                         data_buffer.append(buf, 2);
785                         for(std::set<u16>::iterator
786                                         i = removed_objects.begin();
787                                         i != removed_objects.end(); ++i)
788                         {
789                                 // Get object
790                                 u16 id = *i;
791                                 ServerActiveObject* obj = m_env->getActiveObject(id);
792
793                                 // Add to data buffer for sending
794                                 writeU16((u8*)buf, id);
795                                 data_buffer.append(buf, 2);
796
797                                 // Remove from known objects
798                                 client->m_known_objects.erase(id);
799
800                                 if(obj && obj->m_known_by_count > 0)
801                                         obj->m_known_by_count--;
802                         }
803
804                         // Handle added objects
805                         writeU16((u8*)buf, added_objects.size());
806                         data_buffer.append(buf, 2);
807                         for(std::set<u16>::iterator
808                                         i = added_objects.begin();
809                                         i != added_objects.end(); ++i)
810                         {
811                                 // Get object
812                                 u16 id = *i;
813                                 ServerActiveObject* obj = m_env->getActiveObject(id);
814
815                                 // Get object type
816                                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
817                                 if(obj == NULL)
818                                         infostream<<"WARNING: "<<__FUNCTION_NAME
819                                                         <<": NULL object"<<std::endl;
820                                 else
821                                         type = obj->getSendType();
822
823                                 // Add to data buffer for sending
824                                 writeU16((u8*)buf, id);
825                                 data_buffer.append(buf, 2);
826                                 writeU8((u8*)buf, type);
827                                 data_buffer.append(buf, 1);
828
829                                 if(obj)
830                                         data_buffer.append(serializeLongString(
831                                                         obj->getClientInitializationData(client->net_proto_version)));
832                                 else
833                                         data_buffer.append(serializeLongString(""));
834
835                                 // Add to known objects
836                                 client->m_known_objects.insert(id);
837
838                                 if(obj)
839                                         obj->m_known_by_count++;
840                         }
841
842                         // Send packet
843                         SharedBuffer<u8> reply(2 + data_buffer.size());
844                         writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
845                         memcpy((char*)&reply[2], data_buffer.c_str(),
846                                         data_buffer.size());
847                         // Send as reliable
848                         m_clients.send(client->peer_id, 0, reply, true);
849
850                         verbosestream<<"Server: Sent object remove/add: "
851                                         <<removed_objects.size()<<" removed, "
852                                         <<added_objects.size()<<" added, "
853                                         <<"packet size is "<<reply.getSize()<<std::endl;
854                 }
855                 m_clients.Unlock();
856 #if 0
857                 /*
858                         Collect a list of all the objects known by the clients
859                         and report it back to the environment.
860                 */
861
862                 core::map<u16, bool> all_known_objects;
863
864                 for(core::map<u16, RemoteClient*>::Iterator
865                         i = m_clients.getIterator();
866                         i.atEnd() == false; i++)
867                 {
868                         RemoteClient *client = i.getNode()->getValue();
869                         // Go through all known objects of client
870                         for(core::map<u16, bool>::Iterator
871                                         i = client->m_known_objects.getIterator();
872                                         i.atEnd()==false; i++)
873                         {
874                                 u16 id = i.getNode()->getKey();
875                                 all_known_objects[id] = true;
876                         }
877                 }
878
879                 m_env->setKnownActiveObjects(whatever);
880 #endif
881
882         }
883
884         /*
885                 Send object messages
886         */
887         {
888                 JMutexAutoLock envlock(m_env_mutex);
889                 ScopeProfiler sp(g_profiler, "Server: sending object messages");
890
891                 // Key = object id
892                 // Value = data sent by object
893                 std::map<u16, std::list<ActiveObjectMessage>* > buffered_messages;
894
895                 // Get active object messages from environment
896                 for(;;)
897                 {
898                         ActiveObjectMessage aom = m_env->getActiveObjectMessage();
899                         if(aom.id == 0)
900                                 break;
901
902                         std::list<ActiveObjectMessage>* message_list = NULL;
903                         std::map<u16, std::list<ActiveObjectMessage>* >::iterator n;
904                         n = buffered_messages.find(aom.id);
905                         if(n == buffered_messages.end())
906                         {
907                                 message_list = new std::list<ActiveObjectMessage>;
908                                 buffered_messages[aom.id] = message_list;
909                         }
910                         else
911                         {
912                                 message_list = n->second;
913                         }
914                         message_list->push_back(aom);
915                 }
916
917                 m_clients.Lock();
918                 std::map<u16, RemoteClient*> clients = m_clients.getClientList();
919                 // Route data to every client
920                 for(std::map<u16, RemoteClient*>::iterator
921                         i = clients.begin();
922                         i != clients.end(); ++i)
923                 {
924                         RemoteClient *client = i->second;
925                         std::string reliable_data;
926                         std::string unreliable_data;
927                         // Go through all objects in message buffer
928                         for(std::map<u16, std::list<ActiveObjectMessage>* >::iterator
929                                         j = buffered_messages.begin();
930                                         j != buffered_messages.end(); ++j)
931                         {
932                                 // If object is not known by client, skip it
933                                 u16 id = j->first;
934                                 if(client->m_known_objects.find(id) == client->m_known_objects.end())
935                                         continue;
936                                 // Get message list of object
937                                 std::list<ActiveObjectMessage>* list = j->second;
938                                 // Go through every message
939                                 for(std::list<ActiveObjectMessage>::iterator
940                                                 k = list->begin(); k != list->end(); ++k)
941                                 {
942                                         // Compose the full new data with header
943                                         ActiveObjectMessage aom = *k;
944                                         std::string new_data;
945                                         // Add object id
946                                         char buf[2];
947                                         writeU16((u8*)&buf[0], aom.id);
948                                         new_data.append(buf, 2);
949                                         // Add data
950                                         new_data += serializeString(aom.datastring);
951                                         // Add data to buffer
952                                         if(aom.reliable)
953                                                 reliable_data += new_data;
954                                         else
955                                                 unreliable_data += new_data;
956                                 }
957                         }
958                         /*
959                                 reliable_data and unreliable_data are now ready.
960                                 Send them.
961                         */
962                         if(reliable_data.size() > 0)
963                         {
964                                 SharedBuffer<u8> reply(2 + reliable_data.size());
965                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
966                                 memcpy((char*)&reply[2], reliable_data.c_str(),
967                                                 reliable_data.size());
968                                 // Send as reliable
969                                 m_clients.send(client->peer_id, 0, reply, true);
970                         }
971                         if(unreliable_data.size() > 0)
972                         {
973                                 SharedBuffer<u8> reply(2 + unreliable_data.size());
974                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
975                                 memcpy((char*)&reply[2], unreliable_data.c_str(),
976                                                 unreliable_data.size());
977                                 // Send as unreliable
978                                 m_clients.send(client->peer_id, 1, reply, false);
979                         }
980
981                         /*if(reliable_data.size() > 0 || unreliable_data.size() > 0)
982                         {
983                                 infostream<<"Server: Size of object message data: "
984                                                 <<"reliable: "<<reliable_data.size()
985                                                 <<", unreliable: "<<unreliable_data.size()
986                                                 <<std::endl;
987                         }*/
988                 }
989                 m_clients.Unlock();
990
991                 // Clear buffered_messages
992                 for(std::map<u16, std::list<ActiveObjectMessage>* >::iterator
993                                 i = buffered_messages.begin();
994                                 i != buffered_messages.end(); ++i)
995                 {
996                         delete i->second;
997                 }
998         }
999
1000         /*
1001                 Send queued-for-sending map edit events.
1002         */
1003         {
1004                 // We will be accessing the environment
1005                 JMutexAutoLock lock(m_env_mutex);
1006
1007                 // Don't send too many at a time
1008                 //u32 count = 0;
1009
1010                 // Single change sending is disabled if queue size is not small
1011                 bool disable_single_change_sending = false;
1012                 if(m_unsent_map_edit_queue.size() >= 4)
1013                         disable_single_change_sending = true;
1014
1015                 int event_count = m_unsent_map_edit_queue.size();
1016
1017                 // We'll log the amount of each
1018                 Profiler prof;
1019
1020                 while(m_unsent_map_edit_queue.size() != 0)
1021                 {
1022                         MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
1023
1024                         // Players far away from the change are stored here.
1025                         // Instead of sending the changes, MapBlocks are set not sent
1026                         // for them.
1027                         std::list<u16> far_players;
1028
1029                         if(event->type == MEET_ADDNODE || event->type == MEET_SWAPNODE)
1030                         {
1031                                 //infostream<<"Server: MEET_ADDNODE"<<std::endl;
1032                                 prof.add("MEET_ADDNODE", 1);
1033                                 if(disable_single_change_sending)
1034                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1035                                                         &far_players, 5, event->type == MEET_ADDNODE);
1036                                 else
1037                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1038                                                         &far_players, 30, event->type == MEET_ADDNODE);
1039                         }
1040                         else if(event->type == MEET_REMOVENODE)
1041                         {
1042                                 //infostream<<"Server: MEET_REMOVENODE"<<std::endl;
1043                                 prof.add("MEET_REMOVENODE", 1);
1044                                 if(disable_single_change_sending)
1045                                         sendRemoveNode(event->p, event->already_known_by_peer,
1046                                                         &far_players, 5);
1047                                 else
1048                                         sendRemoveNode(event->p, event->already_known_by_peer,
1049                                                         &far_players, 30);
1050                         }
1051                         else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
1052                         {
1053                                 infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
1054                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
1055                                 setBlockNotSent(event->p);
1056                         }
1057                         else if(event->type == MEET_OTHER)
1058                         {
1059                                 infostream<<"Server: MEET_OTHER"<<std::endl;
1060                                 prof.add("MEET_OTHER", 1);
1061                                 for(std::set<v3s16>::iterator
1062                                                 i = event->modified_blocks.begin();
1063                                                 i != event->modified_blocks.end(); ++i)
1064                                 {
1065                                         setBlockNotSent(*i);
1066                                 }
1067                         }
1068                         else
1069                         {
1070                                 prof.add("unknown", 1);
1071                                 infostream<<"WARNING: Server: Unknown MapEditEvent "
1072                                                 <<((u32)event->type)<<std::endl;
1073                         }
1074
1075                         /*
1076                                 Set blocks not sent to far players
1077                         */
1078                         if(far_players.size() > 0)
1079                         {
1080                                 // Convert list format to that wanted by SetBlocksNotSent
1081                                 std::map<v3s16, MapBlock*> modified_blocks2;
1082                                 for(std::set<v3s16>::iterator
1083                                                 i = event->modified_blocks.begin();
1084                                                 i != event->modified_blocks.end(); ++i)
1085                                 {
1086                                         modified_blocks2[*i] =
1087                                                         m_env->getMap().getBlockNoCreateNoEx(*i);
1088                                 }
1089                                 // Set blocks not sent
1090                                 for(std::list<u16>::iterator
1091                                                 i = far_players.begin();
1092                                                 i != far_players.end(); ++i)
1093                                 {
1094                                         u16 peer_id = *i;
1095                                         RemoteClient *client = getClient(peer_id);
1096                                         if(client==NULL)
1097                                                 continue;
1098                                         client->SetBlocksNotSent(modified_blocks2);
1099                                 }
1100                         }
1101
1102                         delete event;
1103
1104                         /*// Don't send too many at a time
1105                         count++;
1106                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
1107                                 break;*/
1108                 }
1109
1110                 if(event_count >= 5){
1111                         infostream<<"Server: MapEditEvents:"<<std::endl;
1112                         prof.print(infostream);
1113                 } else if(event_count != 0){
1114                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
1115                         prof.print(verbosestream);
1116                 }
1117
1118         }
1119
1120         /*
1121                 Trigger emergethread (it somehow gets to a non-triggered but
1122                 bysy state sometimes)
1123         */
1124         {
1125                 float &counter = m_emergethread_trigger_timer;
1126                 counter += dtime;
1127                 if(counter >= 2.0)
1128                 {
1129                         counter = 0.0;
1130
1131                         m_emerge->startThreads();
1132
1133                         // Update m_enable_rollback_recording here too
1134                         m_enable_rollback_recording =
1135                                         g_settings->getBool("enable_rollback_recording");
1136                 }
1137         }
1138
1139         // Save map, players and auth stuff
1140         {
1141                 float &counter = m_savemap_timer;
1142                 counter += dtime;
1143                 if(counter >= g_settings->getFloat("server_map_save_interval"))
1144                 {
1145                         counter = 0.0;
1146                         JMutexAutoLock lock(m_env_mutex);
1147
1148                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1149
1150                         //Ban stuff
1151                         if(m_banmanager->isModified())
1152                                 m_banmanager->save();
1153
1154                         // Save changed parts of map
1155                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1156
1157                         // Save players
1158                         m_env->serializePlayers(m_path_world);
1159
1160                         // Save environment metadata
1161                         m_env->saveMeta(m_path_world);
1162                 }
1163         }
1164 }
1165
1166 void Server::Receive()
1167 {
1168         DSTACK(__FUNCTION_NAME);
1169         SharedBuffer<u8> data;
1170         u16 peer_id;
1171         u32 datasize;
1172         try{
1173                 datasize = m_con.Receive(peer_id,data);
1174                 ProcessData(*data, datasize, peer_id);
1175         }
1176         catch(con::InvalidIncomingDataException &e)
1177         {
1178                 infostream<<"Server::Receive(): "
1179                                 "InvalidIncomingDataException: what()="
1180                                 <<e.what()<<std::endl;
1181         }
1182         catch(con::PeerNotFoundException &e)
1183         {
1184                 //NOTE: This is not needed anymore
1185
1186                 // The peer has been disconnected.
1187                 // Find the associated player and remove it.
1188
1189                 /*JMutexAutoLock envlock(m_env_mutex);
1190
1191                 infostream<<"ServerThread: peer_id="<<peer_id
1192                                 <<" has apparently closed connection. "
1193                                 <<"Removing player."<<std::endl;
1194
1195                 m_env->removePlayer(peer_id);*/
1196         }
1197         catch(ClientStateError &e)
1198         {
1199                 errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1200                 DenyAccess(peer_id, L"Your client sent something server didn't expect."
1201                                 L"Try reconnecting or updating your client");
1202         }
1203 }
1204
1205 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1206 {
1207         std::string playername = "";
1208         PlayerSAO *playersao = NULL;
1209         m_clients.Lock();
1210         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,InitDone);
1211         if (client != NULL) {
1212                 playername = client->getName();
1213                 playersao = emergePlayer(playername.c_str(), peer_id);
1214         }
1215         m_clients.Unlock();
1216
1217         RemotePlayer *player =
1218                 static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
1219
1220         // If failed, cancel
1221         if((playersao == NULL) || (player == NULL))
1222         {
1223                 if(player && player->peer_id != 0){
1224                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1225                                         <<" (player allocated to an another client)"<<std::endl;
1226                         DenyAccess(peer_id, L"Another client is connected with this "
1227                                         L"name. If your client closed unexpectedly, try again in "
1228                                         L"a minute.");
1229                 } else {
1230                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1231                                         <<std::endl;
1232                         DenyAccess(peer_id, L"Could not allocate player.");
1233                 }
1234                 return NULL;
1235         }
1236
1237         /*
1238                 Send complete position information
1239         */
1240         SendMovePlayer(peer_id);
1241
1242         // Send privileges
1243         SendPlayerPrivileges(peer_id);
1244
1245         // Send inventory formspec
1246         SendPlayerInventoryFormspec(peer_id);
1247
1248         // Send inventory
1249         UpdateCrafting(peer_id);
1250         SendInventory(peer_id);
1251
1252         // Send HP
1253         if(g_settings->getBool("enable_damage"))
1254                 SendPlayerHP(peer_id);
1255
1256         // Send Breath
1257         SendPlayerBreath(peer_id);
1258
1259         // Show death screen if necessary
1260         if(player->hp == 0)
1261                 SendDeathscreen(peer_id, false, v3f(0,0,0));
1262
1263         // Note things in chat if not in simple singleplayer mode
1264         if(!m_simple_singleplayer_mode)
1265         {
1266                 // Send information about server to player in chat
1267                 SendChatMessage(peer_id, getStatusString());
1268
1269                 // Send information about joining in chat
1270                 {
1271                         std::wstring name = L"unknown";
1272                         Player *player = m_env->getPlayer(peer_id);
1273                         if(player != NULL)
1274                                 name = narrow_to_wide(player->getName());
1275
1276                         std::wstring message;
1277                         message += L"*** ";
1278                         message += name;
1279                         message += L" joined the game.";
1280                         SendChatMessage(PEER_ID_INEXISTENT,message);
1281                 }
1282         }
1283         Address addr = getPeerAddress(player->peer_id);
1284         std::string ip_str = addr.serializeString();
1285         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1286         /*
1287                 Print out action
1288         */
1289         {
1290                 std::vector<std::string> names = m_clients.getPlayerNames();
1291
1292                 actionstream<<player->getName() <<" joins game. List of players: ";
1293
1294                 for (std::vector<std::string>::iterator i = names.begin();
1295                                 i != names.end(); i++)
1296                 {
1297                         actionstream << *i << " ";
1298                 }
1299
1300                 actionstream<<std::endl;
1301         }
1302         return playersao;
1303 }
1304
1305 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1306 {
1307         DSTACK(__FUNCTION_NAME);
1308         // Environment is locked first.
1309         JMutexAutoLock envlock(m_env_mutex);
1310
1311         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1312
1313         std::string addr_s;
1314         try{
1315                 Address address = getPeerAddress(peer_id);
1316                 addr_s = address.serializeString();
1317
1318                 // drop player if is ip is banned
1319                 if(m_banmanager->isIpBanned(addr_s)){
1320                         std::string ban_name = m_banmanager->getBanName(addr_s);
1321                         infostream<<"Server: A banned client tried to connect from "
1322                                         <<addr_s<<"; banned name was "
1323                                         <<ban_name<<std::endl;
1324                         // This actually doesn't seem to transfer to the client
1325                         DenyAccess(peer_id, L"Your ip is banned. Banned name was "
1326                                         +narrow_to_wide(ban_name));
1327                         return;
1328                 }
1329         }
1330         catch(con::PeerNotFoundException &e)
1331         {
1332                 /*
1333                  * no peer for this packet found
1334                  * most common reason is peer timeout, e.g. peer didn't
1335                  * respond for some time, your server was overloaded or
1336                  * things like that.
1337                  */
1338                 infostream<<"Server::ProcessData(): Cancelling: peer "
1339                                 <<peer_id<<" not found"<<std::endl;
1340                 return;
1341         }
1342
1343         try
1344         {
1345
1346         if(datasize < 2)
1347                 return;
1348
1349         ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1350
1351         if(command == TOSERVER_INIT)
1352         {
1353                 // [0] u16 TOSERVER_INIT
1354                 // [2] u8 SER_FMT_VER_HIGHEST_READ
1355                 // [3] u8[20] player_name
1356                 // [23] u8[28] password <--- can be sent without this, from old versions
1357
1358                 if(datasize < 2+1+PLAYERNAME_SIZE)
1359                         return;
1360
1361                 RemoteClient* client = getClient(peer_id,Created);
1362
1363                 // If net_proto_version is set, this client has already been handled
1364                 if(client->getState() > Created)
1365                 {
1366                         verbosestream<<"Server: Ignoring multiple TOSERVER_INITs from "
1367                                         <<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1368                         return;
1369                 }
1370
1371                 verbosestream<<"Server: Got TOSERVER_INIT from "<<addr_s<<" (peer_id="
1372                                 <<peer_id<<")"<<std::endl;
1373
1374                 // Do not allow multiple players in simple singleplayer mode.
1375                 // This isn't a perfect way to do it, but will suffice for now
1376                 if(m_simple_singleplayer_mode && m_clients.getClientIDs().size() > 1){
1377                         infostream<<"Server: Not allowing another client ("<<addr_s
1378                                         <<") to connect in simple singleplayer mode"<<std::endl;
1379                         DenyAccess(peer_id, L"Running in simple singleplayer mode.");
1380                         return;
1381                 }
1382
1383                 // First byte after command is maximum supported
1384                 // serialization version
1385                 u8 client_max = data[2];
1386                 u8 our_max = SER_FMT_VER_HIGHEST_READ;
1387                 // Use the highest version supported by both
1388                 u8 deployed = std::min(client_max, our_max);
1389                 // If it's lower than the lowest supported, give up.
1390                 if(deployed < SER_FMT_VER_LOWEST)
1391                         deployed = SER_FMT_VER_INVALID;
1392
1393                 if(deployed == SER_FMT_VER_INVALID)
1394                 {
1395                         actionstream<<"Server: A mismatched client tried to connect from "
1396                                         <<addr_s<<std::endl;
1397                         infostream<<"Server: Cannot negotiate serialization version with "
1398                                         <<addr_s<<std::endl;
1399                         DenyAccess(peer_id, std::wstring(
1400                                         L"Your client's version is not supported.\n"
1401                                         L"Server version is ")
1402                                         + narrow_to_wide(minetest_version_simple) + L"."
1403                         );
1404                         return;
1405                 }
1406
1407                 client->setPendingSerializationVersion(deployed);
1408
1409                 /*
1410                         Read and check network protocol version
1411                 */
1412
1413                 u16 min_net_proto_version = 0;
1414                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1415                         min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1416
1417                 // Use same version as minimum and maximum if maximum version field
1418                 // doesn't exist (backwards compatibility)
1419                 u16 max_net_proto_version = min_net_proto_version;
1420                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
1421                         max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
1422
1423                 // Start with client's maximum version
1424                 u16 net_proto_version = max_net_proto_version;
1425
1426                 // Figure out a working version if it is possible at all
1427                 if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN ||
1428                                 min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX)
1429                 {
1430                         // If maximum is larger than our maximum, go with our maximum
1431                         if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1432                                 net_proto_version = SERVER_PROTOCOL_VERSION_MAX;
1433                         // Else go with client's maximum
1434                         else
1435                                 net_proto_version = max_net_proto_version;
1436                 }
1437
1438                 verbosestream<<"Server: "<<addr_s<<": Protocol version: min: "
1439                                 <<min_net_proto_version<<", max: "<<max_net_proto_version
1440                                 <<", chosen: "<<net_proto_version<<std::endl;
1441
1442                 client->net_proto_version = net_proto_version;
1443
1444                 if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN ||
1445                                 net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1446                 {
1447                         actionstream<<"Server: A mismatched client tried to connect from "
1448                                         <<addr_s<<std::endl;
1449                         DenyAccess(peer_id, std::wstring(
1450                                         L"Your client's version is not supported.\n"
1451                                         L"Server version is ")
1452                                         + narrow_to_wide(minetest_version_simple) + L",\n"
1453                                         + L"server's PROTOCOL_VERSION is "
1454                                         + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN))
1455                                         + L"..."
1456                                         + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX))
1457                                         + L", client's PROTOCOL_VERSION is "
1458                                         + narrow_to_wide(itos(min_net_proto_version))
1459                                         + L"..."
1460                                         + narrow_to_wide(itos(max_net_proto_version))
1461                         );
1462                         return;
1463                 }
1464
1465                 if(g_settings->getBool("strict_protocol_version_checking"))
1466                 {
1467                         if(net_proto_version != LATEST_PROTOCOL_VERSION)
1468                         {
1469                                 actionstream<<"Server: A mismatched (strict) client tried to "
1470                                                 <<"connect from "<<addr_s<<std::endl;
1471                                 DenyAccess(peer_id, std::wstring(
1472                                                 L"Your client's version is not supported.\n"
1473                                                 L"Server version is ")
1474                                                 + narrow_to_wide(minetest_version_simple) + L",\n"
1475                                                 + L"server's PROTOCOL_VERSION (strict) is "
1476                                                 + narrow_to_wide(itos(LATEST_PROTOCOL_VERSION))
1477                                                 + L", client's PROTOCOL_VERSION is "
1478                                                 + narrow_to_wide(itos(min_net_proto_version))
1479                                                 + L"..."
1480                                                 + narrow_to_wide(itos(max_net_proto_version))
1481                                 );
1482                                 return;
1483                         }
1484                 }
1485
1486                 /*
1487                         Set up player
1488                 */
1489
1490                 // Get player name
1491                 char playername[PLAYERNAME_SIZE];
1492                 for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
1493                 {
1494                         playername[i] = data[3+i];
1495                 }
1496                 playername[PLAYERNAME_SIZE-1] = 0;
1497
1498                 if(playername[0]=='\0')
1499                 {
1500                         actionstream<<"Server: Player with an empty name "
1501                                         <<"tried to connect from "<<addr_s<<std::endl;
1502                         DenyAccess(peer_id, L"Empty name");
1503                         return;
1504                 }
1505
1506                 if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
1507                 {
1508                         actionstream<<"Server: Player with an invalid name "
1509                                         <<"tried to connect from "<<addr_s<<std::endl;
1510                         DenyAccess(peer_id, L"Name contains unallowed characters");
1511                         return;
1512                 }
1513
1514                 if(!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0)
1515                 {
1516                         actionstream<<"Server: Player with the name \"singleplayer\" "
1517                                         <<"tried to connect from "<<addr_s<<std::endl;
1518                         DenyAccess(peer_id, L"Name is not allowed");
1519                         return;
1520                 }
1521
1522                 {
1523                         std::string reason;
1524                         if(m_script->on_prejoinplayer(playername, addr_s, reason))
1525                         {
1526                                 actionstream<<"Server: Player with the name \""<<playername<<"\" "
1527                                                 <<"tried to connect from "<<addr_s<<" "
1528                                                 <<"but it was disallowed for the following reason: "
1529                                                 <<reason<<std::endl;
1530                                 DenyAccess(peer_id, narrow_to_wide(reason.c_str()));
1531                                 return;
1532                         }
1533                 }
1534
1535                 infostream<<"Server: New connection: \""<<playername<<"\" from "
1536                                 <<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1537
1538                 // Get password
1539                 char given_password[PASSWORD_SIZE];
1540                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
1541                 {
1542                         // old version - assume blank password
1543                         given_password[0] = 0;
1544                 }
1545                 else
1546                 {
1547                         for(u32 i=0; i<PASSWORD_SIZE-1; i++)
1548                         {
1549                                 given_password[i] = data[23+i];
1550                         }
1551                         given_password[PASSWORD_SIZE-1] = 0;
1552                 }
1553
1554                 if(!base64_is_valid(given_password)){
1555                         actionstream<<"Server: "<<playername
1556                                         <<" supplied invalid password hash"<<std::endl;
1557                         DenyAccess(peer_id, L"Invalid password hash");
1558                         return;
1559                 }
1560
1561                 // Enforce user limit.
1562                 // Don't enforce for users that have some admin right
1563                 if(m_clients.getClientIDs(Created).size() >= g_settings->getU16("max_users") &&
1564                                 !checkPriv(playername, "server") &&
1565                                 !checkPriv(playername, "ban") &&
1566                                 !checkPriv(playername, "privs") &&
1567                                 !checkPriv(playername, "password") &&
1568                                 playername != g_settings->get("name"))
1569                 {
1570                         actionstream<<"Server: "<<playername<<" tried to join, but there"
1571                                         <<" are already max_users="
1572                                         <<g_settings->getU16("max_users")<<" players."<<std::endl;
1573                         DenyAccess(peer_id, L"Too many users.");
1574                         return;
1575                 }
1576
1577                 std::string checkpwd; // Password hash to check against
1578                 bool has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1579
1580                 // If no authentication info exists for user, create it
1581                 if(!has_auth){
1582                         if(!isSingleplayer() &&
1583                                         g_settings->getBool("disallow_empty_password") &&
1584                                         std::string(given_password) == ""){
1585                                 actionstream<<"Server: "<<playername
1586                                                 <<" supplied empty password"<<std::endl;
1587                                 DenyAccess(peer_id, L"Empty passwords are "
1588                                                 L"disallowed. Set a password and try again.");
1589                                 return;
1590                         }
1591                         std::wstring raw_default_password =
1592                                 narrow_to_wide(g_settings->get("default_password"));
1593                         std::string initial_password =
1594                                 translatePassword(playername, raw_default_password);
1595
1596                         // If default_password is empty, allow any initial password
1597                         if (raw_default_password.length() == 0)
1598                                 initial_password = given_password;
1599
1600                         m_script->createAuth(playername, initial_password);
1601                 }
1602
1603                 has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1604
1605                 if(!has_auth){
1606                         actionstream<<"Server: "<<playername<<" cannot be authenticated"
1607                                         <<" (auth handler does not work?)"<<std::endl;
1608                         DenyAccess(peer_id, L"Not allowed to login");
1609                         return;
1610                 }
1611
1612                 if(given_password != checkpwd){
1613                         actionstream<<"Server: "<<playername<<" supplied wrong password"
1614                                         <<std::endl;
1615                         DenyAccess(peer_id, L"Wrong password");
1616                         return;
1617                 }
1618
1619                 RemotePlayer *player =
1620                                 static_cast<RemotePlayer*>(m_env->getPlayer(playername));
1621
1622                 if(player && player->peer_id != 0){
1623                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1624                                         <<" (player allocated to an another client)"<<std::endl;
1625                         DenyAccess(peer_id, L"Another client is connected with this "
1626                                         L"name. If your client closed unexpectedly, try again in "
1627                                         L"a minute.");
1628                 }
1629
1630                 m_clients.setPlayerName(peer_id,playername);
1631
1632                 /*
1633                         Answer with a TOCLIENT_INIT
1634                 */
1635                 {
1636                         SharedBuffer<u8> reply(2+1+6+8+4);
1637                         writeU16(&reply[0], TOCLIENT_INIT);
1638                         writeU8(&reply[2], deployed);
1639                         //send dummy pos for legacy reasons only
1640                         writeV3S16(&reply[2+1], floatToInt(v3f(0,0,0), BS));
1641                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
1642                         writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
1643
1644                         // Send as reliable
1645                         m_clients.send(peer_id, 0, reply, true);
1646                         m_clients.event(peer_id, Init);
1647                 }
1648
1649                 return;
1650         }
1651
1652         if(command == TOSERVER_INIT2)
1653         {
1654
1655                 verbosestream<<"Server: Got TOSERVER_INIT2 from "
1656                                 <<peer_id<<std::endl;
1657
1658                 m_clients.event(peer_id, GotInit2);
1659                 u16 protocol_version = m_clients.getProtocolVersion(peer_id);
1660
1661
1662                 ///// begin compatibility code
1663                 PlayerSAO* playersao = NULL;
1664                 if (protocol_version <= 22) {
1665                         playersao = StageTwoClientInit(peer_id);
1666
1667                         if (playersao == NULL) {
1668                                 errorstream
1669                                         << "TOSERVER_INIT2 stage 2 client init failed for peer "
1670                                         << peer_id << std::endl;
1671                                 return;
1672                         }
1673                 }
1674                 ///// end compatibility code
1675
1676                 /*
1677                         Send some initialization data
1678                 */
1679
1680                 infostream<<"Server: Sending content to "
1681                                 <<getPlayerName(peer_id)<<std::endl;
1682
1683                 // Send player movement settings
1684                 SendMovement(peer_id);
1685
1686                 // Send item definitions
1687                 SendItemDef(peer_id, m_itemdef, protocol_version);
1688
1689                 // Send node definitions
1690                 SendNodeDef(peer_id, m_nodedef, protocol_version);
1691
1692                 m_clients.event(peer_id, SetDefinitionsSent);
1693
1694                 // Send media announcement
1695                 sendMediaAnnouncement(peer_id);
1696
1697                 // Send detached inventories
1698                 sendDetachedInventories(peer_id);
1699
1700                 // Send time of day
1701                 u16 time = m_env->getTimeOfDay();
1702                 float time_speed = g_settings->getFloat("time_speed");
1703                 SendTimeOfDay(peer_id, time, time_speed);
1704
1705                 ///// begin compatibility code
1706                 if (protocol_version <= 22) {
1707                         m_clients.event(peer_id, SetClientReady);
1708                         m_script->on_joinplayer(playersao);
1709                 }
1710                 ///// end compatibility code
1711
1712                 // Warnings about protocol version can be issued here
1713                 if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
1714                 {
1715                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S "
1716                                         L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
1717                 }
1718
1719                 return;
1720         }
1721
1722         u8 peer_ser_ver = getClient(peer_id,InitDone)->serialization_version;
1723         u16 peer_proto_ver = getClient(peer_id,InitDone)->net_proto_version;
1724
1725         if(peer_ser_ver == SER_FMT_VER_INVALID)
1726         {
1727                 errorstream<<"Server::ProcessData(): Cancelling: Peer"
1728                                 " serialization format invalid or not initialized."
1729                                 " Skipping incoming command="<<command<<std::endl;
1730                 return;
1731         }
1732
1733         /* Handle commands relate to client startup */
1734         if(command == TOSERVER_REQUEST_MEDIA) {
1735                 std::string datastring((char*)&data[2], datasize-2);
1736                 std::istringstream is(datastring, std::ios_base::binary);
1737
1738                 std::list<std::string> tosend;
1739                 u16 numfiles = readU16(is);
1740
1741                 infostream<<"Sending "<<numfiles<<" files to "
1742                                 <<getPlayerName(peer_id)<<std::endl;
1743                 verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
1744
1745                 for(int i = 0; i < numfiles; i++) {
1746                         std::string name = deSerializeString(is);
1747                         tosend.push_back(name);
1748                         verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
1749                                         <<name<<std::endl;
1750                 }
1751
1752                 sendRequestedMedia(peer_id, tosend);
1753                 return;
1754         }
1755         else if(command == TOSERVER_RECEIVED_MEDIA) {
1756                 return;
1757         }
1758         else if(command == TOSERVER_CLIENT_READY) {
1759                 // clients <= protocol version 22 did not send ready message,
1760                 // they're already initialized
1761                 assert(peer_proto_ver > 22);
1762
1763                 PlayerSAO* playersao = StageTwoClientInit(peer_id);
1764
1765                 if (playersao == NULL) {
1766                         errorstream
1767                                 << "TOSERVER_CLIENT_READY stage 2 client init failed for peer "
1768                                 << peer_id << std::endl;
1769                         return;
1770                 }
1771
1772
1773                 if(datasize < 2+8)
1774                         return;
1775
1776                 m_clients.setClientVersion(
1777                                 peer_id,
1778                                 data[2], data[3], data[4],
1779                                 std::string((char*) &data[8],(u16) data[6]));
1780
1781                 m_clients.event(peer_id, SetClientReady);
1782                 m_script->on_joinplayer(playersao);
1783
1784         }
1785         else if(command == TOSERVER_GOTBLOCKS)
1786         {
1787                 if(datasize < 2+1)
1788                         return;
1789
1790                 /*
1791                         [0] u16 command
1792                         [2] u8 count
1793                         [3] v3s16 pos_0
1794                         [3+6] v3s16 pos_1
1795                         ...
1796                 */
1797
1798                 u16 count = data[2];
1799                 for(u16 i=0; i<count; i++)
1800                 {
1801                         if((s16)datasize < 2+1+(i+1)*6)
1802                                 throw con::InvalidIncomingDataException
1803                                         ("GOTBLOCKS length is too short");
1804                         v3s16 p = readV3S16(&data[2+1+i*6]);
1805                         /*infostream<<"Server: GOTBLOCKS ("
1806                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
1807                         RemoteClient *client = getClient(peer_id);
1808                         client->GotBlock(p);
1809                 }
1810                 return;
1811         }
1812
1813         if (m_clients.getClientState(peer_id) < Active)
1814         {
1815                 if (command == TOSERVER_PLAYERPOS) return;
1816
1817                 errorstream<<"Got packet command: " << command << " for peer id "
1818                                 << peer_id << " but client isn't active yet. Dropping packet "
1819                                 <<std::endl;
1820                 return;
1821         }
1822
1823         Player *player = m_env->getPlayer(peer_id);
1824         if(player == NULL){
1825                 errorstream<<"Server::ProcessData(): Cancelling: "
1826                                 "No player for peer_id="<<peer_id
1827                                 <<std::endl;
1828                 return;
1829         }
1830
1831         PlayerSAO *playersao = player->getPlayerSAO();
1832         if(playersao == NULL){
1833                 errorstream<<"Server::ProcessData(): Cancelling: "
1834                                 "No player object for peer_id="<<peer_id
1835                                 <<std::endl;
1836                 return;
1837         }
1838
1839         if(command == TOSERVER_PLAYERPOS)
1840         {
1841                 if(datasize < 2+12+12+4+4)
1842                         return;
1843
1844                 u32 start = 0;
1845                 v3s32 ps = readV3S32(&data[start+2]);
1846                 v3s32 ss = readV3S32(&data[start+2+12]);
1847                 f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
1848                 f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
1849                 u32 keyPressed = 0;
1850                 if(datasize >= 2+12+12+4+4+4)
1851                         keyPressed = (u32)readU32(&data[2+12+12+4+4]);
1852                 v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
1853                 v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
1854                 pitch = wrapDegrees(pitch);
1855                 yaw = wrapDegrees(yaw);
1856
1857                 player->setPosition(position);
1858                 player->setSpeed(speed);
1859                 player->setPitch(pitch);
1860                 player->setYaw(yaw);
1861                 player->keyPressed=keyPressed;
1862                 player->control.up = (bool)(keyPressed&1);
1863                 player->control.down = (bool)(keyPressed&2);
1864                 player->control.left = (bool)(keyPressed&4);
1865                 player->control.right = (bool)(keyPressed&8);
1866                 player->control.jump = (bool)(keyPressed&16);
1867                 player->control.aux1 = (bool)(keyPressed&32);
1868                 player->control.sneak = (bool)(keyPressed&64);
1869                 player->control.LMB = (bool)(keyPressed&128);
1870                 player->control.RMB = (bool)(keyPressed&256);
1871
1872                 bool cheated = playersao->checkMovementCheat();
1873                 if(cheated){
1874                         // Call callbacks
1875                         m_script->on_cheat(playersao, "moved_too_fast");
1876                 }
1877
1878                 /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
1879                                 <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
1880                                 <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
1881         }
1882         else if(command == TOSERVER_DELETEDBLOCKS)
1883         {
1884                 if(datasize < 2+1)
1885                         return;
1886
1887                 /*
1888                         [0] u16 command
1889                         [2] u8 count
1890                         [3] v3s16 pos_0
1891                         [3+6] v3s16 pos_1
1892                         ...
1893                 */
1894
1895                 u16 count = data[2];
1896                 for(u16 i=0; i<count; i++)
1897                 {
1898                         if((s16)datasize < 2+1+(i+1)*6)
1899                                 throw con::InvalidIncomingDataException
1900                                         ("DELETEDBLOCKS length is too short");
1901                         v3s16 p = readV3S16(&data[2+1+i*6]);
1902                         /*infostream<<"Server: DELETEDBLOCKS ("
1903                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
1904                         RemoteClient *client = getClient(peer_id);
1905                         client->SetBlockNotSent(p);
1906                 }
1907         }
1908         else if(command == TOSERVER_CLICK_OBJECT)
1909         {
1910                 infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
1911                 return;
1912         }
1913         else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
1914         {
1915                 infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
1916                 return;
1917         }
1918         else if(command == TOSERVER_GROUND_ACTION)
1919         {
1920                 infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
1921                 return;
1922
1923         }
1924         else if(command == TOSERVER_RELEASE)
1925         {
1926                 infostream<<"Server: RELEASE not supported anymore"<<std::endl;
1927                 return;
1928         }
1929         else if(command == TOSERVER_SIGNTEXT)
1930         {
1931                 infostream<<"Server: SIGNTEXT not supported anymore"
1932                                 <<std::endl;
1933                 return;
1934         }
1935         else if(command == TOSERVER_SIGNNODETEXT)
1936         {
1937                 infostream<<"Server: SIGNNODETEXT not supported anymore"
1938                                 <<std::endl;
1939                 return;
1940         }
1941         else if(command == TOSERVER_INVENTORY_ACTION)
1942         {
1943                 // Strip command and create a stream
1944                 std::string datastring((char*)&data[2], datasize-2);
1945                 verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
1946                 std::istringstream is(datastring, std::ios_base::binary);
1947                 // Create an action
1948                 InventoryAction *a = InventoryAction::deSerialize(is);
1949                 if(a == NULL)
1950                 {
1951                         infostream<<"TOSERVER_INVENTORY_ACTION: "
1952                                         <<"InventoryAction::deSerialize() returned NULL"
1953                                         <<std::endl;
1954                         return;
1955                 }
1956
1957                 // If something goes wrong, this player is to blame
1958                 RollbackScopeActor rollback_scope(m_rollback,
1959                                 std::string("player:")+player->getName());
1960
1961                 /*
1962                         Note: Always set inventory not sent, to repair cases
1963                         where the client made a bad prediction.
1964                 */
1965
1966                 /*
1967                         Handle restrictions and special cases of the move action
1968                 */
1969                 if(a->getType() == IACTION_MOVE)
1970                 {
1971                         IMoveAction *ma = (IMoveAction*)a;
1972
1973                         ma->from_inv.applyCurrentPlayer(player->getName());
1974                         ma->to_inv.applyCurrentPlayer(player->getName());
1975
1976                         setInventoryModified(ma->from_inv);
1977                         setInventoryModified(ma->to_inv);
1978
1979                         bool from_inv_is_current_player =
1980                                 (ma->from_inv.type == InventoryLocation::PLAYER) &&
1981                                 (ma->from_inv.name == player->getName());
1982
1983                         bool to_inv_is_current_player =
1984                                 (ma->to_inv.type == InventoryLocation::PLAYER) &&
1985                                 (ma->to_inv.name == player->getName());
1986
1987                         /*
1988                                 Disable moving items out of craftpreview
1989                         */
1990                         if(ma->from_list == "craftpreview")
1991                         {
1992                                 infostream<<"Ignoring IMoveAction from "
1993                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
1994                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
1995                                                 <<" because src is "<<ma->from_list<<std::endl;
1996                                 delete a;
1997                                 return;
1998                         }
1999
2000                         /*
2001                                 Disable moving items into craftresult and craftpreview
2002                         */
2003                         if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
2004                         {
2005                                 infostream<<"Ignoring IMoveAction from "
2006                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2007                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2008                                                 <<" because dst is "<<ma->to_list<<std::endl;
2009                                 delete a;
2010                                 return;
2011                         }
2012
2013                         // Disallow moving items in elsewhere than player's inventory
2014                         // if not allowed to interact
2015                         if(!checkPriv(player->getName(), "interact") &&
2016                                         (!from_inv_is_current_player ||
2017                                         !to_inv_is_current_player))
2018                         {
2019                                 infostream<<"Cannot move outside of player's inventory: "
2020                                                 <<"No interact privilege"<<std::endl;
2021                                 delete a;
2022                                 return;
2023                         }
2024                 }
2025                 /*
2026                         Handle restrictions and special cases of the drop action
2027                 */
2028                 else if(a->getType() == IACTION_DROP)
2029                 {
2030                         IDropAction *da = (IDropAction*)a;
2031
2032                         da->from_inv.applyCurrentPlayer(player->getName());
2033
2034                         setInventoryModified(da->from_inv);
2035
2036                         /*
2037                                 Disable dropping items out of craftpreview
2038                         */
2039                         if(da->from_list == "craftpreview")
2040                         {
2041                                 infostream<<"Ignoring IDropAction from "
2042                                                 <<(da->from_inv.dump())<<":"<<da->from_list
2043                                                 <<" because src is "<<da->from_list<<std::endl;
2044                                 delete a;
2045                                 return;
2046                         }
2047
2048                         // Disallow dropping items if not allowed to interact
2049                         if(!checkPriv(player->getName(), "interact"))
2050                         {
2051                                 delete a;
2052                                 return;
2053                         }
2054                 }
2055                 /*
2056                         Handle restrictions and special cases of the craft action
2057                 */
2058                 else if(a->getType() == IACTION_CRAFT)
2059                 {
2060                         ICraftAction *ca = (ICraftAction*)a;
2061
2062                         ca->craft_inv.applyCurrentPlayer(player->getName());
2063
2064                         setInventoryModified(ca->craft_inv);
2065
2066                         //bool craft_inv_is_current_player =
2067                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2068                         //      (ca->craft_inv.name == player->getName());
2069
2070                         // Disallow crafting if not allowed to interact
2071                         if(!checkPriv(player->getName(), "interact"))
2072                         {
2073                                 infostream<<"Cannot craft: "
2074                                                 <<"No interact privilege"<<std::endl;
2075                                 delete a;
2076                                 return;
2077                         }
2078                 }
2079
2080                 // Do the action
2081                 a->apply(this, playersao, this);
2082                 // Eat the action
2083                 delete a;
2084         }
2085         else if(command == TOSERVER_CHAT_MESSAGE)
2086         {
2087                 /*
2088                         u16 command
2089                         u16 length
2090                         wstring message
2091                 */
2092                 u8 buf[6];
2093                 std::string datastring((char*)&data[2], datasize-2);
2094                 std::istringstream is(datastring, std::ios_base::binary);
2095
2096                 // Read stuff
2097                 is.read((char*)buf, 2);
2098                 u16 len = readU16(buf);
2099
2100                 std::wstring message;
2101                 for(u16 i=0; i<len; i++)
2102                 {
2103                         is.read((char*)buf, 2);
2104                         message += (wchar_t)readU16(buf);
2105                 }
2106
2107                 // If something goes wrong, this player is to blame
2108                 RollbackScopeActor rollback_scope(m_rollback,
2109                                 std::string("player:")+player->getName());
2110
2111                 // Get player name of this client
2112                 std::wstring name = narrow_to_wide(player->getName());
2113
2114                 // Run script hook
2115                 bool ate = m_script->on_chat_message(player->getName(),
2116                                 wide_to_narrow(message));
2117                 // If script ate the message, don't proceed
2118                 if(ate)
2119                         return;
2120
2121                 // Line to send to players
2122                 std::wstring line;
2123                 // Whether to send to the player that sent the line
2124                 bool send_to_sender_only = false;
2125
2126                 // Commands are implemented in Lua, so only catch invalid
2127                 // commands that were not "eaten" and send an error back
2128                 if(message[0] == L'/')
2129                 {
2130                         message = message.substr(1);
2131                         send_to_sender_only = true;
2132                         if(message.length() == 0)
2133                                 line += L"-!- Empty command";
2134                         else
2135                                 line += L"-!- Invalid command: " + str_split(message, L' ')[0];
2136                 }
2137                 else
2138                 {
2139                         if(checkPriv(player->getName(), "shout")){
2140                                 line += L"<";
2141                                 line += name;
2142                                 line += L"> ";
2143                                 line += message;
2144                         } else {
2145                                 line += L"-!- You don't have permission to shout.";
2146                                 send_to_sender_only = true;
2147                         }
2148                 }
2149
2150                 if(line != L"")
2151                 {
2152                         /*
2153                                 Send the message to sender
2154                         */
2155                         if (send_to_sender_only)
2156                         {
2157                                 SendChatMessage(peer_id, line);
2158                         }
2159                         /*
2160                                 Send the message to others
2161                         */
2162                         else
2163                         {
2164                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2165
2166                                 std::list<u16> clients = m_clients.getClientIDs();
2167
2168                                 for(std::list<u16>::iterator
2169                                         i = clients.begin();
2170                                         i != clients.end(); ++i)
2171                                 {
2172                                         if (*i != peer_id)
2173                                                 SendChatMessage(*i, line);
2174                                 }
2175                         }
2176                 }
2177         }
2178         else if(command == TOSERVER_DAMAGE)
2179         {
2180                 std::string datastring((char*)&data[2], datasize-2);
2181                 std::istringstream is(datastring, std::ios_base::binary);
2182                 u8 damage = readU8(is);
2183
2184                 if(g_settings->getBool("enable_damage"))
2185                 {
2186                         actionstream<<player->getName()<<" damaged by "
2187                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2188                                         <<std::endl;
2189
2190                         playersao->setHP(playersao->getHP() - damage);
2191
2192                         if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
2193                                 DiePlayer(peer_id);
2194
2195                         if(playersao->m_hp_not_sent)
2196                                 SendPlayerHP(peer_id);
2197                 }
2198         }
2199         else if(command == TOSERVER_BREATH)
2200         {
2201                 std::string datastring((char*)&data[2], datasize-2);
2202                 std::istringstream is(datastring, std::ios_base::binary);
2203                 u16 breath = readU16(is);
2204                 playersao->setBreath(breath);
2205                 m_script->player_event(playersao,"breath_changed");
2206         }
2207         else if(command == TOSERVER_PASSWORD)
2208         {
2209                 /*
2210                         [0] u16 TOSERVER_PASSWORD
2211                         [2] u8[28] old password
2212                         [30] u8[28] new password
2213                 */
2214
2215                 if(datasize != 2+PASSWORD_SIZE*2)
2216                         return;
2217                 /*char password[PASSWORD_SIZE];
2218                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2219                         password[i] = data[2+i];
2220                 password[PASSWORD_SIZE-1] = 0;*/
2221                 std::string oldpwd;
2222                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2223                 {
2224                         char c = data[2+i];
2225                         if(c == 0)
2226                                 break;
2227                         oldpwd += c;
2228                 }
2229                 std::string newpwd;
2230                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2231                 {
2232                         char c = data[2+PASSWORD_SIZE+i];
2233                         if(c == 0)
2234                                 break;
2235                         newpwd += c;
2236                 }
2237
2238                 if(!base64_is_valid(newpwd)){
2239                         infostream<<"Server: "<<player->getName()<<" supplied invalid password hash"<<std::endl;
2240                         // Wrong old password supplied!!
2241                         SendChatMessage(peer_id, L"Invalid new password hash supplied. Password NOT changed.");
2242                         return;
2243                 }
2244
2245                 infostream<<"Server: Client requests a password change from "
2246                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2247
2248                 std::string playername = player->getName();
2249
2250                 std::string checkpwd;
2251                 m_script->getAuth(playername, &checkpwd, NULL);
2252
2253                 if(oldpwd != checkpwd)
2254                 {
2255                         infostream<<"Server: invalid old password"<<std::endl;
2256                         // Wrong old password supplied!!
2257                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2258                         return;
2259                 }
2260
2261                 bool success = m_script->setPassword(playername, newpwd);
2262                 if(success){
2263                         actionstream<<player->getName()<<" changes password"<<std::endl;
2264                         SendChatMessage(peer_id, L"Password change successful.");
2265                 } else {
2266                         actionstream<<player->getName()<<" tries to change password but "
2267                                         <<"it fails"<<std::endl;
2268                         SendChatMessage(peer_id, L"Password change failed or inavailable.");
2269                 }
2270         }
2271         else if(command == TOSERVER_PLAYERITEM)
2272         {
2273                 if (datasize < 2+2)
2274                         return;
2275
2276                 u16 item = readU16(&data[2]);
2277                 playersao->setWieldIndex(item);
2278         }
2279         else if(command == TOSERVER_RESPAWN)
2280         {
2281                 if(player->hp != 0 || !g_settings->getBool("enable_damage"))
2282                         return;
2283
2284                 RespawnPlayer(peer_id);
2285
2286                 actionstream<<player->getName()<<" respawns at "
2287                                 <<PP(player->getPosition()/BS)<<std::endl;
2288
2289                 // ActiveObject is added to environment in AsyncRunStep after
2290                 // the previous addition has been succesfully removed
2291         }
2292         else if(command == TOSERVER_INTERACT)
2293         {
2294                 std::string datastring((char*)&data[2], datasize-2);
2295                 std::istringstream is(datastring, std::ios_base::binary);
2296
2297                 /*
2298                         [0] u16 command
2299                         [2] u8 action
2300                         [3] u16 item
2301                         [5] u32 length of the next item
2302                         [9] serialized PointedThing
2303                         actions:
2304                         0: start digging (from undersurface) or use
2305                         1: stop digging (all parameters ignored)
2306                         2: digging completed
2307                         3: place block or item (to abovesurface)
2308                         4: use item
2309                 */
2310                 u8 action = readU8(is);
2311                 u16 item_i = readU16(is);
2312                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2313                 PointedThing pointed;
2314                 pointed.deSerialize(tmp_is);
2315
2316                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2317                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2318
2319                 if(player->hp == 0)
2320                 {
2321                         verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
2322                                 <<" tried to interact, but is dead!"<<std::endl;
2323                         return;
2324                 }
2325
2326                 v3f player_pos = playersao->getLastGoodPosition();
2327
2328                 // Update wielded item
2329                 playersao->setWieldIndex(item_i);
2330
2331                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2332                 v3s16 p_under = pointed.node_undersurface;
2333                 v3s16 p_above = pointed.node_abovesurface;
2334
2335                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2336                 ServerActiveObject *pointed_object = NULL;
2337                 if(pointed.type == POINTEDTHING_OBJECT)
2338                 {
2339                         pointed_object = m_env->getActiveObject(pointed.object_id);
2340                         if(pointed_object == NULL)
2341                         {
2342                                 verbosestream<<"TOSERVER_INTERACT: "
2343                                         "pointed object is NULL"<<std::endl;
2344                                 return;
2345                         }
2346
2347                 }
2348
2349                 v3f pointed_pos_under = player_pos;
2350                 v3f pointed_pos_above = player_pos;
2351                 if(pointed.type == POINTEDTHING_NODE)
2352                 {
2353                         pointed_pos_under = intToFloat(p_under, BS);
2354                         pointed_pos_above = intToFloat(p_above, BS);
2355                 }
2356                 else if(pointed.type == POINTEDTHING_OBJECT)
2357                 {
2358                         pointed_pos_under = pointed_object->getBasePosition();
2359                         pointed_pos_above = pointed_pos_under;
2360                 }
2361
2362                 /*
2363                         Check that target is reasonably close
2364                         (only when digging or placing things)
2365                 */
2366                 if(action == 0 || action == 2 || action == 3)
2367                 {
2368                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2369                         float max_d = BS * 14; // Just some large enough value
2370                         if(d > max_d){
2371                                 actionstream<<"Player "<<player->getName()
2372                                                 <<" tried to access "<<pointed.dump()
2373                                                 <<" from too far: "
2374                                                 <<"d="<<d<<", max_d="<<max_d
2375                                                 <<". ignoring."<<std::endl;
2376                                 // Re-send block to revert change on client-side
2377                                 RemoteClient *client = getClient(peer_id);
2378                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2379                                 client->SetBlockNotSent(blockpos);
2380                                 // Call callbacks
2381                                 m_script->on_cheat(playersao, "interacted_too_far");
2382                                 // Do nothing else
2383                                 return;
2384                         }
2385                 }
2386
2387                 /*
2388                         Make sure the player is allowed to do it
2389                 */
2390                 if(!checkPriv(player->getName(), "interact"))
2391                 {
2392                         actionstream<<player->getName()<<" attempted to interact with "
2393                                         <<pointed.dump()<<" without 'interact' privilege"
2394                                         <<std::endl;
2395                         // Re-send block to revert change on client-side
2396                         RemoteClient *client = getClient(peer_id);
2397                         // Digging completed -> under
2398                         if(action == 2){
2399                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2400                                 client->SetBlockNotSent(blockpos);
2401                         }
2402                         // Placement -> above
2403                         if(action == 3){
2404                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2405                                 client->SetBlockNotSent(blockpos);
2406                         }
2407                         return;
2408                 }
2409
2410                 /*
2411                         If something goes wrong, this player is to blame
2412                 */
2413                 RollbackScopeActor rollback_scope(m_rollback,
2414                                 std::string("player:")+player->getName());
2415
2416                 /*
2417                         0: start digging or punch object
2418                 */
2419                 if(action == 0)
2420                 {
2421                         if(pointed.type == POINTEDTHING_NODE)
2422                         {
2423                                 /*
2424                                         NOTE: This can be used in the future to check if
2425                                         somebody is cheating, by checking the timing.
2426                                 */
2427                                 MapNode n(CONTENT_IGNORE);
2428                                 try
2429                                 {
2430                                         n = m_env->getMap().getNode(p_under);
2431                                 }
2432                                 catch(InvalidPositionException &e)
2433                                 {
2434                                         infostream<<"Server: Not punching: Node not found."
2435                                                         <<" Adding block to emerge queue."
2436                                                         <<std::endl;
2437                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2438                                 }
2439                                 if(n.getContent() != CONTENT_IGNORE)
2440                                         m_script->node_on_punch(p_under, n, playersao, pointed);
2441                                 // Cheat prevention
2442                                 playersao->noCheatDigStart(p_under);
2443                         }
2444                         else if(pointed.type == POINTEDTHING_OBJECT)
2445                         {
2446                                 // Skip if object has been removed
2447                                 if(pointed_object->m_removed)
2448                                         return;
2449
2450                                 actionstream<<player->getName()<<" punches object "
2451                                                 <<pointed.object_id<<": "
2452                                                 <<pointed_object->getDescription()<<std::endl;
2453
2454                                 ItemStack punchitem = playersao->getWieldedItem();
2455                                 ToolCapabilities toolcap =
2456                                                 punchitem.getToolCapabilities(m_itemdef);
2457                                 v3f dir = (pointed_object->getBasePosition() -
2458                                                 (player->getPosition() + player->getEyeOffset())
2459                                                         ).normalize();
2460                                 float time_from_last_punch =
2461                                         playersao->resetTimeFromLastPunch();
2462                                 pointed_object->punch(dir, &toolcap, playersao,
2463                                                 time_from_last_punch);
2464                         }
2465
2466                 } // action == 0
2467
2468                 /*
2469                         1: stop digging
2470                 */
2471                 else if(action == 1)
2472                 {
2473                 } // action == 1
2474
2475                 /*
2476                         2: Digging completed
2477                 */
2478                 else if(action == 2)
2479                 {
2480                         // Only digging of nodes
2481                         if(pointed.type == POINTEDTHING_NODE)
2482                         {
2483                                 MapNode n(CONTENT_IGNORE);
2484                                 try
2485                                 {
2486                                         n = m_env->getMap().getNode(p_under);
2487                                 }
2488                                 catch(InvalidPositionException &e)
2489                                 {
2490                                         infostream<<"Server: Not finishing digging: Node not found."
2491                                                         <<" Adding block to emerge queue."
2492                                                         <<std::endl;
2493                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2494                                 }
2495
2496                                 /* Cheat prevention */
2497                                 bool is_valid_dig = true;
2498                                 if(!isSingleplayer() && !g_settings->getBool("disable_anticheat"))
2499                                 {
2500                                         v3s16 nocheat_p = playersao->getNoCheatDigPos();
2501                                         float nocheat_t = playersao->getNoCheatDigTime();
2502                                         playersao->noCheatDigEnd();
2503                                         // If player didn't start digging this, ignore dig
2504                                         if(nocheat_p != p_under){
2505                                                 infostream<<"Server: NoCheat: "<<player->getName()
2506                                                                 <<" started digging "
2507                                                                 <<PP(nocheat_p)<<" and completed digging "
2508                                                                 <<PP(p_under)<<"; not digging."<<std::endl;
2509                                                 is_valid_dig = false;
2510                                                 // Call callbacks
2511                                                 m_script->on_cheat(playersao, "finished_unknown_dig");
2512                                         }
2513                                         // Get player's wielded item
2514                                         ItemStack playeritem;
2515                                         InventoryList *mlist = playersao->getInventory()->getList("main");
2516                                         if(mlist != NULL)
2517                                                 playeritem = mlist->getItem(playersao->getWieldIndex());
2518                                         ToolCapabilities playeritem_toolcap =
2519                                                         playeritem.getToolCapabilities(m_itemdef);
2520                                         // Get diggability and expected digging time
2521                                         DigParams params = getDigParams(m_nodedef->get(n).groups,
2522                                                         &playeritem_toolcap);
2523                                         // If can't dig, try hand
2524                                         if(!params.diggable){
2525                                                 const ItemDefinition &hand = m_itemdef->get("");
2526                                                 const ToolCapabilities *tp = hand.tool_capabilities;
2527                                                 if(tp)
2528                                                         params = getDigParams(m_nodedef->get(n).groups, tp);
2529                                         }
2530                                         // If can't dig, ignore dig
2531                                         if(!params.diggable){
2532                                                 infostream<<"Server: NoCheat: "<<player->getName()
2533                                                                 <<" completed digging "<<PP(p_under)
2534                                                                 <<", which is not diggable with tool. not digging."
2535                                                                 <<std::endl;
2536                                                 is_valid_dig = false;
2537                                                 // Call callbacks
2538                                                 m_script->on_cheat(playersao, "dug_unbreakable");
2539                                         }
2540                                         // Check digging time
2541                                         // If already invalidated, we don't have to
2542                                         if(!is_valid_dig){
2543                                                 // Well not our problem then
2544                                         }
2545                                         // Clean and long dig
2546                                         else if(params.time > 2.0 && nocheat_t * 1.2 > params.time){
2547                                                 // All is good, but grab time from pool; don't care if
2548                                                 // it's actually available
2549                                                 playersao->getDigPool().grab(params.time);
2550                                         }
2551                                         // Short or laggy dig
2552                                         // Try getting the time from pool
2553                                         else if(playersao->getDigPool().grab(params.time)){
2554                                                 // All is good
2555                                         }
2556                                         // Dig not possible
2557                                         else{
2558                                                 infostream<<"Server: NoCheat: "<<player->getName()
2559                                                                 <<" completed digging "<<PP(p_under)
2560                                                                 <<"too fast; not digging."<<std::endl;
2561                                                 is_valid_dig = false;
2562                                                 // Call callbacks
2563                                                 m_script->on_cheat(playersao, "dug_too_fast");
2564                                         }
2565                                 }
2566
2567                                 /* Actually dig node */
2568
2569                                 if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
2570                                         m_script->node_on_dig(p_under, n, playersao);
2571
2572                                 // Send unusual result (that is, node not being removed)
2573                                 if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
2574                                 {
2575                                         // Re-send block to revert change on client-side
2576                                         RemoteClient *client = getClient(peer_id);
2577                                         v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2578                                         client->SetBlockNotSent(blockpos);
2579                                 }
2580                         }
2581                 } // action == 2
2582
2583                 /*
2584                         3: place block or right-click object
2585                 */
2586                 else if(action == 3)
2587                 {
2588                         ItemStack item = playersao->getWieldedItem();
2589
2590                         // Reset build time counter
2591                         if(pointed.type == POINTEDTHING_NODE &&
2592                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
2593                                 getClient(peer_id)->m_time_from_building = 0.0;
2594
2595                         if(pointed.type == POINTEDTHING_OBJECT)
2596                         {
2597                                 // Right click object
2598
2599                                 // Skip if object has been removed
2600                                 if(pointed_object->m_removed)
2601                                         return;
2602
2603                                 actionstream<<player->getName()<<" right-clicks object "
2604                                                 <<pointed.object_id<<": "
2605                                                 <<pointed_object->getDescription()<<std::endl;
2606
2607                                 // Do stuff
2608                                 pointed_object->rightClick(playersao);
2609                         }
2610                         else if(m_script->item_OnPlace(
2611                                         item, playersao, pointed))
2612                         {
2613                                 // Placement was handled in lua
2614
2615                                 // Apply returned ItemStack
2616                                 playersao->setWieldedItem(item);
2617                         }
2618
2619                         // If item has node placement prediction, always send the
2620                         // blocks to make sure the client knows what exactly happened
2621                         if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
2622                                 RemoteClient *client = getClient(peer_id);
2623                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2624                                 client->SetBlockNotSent(blockpos);
2625                                 v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2626                                 if(blockpos2 != blockpos){
2627                                         client->SetBlockNotSent(blockpos2);
2628                                 }
2629                         }
2630                 } // action == 3
2631
2632                 /*
2633                         4: use
2634                 */
2635                 else if(action == 4)
2636                 {
2637                         ItemStack item = playersao->getWieldedItem();
2638
2639                         actionstream<<player->getName()<<" uses "<<item.name
2640                                         <<", pointing at "<<pointed.dump()<<std::endl;
2641
2642                         if(m_script->item_OnUse(
2643                                         item, playersao, pointed))
2644                         {
2645                                 // Apply returned ItemStack
2646                                 playersao->setWieldedItem(item);
2647                         }
2648
2649                 } // action == 4
2650                 
2651
2652                 /*
2653                         Catch invalid actions
2654                 */
2655                 else
2656                 {
2657                         infostream<<"WARNING: Server: Invalid action "
2658                                         <<action<<std::endl;
2659                 }
2660         }
2661         else if(command == TOSERVER_REMOVED_SOUNDS)
2662         {
2663                 std::string datastring((char*)&data[2], datasize-2);
2664                 std::istringstream is(datastring, std::ios_base::binary);
2665
2666                 int num = readU16(is);
2667                 for(int k=0; k<num; k++){
2668                         s32 id = readS32(is);
2669                         std::map<s32, ServerPlayingSound>::iterator i =
2670                                         m_playing_sounds.find(id);
2671                         if(i == m_playing_sounds.end())
2672                                 continue;
2673                         ServerPlayingSound &psound = i->second;
2674                         psound.clients.erase(peer_id);
2675                         if(psound.clients.size() == 0)
2676                                 m_playing_sounds.erase(i++);
2677                 }
2678         }
2679         else if(command == TOSERVER_NODEMETA_FIELDS)
2680         {
2681                 std::string datastring((char*)&data[2], datasize-2);
2682                 std::istringstream is(datastring, std::ios_base::binary);
2683
2684                 v3s16 p = readV3S16(is);
2685                 std::string formname = deSerializeString(is);
2686                 int num = readU16(is);
2687                 std::map<std::string, std::string> fields;
2688                 for(int k=0; k<num; k++){
2689                         std::string fieldname = deSerializeString(is);
2690                         std::string fieldvalue = deSerializeLongString(is);
2691                         fields[fieldname] = fieldvalue;
2692                 }
2693
2694                 // If something goes wrong, this player is to blame
2695                 RollbackScopeActor rollback_scope(m_rollback,
2696                                 std::string("player:")+player->getName());
2697
2698                 // Check the target node for rollback data; leave others unnoticed
2699                 RollbackNode rn_old(&m_env->getMap(), p, this);
2700
2701                 m_script->node_on_receive_fields(p, formname, fields,playersao);
2702
2703                 // Report rollback data
2704                 RollbackNode rn_new(&m_env->getMap(), p, this);
2705                 if(rollback() && rn_new != rn_old){
2706                         RollbackAction action;
2707                         action.setSetNode(p, rn_old, rn_new);
2708                         rollback()->reportAction(action);
2709                 }
2710         }
2711         else if(command == TOSERVER_INVENTORY_FIELDS)
2712         {
2713                 std::string datastring((char*)&data[2], datasize-2);
2714                 std::istringstream is(datastring, std::ios_base::binary);
2715
2716                 std::string formname = deSerializeString(is);
2717                 int num = readU16(is);
2718                 std::map<std::string, std::string> fields;
2719                 for(int k=0; k<num; k++){
2720                         std::string fieldname = deSerializeString(is);
2721                         std::string fieldvalue = deSerializeLongString(is);
2722                         fields[fieldname] = fieldvalue;
2723                 }
2724
2725                 m_script->on_playerReceiveFields(playersao, formname, fields);
2726         }
2727         else
2728         {
2729                 infostream<<"Server::ProcessData(): Ignoring "
2730                                 "unknown command "<<command<<std::endl;
2731         }
2732
2733         } //try
2734         catch(SendFailedException &e)
2735         {
2736                 errorstream<<"Server::ProcessData(): SendFailedException: "
2737                                 <<"what="<<e.what()
2738                                 <<std::endl;
2739         }
2740 }
2741
2742 void Server::setTimeOfDay(u32 time)
2743 {
2744         m_env->setTimeOfDay(time);
2745         m_time_of_day_send_timer = 0;
2746 }
2747
2748 void Server::onMapEditEvent(MapEditEvent *event)
2749 {
2750         //infostream<<"Server::onMapEditEvent()"<<std::endl;
2751         if(m_ignore_map_edit_events)
2752                 return;
2753         if(m_ignore_map_edit_events_area.contains(event->getArea()))
2754                 return;
2755         MapEditEvent *e = event->clone();
2756         m_unsent_map_edit_queue.push_back(e);
2757 }
2758
2759 Inventory* Server::getInventory(const InventoryLocation &loc)
2760 {
2761         switch(loc.type){
2762         case InventoryLocation::UNDEFINED:
2763         {}
2764         break;
2765         case InventoryLocation::CURRENT_PLAYER:
2766         {}
2767         break;
2768         case InventoryLocation::PLAYER:
2769         {
2770                 Player *player = m_env->getPlayer(loc.name.c_str());
2771                 if(!player)
2772                         return NULL;
2773                 PlayerSAO *playersao = player->getPlayerSAO();
2774                 if(!playersao)
2775                         return NULL;
2776                 return playersao->getInventory();
2777         }
2778         break;
2779         case InventoryLocation::NODEMETA:
2780         {
2781                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
2782                 if(!meta)
2783                         return NULL;
2784                 return meta->getInventory();
2785         }
2786         break;
2787         case InventoryLocation::DETACHED:
2788         {
2789                 if(m_detached_inventories.count(loc.name) == 0)
2790                         return NULL;
2791                 return m_detached_inventories[loc.name];
2792         }
2793         break;
2794         default:
2795                 assert(0);
2796         }
2797         return NULL;
2798 }
2799 void Server::setInventoryModified(const InventoryLocation &loc)
2800 {
2801         switch(loc.type){
2802         case InventoryLocation::UNDEFINED:
2803         {}
2804         break;
2805         case InventoryLocation::PLAYER:
2806         {
2807                 Player *player = m_env->getPlayer(loc.name.c_str());
2808                 if(!player)
2809                         return;
2810                 PlayerSAO *playersao = player->getPlayerSAO();
2811                 if(!playersao)
2812                         return;
2813                 playersao->m_inventory_not_sent = true;
2814                 playersao->m_wielded_item_not_sent = true;
2815         }
2816         break;
2817         case InventoryLocation::NODEMETA:
2818         {
2819                 v3s16 blockpos = getNodeBlockPos(loc.p);
2820
2821                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2822                 if(block)
2823                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
2824
2825                 setBlockNotSent(blockpos);
2826         }
2827         break;
2828         case InventoryLocation::DETACHED:
2829         {
2830                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
2831         }
2832         break;
2833         default:
2834                 assert(0);
2835         }
2836 }
2837
2838 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
2839 {
2840         std::list<u16> clients = m_clients.getClientIDs();
2841         m_clients.Lock();
2842         // Set the modified blocks unsent for all the clients
2843         for (std::list<u16>::iterator
2844                  i = clients.begin();
2845                  i != clients.end(); ++i) {
2846                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2847                         if (client != NULL)
2848                                 client->SetBlocksNotSent(block);
2849                 }
2850         m_clients.Unlock();
2851 }
2852
2853 void Server::peerAdded(con::Peer *peer)
2854 {
2855         DSTACK(__FUNCTION_NAME);
2856         verbosestream<<"Server::peerAdded(): peer->id="
2857                         <<peer->id<<std::endl;
2858
2859         con::PeerChange c;
2860         c.type = con::PEER_ADDED;
2861         c.peer_id = peer->id;
2862         c.timeout = false;
2863         m_peer_change_queue.push_back(c);
2864 }
2865
2866 void Server::deletingPeer(con::Peer *peer, bool timeout)
2867 {
2868         DSTACK(__FUNCTION_NAME);
2869         verbosestream<<"Server::deletingPeer(): peer->id="
2870                         <<peer->id<<", timeout="<<timeout<<std::endl;
2871
2872         m_clients.event(peer->id,Disconnect);
2873         con::PeerChange c;
2874         c.type = con::PEER_REMOVED;
2875         c.peer_id = peer->id;
2876         c.timeout = timeout;
2877         m_peer_change_queue.push_back(c);
2878 }
2879
2880 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
2881 {
2882         *retval = m_con.getPeerStat(peer_id,type);
2883         if (*retval == -1) return false;
2884         return true;
2885 }
2886
2887 bool Server::getClientInfo(
2888                 u16          peer_id,
2889                 ClientState* state,
2890                 u32*         uptime,
2891                 u8*          ser_vers,
2892                 u16*         prot_vers,
2893                 u8*          major,
2894                 u8*          minor,
2895                 u8*          patch,
2896                 std::string* vers_string
2897         )
2898 {
2899         *state = m_clients.getClientState(peer_id);
2900         m_clients.Lock();
2901         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,Invalid);
2902
2903         if (client == NULL)
2904                 return false;
2905
2906         *uptime = client->uptime();
2907         *ser_vers = client->serialization_version;
2908         *prot_vers = client->net_proto_version;
2909
2910         *major = client->getMajor();
2911         *minor = client->getMinor();
2912         *patch = client->getPatch();
2913         *vers_string = client->getPatch();
2914
2915         m_clients.Unlock();
2916
2917         return true;
2918 }
2919
2920 void Server::handlePeerChanges()
2921 {
2922         while(m_peer_change_queue.size() > 0)
2923         {
2924                 con::PeerChange c = m_peer_change_queue.pop_front();
2925
2926                 verbosestream<<"Server: Handling peer change: "
2927                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
2928                                 <<std::endl;
2929
2930                 switch(c.type)
2931                 {
2932                 case con::PEER_ADDED:
2933                         m_clients.CreateClient(c.peer_id);
2934                         break;
2935
2936                 case con::PEER_REMOVED:
2937                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
2938                         break;
2939
2940                 default:
2941                         assert("Invalid peer change event received!" == 0);
2942                         break;
2943                 }
2944         }
2945 }
2946
2947 void Server::SendMovement(u16 peer_id)
2948 {
2949         DSTACK(__FUNCTION_NAME);
2950         std::ostringstream os(std::ios_base::binary);
2951
2952         writeU16(os, TOCLIENT_MOVEMENT);
2953         writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
2954         writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
2955         writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
2956         writeF1000(os, g_settings->getFloat("movement_speed_walk"));
2957         writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
2958         writeF1000(os, g_settings->getFloat("movement_speed_fast"));
2959         writeF1000(os, g_settings->getFloat("movement_speed_climb"));
2960         writeF1000(os, g_settings->getFloat("movement_speed_jump"));
2961         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
2962         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
2963         writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
2964         writeF1000(os, g_settings->getFloat("movement_gravity"));
2965
2966         // Make data buffer
2967         std::string s = os.str();
2968         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2969         // Send as reliable
2970         m_clients.send(peer_id, 0, data, true);
2971 }
2972
2973 void Server::SendHP(u16 peer_id, u8 hp)
2974 {
2975         DSTACK(__FUNCTION_NAME);
2976         std::ostringstream os(std::ios_base::binary);
2977
2978         writeU16(os, TOCLIENT_HP);
2979         writeU8(os, hp);
2980
2981         // Make data buffer
2982         std::string s = os.str();
2983         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2984         // Send as reliable
2985         m_clients.send(peer_id, 0, data, true);
2986 }
2987
2988 void Server::SendBreath(u16 peer_id, u16 breath)
2989 {
2990         DSTACK(__FUNCTION_NAME);
2991         std::ostringstream os(std::ios_base::binary);
2992
2993         writeU16(os, TOCLIENT_BREATH);
2994         writeU16(os, breath);
2995
2996         // Make data buffer
2997         std::string s = os.str();
2998         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2999         // Send as reliable
3000         m_clients.send(peer_id, 0, data, true);
3001 }
3002
3003 void Server::SendAccessDenied(u16 peer_id,const std::wstring &reason)
3004 {
3005         DSTACK(__FUNCTION_NAME);
3006         std::ostringstream os(std::ios_base::binary);
3007
3008         writeU16(os, TOCLIENT_ACCESS_DENIED);
3009         os<<serializeWideString(reason);
3010
3011         // Make data buffer
3012         std::string s = os.str();
3013         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3014         // Send as reliable
3015         m_clients.send(peer_id, 0, data, true);
3016 }
3017
3018 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
3019                 v3f camera_point_target)
3020 {
3021         DSTACK(__FUNCTION_NAME);
3022         std::ostringstream os(std::ios_base::binary);
3023
3024         writeU16(os, TOCLIENT_DEATHSCREEN);
3025         writeU8(os, set_camera_point_target);
3026         writeV3F1000(os, camera_point_target);
3027
3028         // Make data buffer
3029         std::string s = os.str();
3030         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3031         // Send as reliable
3032         m_clients.send(peer_id, 0, data, true);
3033 }
3034
3035 void Server::SendItemDef(u16 peer_id,
3036                 IItemDefManager *itemdef, u16 protocol_version)
3037 {
3038         DSTACK(__FUNCTION_NAME);
3039         std::ostringstream os(std::ios_base::binary);
3040
3041         /*
3042                 u16 command
3043                 u32 length of the next item
3044                 zlib-compressed serialized ItemDefManager
3045         */
3046         writeU16(os, TOCLIENT_ITEMDEF);
3047         std::ostringstream tmp_os(std::ios::binary);
3048         itemdef->serialize(tmp_os, protocol_version);
3049         std::ostringstream tmp_os2(std::ios::binary);
3050         compressZlib(tmp_os.str(), tmp_os2);
3051         os<<serializeLongString(tmp_os2.str());
3052
3053         // Make data buffer
3054         std::string s = os.str();
3055         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3056                         <<"): size="<<s.size()<<std::endl;
3057         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3058         // Send as reliable
3059         m_clients.send(peer_id, 0, data, true);
3060 }
3061
3062 void Server::SendNodeDef(u16 peer_id,
3063                 INodeDefManager *nodedef, u16 protocol_version)
3064 {
3065         DSTACK(__FUNCTION_NAME);
3066         std::ostringstream os(std::ios_base::binary);
3067
3068         /*
3069                 u16 command
3070                 u32 length of the next item
3071                 zlib-compressed serialized NodeDefManager
3072         */
3073         writeU16(os, TOCLIENT_NODEDEF);
3074         std::ostringstream tmp_os(std::ios::binary);
3075         nodedef->serialize(tmp_os, protocol_version);
3076         std::ostringstream tmp_os2(std::ios::binary);
3077         compressZlib(tmp_os.str(), tmp_os2);
3078         os<<serializeLongString(tmp_os2.str());
3079
3080         // Make data buffer
3081         std::string s = os.str();
3082         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3083                         <<"): size="<<s.size()<<std::endl;
3084         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3085         // Send as reliable
3086         m_clients.send(peer_id, 0, data, true);
3087 }
3088
3089 /*
3090         Non-static send methods
3091 */
3092
3093 void Server::SendInventory(u16 peer_id)
3094 {
3095         DSTACK(__FUNCTION_NAME);
3096
3097         PlayerSAO *playersao = getPlayerSAO(peer_id);
3098         assert(playersao);
3099
3100         playersao->m_inventory_not_sent = false;
3101
3102         /*
3103                 Serialize it
3104         */
3105
3106         std::ostringstream os;
3107         playersao->getInventory()->serialize(os);
3108
3109         std::string s = os.str();
3110
3111         SharedBuffer<u8> data(s.size()+2);
3112         writeU16(&data[0], TOCLIENT_INVENTORY);
3113         memcpy(&data[2], s.c_str(), s.size());
3114
3115         // Send as reliable
3116         m_clients.send(peer_id, 0, data, true);
3117 }
3118
3119 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3120 {
3121         DSTACK(__FUNCTION_NAME);
3122
3123         std::ostringstream os(std::ios_base::binary);
3124         u8 buf[12];
3125
3126         // Write command
3127         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3128         os.write((char*)buf, 2);
3129
3130         // Write length
3131         writeU16(buf, message.size());
3132         os.write((char*)buf, 2);
3133
3134         // Write string
3135         for(u32 i=0; i<message.size(); i++)
3136         {
3137                 u16 w = message[i];
3138                 writeU16(buf, w);
3139                 os.write((char*)buf, 2);
3140         }
3141
3142         // Make data buffer
3143         std::string s = os.str();
3144         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3145
3146         if (peer_id != PEER_ID_INEXISTENT)
3147         {
3148                 // Send as reliable
3149                 m_clients.send(peer_id, 0, data, true);
3150         }
3151         else
3152         {
3153                 m_clients.sendToAll(0,data,true);
3154         }
3155 }
3156
3157 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
3158                                      const std::string &formname)
3159 {
3160         DSTACK(__FUNCTION_NAME);
3161
3162         std::ostringstream os(std::ios_base::binary);
3163         u8 buf[12];
3164
3165         // Write command
3166         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3167         os.write((char*)buf, 2);
3168         os<<serializeLongString(formspec);
3169         os<<serializeString(formname);
3170
3171         // Make data buffer
3172         std::string s = os.str();
3173         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3174         // Send as reliable
3175         m_clients.send(peer_id, 0, data, true);
3176 }
3177
3178 // Spawns a particle on peer with peer_id
3179 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3180                                 float expirationtime, float size, bool collisiondetection,
3181                                 bool vertical, std::string texture)
3182 {
3183         DSTACK(__FUNCTION_NAME);
3184
3185         std::ostringstream os(std::ios_base::binary);
3186         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3187         writeV3F1000(os, pos);
3188         writeV3F1000(os, velocity);
3189         writeV3F1000(os, acceleration);
3190         writeF1000(os, expirationtime);
3191         writeF1000(os, size);
3192         writeU8(os,  collisiondetection);
3193         os<<serializeLongString(texture);
3194         writeU8(os, vertical);
3195
3196         // Make data buffer
3197         std::string s = os.str();
3198         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3199
3200         if (peer_id != PEER_ID_INEXISTENT)
3201         {
3202         // Send as reliable
3203                 m_clients.send(peer_id, 0, data, true);
3204         }
3205         else
3206         {
3207                 m_clients.sendToAll(0,data,true);
3208         }
3209 }
3210
3211 // Adds a ParticleSpawner on peer with peer_id
3212 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3213         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3214         float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
3215 {
3216         DSTACK(__FUNCTION_NAME);
3217
3218         std::ostringstream os(std::ios_base::binary);
3219         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3220
3221         writeU16(os, amount);
3222         writeF1000(os, spawntime);
3223         writeV3F1000(os, minpos);
3224         writeV3F1000(os, maxpos);
3225         writeV3F1000(os, minvel);
3226         writeV3F1000(os, maxvel);
3227         writeV3F1000(os, minacc);
3228         writeV3F1000(os, maxacc);
3229         writeF1000(os, minexptime);
3230         writeF1000(os, maxexptime);
3231         writeF1000(os, minsize);
3232         writeF1000(os, maxsize);
3233         writeU8(os,  collisiondetection);
3234         os<<serializeLongString(texture);
3235         writeU32(os, id);
3236         writeU8(os, vertical);
3237
3238         // Make data buffer
3239         std::string s = os.str();
3240         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3241
3242         if (peer_id != PEER_ID_INEXISTENT)
3243         {
3244                 // Send as reliable
3245                 m_clients.send(peer_id, 0, data, true);
3246         }
3247         else {
3248                 m_clients.sendToAll(0,data,true);
3249         }
3250 }
3251
3252 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3253 {
3254         DSTACK(__FUNCTION_NAME);
3255
3256         std::ostringstream os(std::ios_base::binary);
3257         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3258
3259         writeU16(os, id);
3260
3261         // Make data buffer
3262         std::string s = os.str();
3263         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3264
3265         if (peer_id != PEER_ID_INEXISTENT) {
3266                 // Send as reliable
3267                 m_clients.send(peer_id, 0, data, true);
3268         }
3269         else {
3270                 m_clients.sendToAll(0,data,true);
3271         }
3272
3273 }
3274
3275 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3276 {
3277         std::ostringstream os(std::ios_base::binary);
3278
3279         // Write command
3280         writeU16(os, TOCLIENT_HUDADD);
3281         writeU32(os, id);
3282         writeU8(os, (u8)form->type);
3283         writeV2F1000(os, form->pos);
3284         os << serializeString(form->name);
3285         writeV2F1000(os, form->scale);
3286         os << serializeString(form->text);
3287         writeU32(os, form->number);
3288         writeU32(os, form->item);
3289         writeU32(os, form->dir);
3290         writeV2F1000(os, form->align);
3291         writeV2F1000(os, form->offset);
3292         writeV3F1000(os, form->world_pos);
3293         writeV2S32(os,form->size);
3294
3295         // Make data buffer
3296         std::string s = os.str();
3297         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3298         // Send as reliable
3299         m_clients.send(peer_id, 1, data, true);
3300 }
3301
3302 void Server::SendHUDRemove(u16 peer_id, u32 id)
3303 {
3304         std::ostringstream os(std::ios_base::binary);
3305
3306         // Write command
3307         writeU16(os, TOCLIENT_HUDRM);
3308         writeU32(os, id);
3309
3310         // Make data buffer
3311         std::string s = os.str();
3312         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3313         // Send as reliable
3314
3315         m_clients.send(peer_id, 1, data, true);
3316 }
3317
3318 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3319 {
3320         std::ostringstream os(std::ios_base::binary);
3321
3322         // Write command
3323         writeU16(os, TOCLIENT_HUDCHANGE);
3324         writeU32(os, id);
3325         writeU8(os, (u8)stat);
3326         switch (stat) {
3327                 case HUD_STAT_POS:
3328                 case HUD_STAT_SCALE:
3329                 case HUD_STAT_ALIGN:
3330                 case HUD_STAT_OFFSET:
3331                         writeV2F1000(os, *(v2f *)value);
3332                         break;
3333                 case HUD_STAT_NAME:
3334                 case HUD_STAT_TEXT:
3335                         os << serializeString(*(std::string *)value);
3336                         break;
3337                 case HUD_STAT_WORLD_POS:
3338                         writeV3F1000(os, *(v3f *)value);
3339                         break;
3340                 case HUD_STAT_SIZE:
3341                         writeV2S32(os,*(v2s32 *)value);
3342                         break;
3343                 case HUD_STAT_NUMBER:
3344                 case HUD_STAT_ITEM:
3345                 case HUD_STAT_DIR:
3346                 default:
3347                         writeU32(os, *(u32 *)value);
3348                         break;
3349         }
3350
3351         // Make data buffer
3352         std::string s = os.str();
3353         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3354         // Send as reliable
3355         m_clients.send(peer_id, 0, data, true);
3356 }
3357
3358 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3359 {
3360         std::ostringstream os(std::ios_base::binary);
3361
3362         // Write command
3363         writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3364         writeU32(os, flags);
3365         writeU32(os, mask);
3366
3367         // Make data buffer
3368         std::string s = os.str();
3369         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3370         // Send as reliable
3371         m_clients.send(peer_id, 0, data, true);
3372 }
3373
3374 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3375 {
3376         std::ostringstream os(std::ios_base::binary);
3377
3378         // Write command
3379         writeU16(os, TOCLIENT_HUD_SET_PARAM);
3380         writeU16(os, param);
3381         os<<serializeString(value);
3382
3383         // Make data buffer
3384         std::string s = os.str();
3385         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3386         // Send as reliable
3387         m_clients.send(peer_id, 0, data, true);
3388 }
3389
3390 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
3391                 const std::string &type, const std::vector<std::string> &params)
3392 {
3393         std::ostringstream os(std::ios_base::binary);
3394
3395         // Write command
3396         writeU16(os, TOCLIENT_SET_SKY);
3397         writeARGB8(os, bgcolor);
3398         os<<serializeString(type);
3399         writeU16(os, params.size());
3400         for(size_t i=0; i<params.size(); i++)
3401                 os<<serializeString(params[i]);
3402
3403         // Make data buffer
3404         std::string s = os.str();
3405         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3406         // Send as reliable
3407         m_clients.send(peer_id, 0, data, true);
3408 }
3409
3410 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
3411                 float ratio)
3412 {
3413         std::ostringstream os(std::ios_base::binary);
3414
3415         // Write command
3416         writeU16(os, TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO);
3417         writeU8(os, do_override);
3418         writeU16(os, ratio*65535);
3419
3420         // Make data buffer
3421         std::string s = os.str();
3422         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3423         // Send as reliable
3424         m_clients.send(peer_id, 0, data, true);
3425 }
3426
3427 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
3428 {
3429         DSTACK(__FUNCTION_NAME);
3430
3431         // Make packet
3432         SharedBuffer<u8> data(2+2+4);
3433         writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
3434         writeU16(&data[2], time);
3435         writeF1000(&data[4], time_speed);
3436
3437         if (peer_id == PEER_ID_INEXISTENT) {
3438                 m_clients.sendToAll(0,data,true);
3439         }
3440         else {
3441                 // Send as reliable
3442                 m_clients.send(peer_id, 0, data, true);
3443         }
3444 }
3445
3446 void Server::SendPlayerHP(u16 peer_id)
3447 {
3448         DSTACK(__FUNCTION_NAME);
3449         PlayerSAO *playersao = getPlayerSAO(peer_id);
3450         assert(playersao);
3451         playersao->m_hp_not_sent = false;
3452         SendHP(peer_id, playersao->getHP());
3453         m_script->player_event(playersao,"health_changed");
3454
3455         // Send to other clients
3456         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
3457         ActiveObjectMessage aom(playersao->getId(), true, str);
3458         playersao->m_messages_out.push_back(aom);
3459 }
3460
3461 void Server::SendPlayerBreath(u16 peer_id)
3462 {
3463         DSTACK(__FUNCTION_NAME);
3464         PlayerSAO *playersao = getPlayerSAO(peer_id);
3465         assert(playersao);
3466         playersao->m_breath_not_sent = false;
3467         m_script->player_event(playersao,"breath_changed");
3468         SendBreath(peer_id, playersao->getBreath());
3469 }
3470
3471 void Server::SendMovePlayer(u16 peer_id)
3472 {
3473         DSTACK(__FUNCTION_NAME);
3474         Player *player = m_env->getPlayer(peer_id);
3475         assert(player);
3476
3477         std::ostringstream os(std::ios_base::binary);
3478         writeU16(os, TOCLIENT_MOVE_PLAYER);
3479         writeV3F1000(os, player->getPosition());
3480         writeF1000(os, player->getPitch());
3481         writeF1000(os, player->getYaw());
3482
3483         {
3484                 v3f pos = player->getPosition();
3485                 f32 pitch = player->getPitch();
3486                 f32 yaw = player->getYaw();
3487                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3488                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3489                                 <<" pitch="<<pitch
3490                                 <<" yaw="<<yaw
3491                                 <<std::endl;
3492         }
3493
3494         // Make data buffer
3495         std::string s = os.str();
3496         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3497         // Send as reliable
3498         m_clients.send(peer_id, 0, data, true);
3499 }
3500
3501 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
3502 {
3503         std::ostringstream os(std::ios_base::binary);
3504
3505         writeU16(os, TOCLIENT_LOCAL_PLAYER_ANIMATIONS);
3506         writeV2S32(os, animation_frames[0]);
3507         writeV2S32(os, animation_frames[1]);
3508         writeV2S32(os, animation_frames[2]);
3509         writeV2S32(os, animation_frames[3]);
3510         writeF1000(os, animation_speed);
3511
3512         // Make data buffer
3513         std::string s = os.str();
3514         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3515         // Send as reliable
3516         m_clients.send(peer_id, 0, data, true);
3517 }
3518
3519 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
3520 {
3521         std::ostringstream os(std::ios_base::binary);
3522
3523         writeU16(os, TOCLIENT_EYE_OFFSET);
3524         writeV3F1000(os, first);
3525         writeV3F1000(os, third);
3526
3527         // Make data buffer
3528         std::string s = os.str();
3529         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3530         // Send as reliable
3531         m_clients.send(peer_id, 0, data, true);
3532 }
3533 void Server::SendPlayerPrivileges(u16 peer_id)
3534 {
3535         Player *player = m_env->getPlayer(peer_id);
3536         assert(player);
3537         if(player->peer_id == PEER_ID_INEXISTENT)
3538                 return;
3539
3540         std::set<std::string> privs;
3541         m_script->getAuth(player->getName(), NULL, &privs);
3542
3543         std::ostringstream os(std::ios_base::binary);
3544         writeU16(os, TOCLIENT_PRIVILEGES);
3545         writeU16(os, privs.size());
3546         for(std::set<std::string>::const_iterator i = privs.begin();
3547                         i != privs.end(); i++){
3548                 os<<serializeString(*i);
3549         }
3550
3551         // Make data buffer
3552         std::string s = os.str();
3553         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3554         // Send as reliable
3555         m_clients.send(peer_id, 0, data, true);
3556 }
3557
3558 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3559 {
3560         Player *player = m_env->getPlayer(peer_id);
3561         assert(player);
3562         if(player->peer_id == PEER_ID_INEXISTENT)
3563                 return;
3564
3565         std::ostringstream os(std::ios_base::binary);
3566         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3567         os<<serializeLongString(player->inventory_formspec);
3568
3569         // Make data buffer
3570         std::string s = os.str();
3571         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3572         // Send as reliable
3573         m_clients.send(peer_id, 0, data, true);
3574 }
3575
3576 s32 Server::playSound(const SimpleSoundSpec &spec,
3577                 const ServerSoundParams &params)
3578 {
3579         // Find out initial position of sound
3580         bool pos_exists = false;
3581         v3f pos = params.getPos(m_env, &pos_exists);
3582         // If position is not found while it should be, cancel sound
3583         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3584                 return -1;
3585
3586         // Filter destination clients
3587         std::list<u16> dst_clients;
3588         if(params.to_player != "")
3589         {
3590                 Player *player = m_env->getPlayer(params.to_player.c_str());
3591                 if(!player){
3592                         infostream<<"Server::playSound: Player \""<<params.to_player
3593                                         <<"\" not found"<<std::endl;
3594                         return -1;
3595                 }
3596                 if(player->peer_id == PEER_ID_INEXISTENT){
3597                         infostream<<"Server::playSound: Player \""<<params.to_player
3598                                         <<"\" not connected"<<std::endl;
3599                         return -1;
3600                 }
3601                 dst_clients.push_back(player->peer_id);
3602         }
3603         else
3604         {
3605                 std::list<u16> clients = m_clients.getClientIDs();
3606
3607                 for(std::list<u16>::iterator
3608                                 i = clients.begin(); i != clients.end(); ++i)
3609                 {
3610                         Player *player = m_env->getPlayer(*i);
3611                         if(!player)
3612                                 continue;
3613                         if(pos_exists){
3614                                 if(player->getPosition().getDistanceFrom(pos) >
3615                                                 params.max_hear_distance)
3616                                         continue;
3617                         }
3618                         dst_clients.push_back(*i);
3619                 }
3620         }
3621         if(dst_clients.size() == 0)
3622                 return -1;
3623
3624         // Create the sound
3625         s32 id = m_next_sound_id++;
3626         // The sound will exist as a reference in m_playing_sounds
3627         m_playing_sounds[id] = ServerPlayingSound();
3628         ServerPlayingSound &psound = m_playing_sounds[id];
3629         psound.params = params;
3630         for(std::list<u16>::iterator i = dst_clients.begin();
3631                         i != dst_clients.end(); i++)
3632                 psound.clients.insert(*i);
3633         // Create packet
3634         std::ostringstream os(std::ios_base::binary);
3635         writeU16(os, TOCLIENT_PLAY_SOUND);
3636         writeS32(os, id);
3637         os<<serializeString(spec.name);
3638         writeF1000(os, spec.gain * params.gain);
3639         writeU8(os, params.type);
3640         writeV3F1000(os, pos);
3641         writeU16(os, params.object);
3642         writeU8(os, params.loop);
3643         // Make data buffer
3644         std::string s = os.str();
3645         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3646         // Send
3647         for(std::list<u16>::iterator i = dst_clients.begin();
3648                         i != dst_clients.end(); i++){
3649                 // Send as reliable
3650                 m_clients.send(*i, 0, data, true);
3651         }
3652         return id;
3653 }
3654 void Server::stopSound(s32 handle)
3655 {
3656         // Get sound reference
3657         std::map<s32, ServerPlayingSound>::iterator i =
3658                         m_playing_sounds.find(handle);
3659         if(i == m_playing_sounds.end())
3660                 return;
3661         ServerPlayingSound &psound = i->second;
3662         // Create packet
3663         std::ostringstream os(std::ios_base::binary);
3664         writeU16(os, TOCLIENT_STOP_SOUND);
3665         writeS32(os, handle);
3666         // Make data buffer
3667         std::string s = os.str();
3668         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3669         // Send
3670         for(std::set<u16>::iterator i = psound.clients.begin();
3671                         i != psound.clients.end(); i++){
3672                 // Send as reliable
3673                 m_clients.send(*i, 0, data, true);
3674         }
3675         // Remove sound reference
3676         m_playing_sounds.erase(i);
3677 }
3678
3679 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3680         std::list<u16> *far_players, float far_d_nodes)
3681 {
3682         float maxd = far_d_nodes*BS;
3683         v3f p_f = intToFloat(p, BS);
3684
3685         // Create packet
3686         u32 replysize = 8;
3687         SharedBuffer<u8> reply(replysize);
3688         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3689         writeS16(&reply[2], p.X);
3690         writeS16(&reply[4], p.Y);
3691         writeS16(&reply[6], p.Z);
3692
3693         std::list<u16> clients = m_clients.getClientIDs();
3694         for(std::list<u16>::iterator
3695                 i = clients.begin();
3696                 i != clients.end(); ++i)
3697         {
3698                 if(far_players)
3699                 {
3700                         // Get player
3701                         Player *player = m_env->getPlayer(*i);
3702                         if(player)
3703                         {
3704                                 // If player is far away, only set modified blocks not sent
3705                                 v3f player_pos = player->getPosition();
3706                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3707                                 {
3708                                         far_players->push_back(*i);
3709                                         continue;
3710                                 }
3711                         }
3712                 }
3713
3714                 // Send as reliable
3715                 m_clients.send(*i, 0, reply, true);
3716         }
3717 }
3718
3719 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3720                 std::list<u16> *far_players, float far_d_nodes,
3721                 bool remove_metadata)
3722 {
3723         float maxd = far_d_nodes*BS;
3724         v3f p_f = intToFloat(p, BS);
3725
3726         std::list<u16> clients = m_clients.getClientIDs();
3727                 for(std::list<u16>::iterator
3728                         i = clients.begin();
3729                         i != clients.end(); ++i)
3730                 {
3731
3732                 if(far_players)
3733                 {
3734                         // Get player
3735                         Player *player = m_env->getPlayer(*i);
3736                         if(player)
3737                         {
3738                                 // If player is far away, only set modified blocks not sent
3739                                 v3f player_pos = player->getPosition();
3740                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3741                                 {
3742                                         far_players->push_back(*i);
3743                                         continue;
3744                                 }
3745                         }
3746                 }
3747                 SharedBuffer<u8> reply(0);
3748                 m_clients.Lock();
3749                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
3750                 if (client != 0)
3751                 {
3752                         // Create packet
3753                         u32 replysize = 9 + MapNode::serializedLength(client->serialization_version);
3754                         reply = SharedBuffer<u8>(replysize);
3755                         writeU16(&reply[0], TOCLIENT_ADDNODE);
3756                         writeS16(&reply[2], p.X);
3757                         writeS16(&reply[4], p.Y);
3758                         writeS16(&reply[6], p.Z);
3759                         n.serialize(&reply[8], client->serialization_version);
3760                         u32 index = 8 + MapNode::serializedLength(client->serialization_version);
3761                         writeU8(&reply[index], remove_metadata ? 0 : 1);
3762
3763                         if (!remove_metadata) {
3764                                 if (client->net_proto_version <= 21) {
3765                                         // Old clients always clear metadata; fix it
3766                                         // by sending the full block again.
3767                                         client->SetBlockNotSent(p);
3768                                 }
3769                         }
3770                 }
3771                 m_clients.Unlock();
3772
3773                 // Send as reliable
3774                 if (reply.getSize() > 0)
3775                         m_clients.send(*i, 0, reply, true);
3776         }
3777 }
3778
3779 void Server::setBlockNotSent(v3s16 p)
3780 {
3781         std::list<u16> clients = m_clients.getClientIDs();
3782         m_clients.Lock();
3783         for(std::list<u16>::iterator
3784                 i = clients.begin();
3785                 i != clients.end(); ++i)
3786         {
3787                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
3788                 client->SetBlockNotSent(p);
3789         }
3790         m_clients.Unlock();
3791 }
3792
3793 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
3794 {
3795         DSTACK(__FUNCTION_NAME);
3796
3797         v3s16 p = block->getPos();
3798
3799 #if 0
3800         // Analyze it a bit
3801         bool completely_air = true;
3802         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3803         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3804         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3805         {
3806                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3807                 {
3808                         completely_air = false;
3809                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3810                 }
3811         }
3812
3813         // Print result
3814         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3815         if(completely_air)
3816                 infostream<<"[completely air] ";
3817         infostream<<std::endl;
3818 #endif
3819
3820         /*
3821                 Create a packet with the block in the right format
3822         */
3823
3824         std::ostringstream os(std::ios_base::binary);
3825         block->serialize(os, ver, false);
3826         block->serializeNetworkSpecific(os, net_proto_version);
3827         std::string s = os.str();
3828         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3829
3830         u32 replysize = 8 + blockdata.getSize();
3831         SharedBuffer<u8> reply(replysize);
3832         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3833         writeS16(&reply[2], p.X);
3834         writeS16(&reply[4], p.Y);
3835         writeS16(&reply[6], p.Z);
3836         memcpy(&reply[8], *blockdata, blockdata.getSize());
3837
3838         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3839                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3840
3841         /*
3842                 Send packet
3843         */
3844         m_clients.send(peer_id, 2, reply, true);
3845 }
3846
3847 void Server::SendBlocks(float dtime)
3848 {
3849         DSTACK(__FUNCTION_NAME);
3850
3851         JMutexAutoLock envlock(m_env_mutex);
3852         //TODO check if one big lock could be faster then multiple small ones
3853
3854         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
3855
3856         std::vector<PrioritySortedBlockTransfer> queue;
3857
3858         s32 total_sending = 0;
3859
3860         {
3861                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3862
3863                 std::list<u16> clients = m_clients.getClientIDs();
3864
3865                 m_clients.Lock();
3866                 for(std::list<u16>::iterator
3867                         i = clients.begin();
3868                         i != clients.end(); ++i)
3869                 {
3870                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i,Active);
3871
3872                         if (client == NULL)
3873                                 return;
3874
3875                         total_sending += client->SendingCount();
3876                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
3877                 }
3878                 m_clients.Unlock();
3879         }
3880
3881         // Sort.
3882         // Lowest priority number comes first.
3883         // Lowest is most important.
3884         std::sort(queue.begin(), queue.end());
3885
3886         m_clients.Lock();
3887         for(u32 i=0; i<queue.size(); i++)
3888         {
3889                 //TODO: Calculate limit dynamically
3890                 if(total_sending >= g_settings->getS32
3891                                 ("max_simultaneous_block_sends_server_total"))
3892                         break;
3893
3894                 PrioritySortedBlockTransfer q = queue[i];
3895
3896                 MapBlock *block = NULL;
3897                 try
3898                 {
3899                         block = m_env->getMap().getBlockNoCreate(q.pos);
3900                 }
3901                 catch(InvalidPositionException &e)
3902                 {
3903                         continue;
3904                 }
3905
3906                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id,Active);
3907
3908                 if(!client)
3909                         continue;
3910
3911                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
3912
3913                 client->SentBlock(q.pos);
3914                 total_sending++;
3915         }
3916         m_clients.Unlock();
3917 }
3918
3919 void Server::fillMediaCache()
3920 {
3921         DSTACK(__FUNCTION_NAME);
3922
3923         infostream<<"Server: Calculating media file checksums"<<std::endl;
3924
3925         // Collect all media file paths
3926         std::list<std::string> paths;
3927         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3928                         i != m_mods.end(); i++){
3929                 const ModSpec &mod = *i;
3930                 paths.push_back(mod.path + DIR_DELIM + "textures");
3931                 paths.push_back(mod.path + DIR_DELIM + "sounds");
3932                 paths.push_back(mod.path + DIR_DELIM + "media");
3933                 paths.push_back(mod.path + DIR_DELIM + "models");
3934         }
3935         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
3936
3937         // Collect media file information from paths into cache
3938         for(std::list<std::string>::iterator i = paths.begin();
3939                         i != paths.end(); i++)
3940         {
3941                 std::string mediapath = *i;
3942                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
3943                 for(u32 j=0; j<dirlist.size(); j++){
3944                         if(dirlist[j].dir) // Ignode dirs
3945                                 continue;
3946                         std::string filename = dirlist[j].name;
3947                         // If name contains illegal characters, ignore the file
3948                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
3949                                 infostream<<"Server: ignoring illegal file name: \""
3950                                                 <<filename<<"\""<<std::endl;
3951                                 continue;
3952                         }
3953                         // If name is not in a supported format, ignore it
3954                         const char *supported_ext[] = {
3955                                 ".png", ".jpg", ".bmp", ".tga",
3956                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
3957                                 ".ogg",
3958                                 ".x", ".b3d", ".md2", ".obj",
3959                                 NULL
3960                         };
3961                         if(removeStringEnd(filename, supported_ext) == ""){
3962                                 infostream<<"Server: ignoring unsupported file extension: \""
3963                                                 <<filename<<"\""<<std::endl;
3964                                 continue;
3965                         }
3966                         // Ok, attempt to load the file and add to cache
3967                         std::string filepath = mediapath + DIR_DELIM + filename;
3968                         // Read data
3969                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
3970                         if(fis.good() == false){
3971                                 errorstream<<"Server::fillMediaCache(): Could not open \""
3972                                                 <<filename<<"\" for reading"<<std::endl;
3973                                 continue;
3974                         }
3975                         std::ostringstream tmp_os(std::ios_base::binary);
3976                         bool bad = false;
3977                         for(;;){
3978                                 char buf[1024];
3979                                 fis.read(buf, 1024);
3980                                 std::streamsize len = fis.gcount();
3981                                 tmp_os.write(buf, len);
3982                                 if(fis.eof())
3983                                         break;
3984                                 if(!fis.good()){
3985                                         bad = true;
3986                                         break;
3987                                 }
3988                         }
3989                         if(bad){
3990                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
3991                                                 <<filename<<"\""<<std::endl;
3992                                 continue;
3993                         }
3994                         if(tmp_os.str().length() == 0){
3995                                 errorstream<<"Server::fillMediaCache(): Empty file \""
3996                                                 <<filepath<<"\""<<std::endl;
3997                                 continue;
3998                         }
3999
4000                         SHA1 sha1;
4001                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
4002
4003                         unsigned char *digest = sha1.getDigest();
4004                         std::string sha1_base64 = base64_encode(digest, 20);
4005                         std::string sha1_hex = hex_encode((char*)digest, 20);
4006                         free(digest);
4007
4008                         // Put in list
4009                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4010                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4011                 }
4012         }
4013 }
4014
4015 struct SendableMediaAnnouncement
4016 {
4017         std::string name;
4018         std::string sha1_digest;
4019
4020         SendableMediaAnnouncement(const std::string &name_="",
4021                                   const std::string &sha1_digest_=""):
4022                 name(name_),
4023                 sha1_digest(sha1_digest_)
4024         {}
4025 };
4026
4027 void Server::sendMediaAnnouncement(u16 peer_id)
4028 {
4029         DSTACK(__FUNCTION_NAME);
4030
4031         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4032                         <<std::endl;
4033
4034         std::list<SendableMediaAnnouncement> file_announcements;
4035
4036         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4037                         i != m_media.end(); i++){
4038                 // Put in list
4039                 file_announcements.push_back(
4040                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4041         }
4042
4043         // Make packet
4044         std::ostringstream os(std::ios_base::binary);
4045
4046         /*
4047                 u16 command
4048                 u32 number of files
4049                 for each texture {
4050                         u16 length of name
4051                         string name
4052                         u16 length of sha1_digest
4053                         string sha1_digest
4054                 }
4055         */
4056
4057         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4058         writeU16(os, file_announcements.size());
4059
4060         for(std::list<SendableMediaAnnouncement>::iterator
4061                         j = file_announcements.begin();
4062                         j != file_announcements.end(); ++j){
4063                 os<<serializeString(j->name);
4064                 os<<serializeString(j->sha1_digest);
4065         }
4066         os<<serializeString(g_settings->get("remote_media"));
4067
4068         // Make data buffer
4069         std::string s = os.str();
4070         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4071
4072         // Send as reliable
4073         m_clients.send(peer_id, 0, data, true);
4074 }
4075
4076 struct SendableMedia
4077 {
4078         std::string name;
4079         std::string path;
4080         std::string data;
4081
4082         SendableMedia(const std::string &name_="", const std::string &path_="",
4083                       const std::string &data_=""):
4084                 name(name_),
4085                 path(path_),
4086                 data(data_)
4087         {}
4088 };
4089
4090 void Server::sendRequestedMedia(u16 peer_id,
4091                 const std::list<std::string> &tosend)
4092 {
4093         DSTACK(__FUNCTION_NAME);
4094
4095         verbosestream<<"Server::sendRequestedMedia(): "
4096                         <<"Sending files to client"<<std::endl;
4097
4098         /* Read files */
4099
4100         // Put 5kB in one bunch (this is not accurate)
4101         u32 bytes_per_bunch = 5000;
4102
4103         std::vector< std::list<SendableMedia> > file_bunches;
4104         file_bunches.push_back(std::list<SendableMedia>());
4105
4106         u32 file_size_bunch_total = 0;
4107
4108         for(std::list<std::string>::const_iterator i = tosend.begin();
4109                         i != tosend.end(); ++i)
4110         {
4111                 const std::string &name = *i;
4112
4113                 if(m_media.find(name) == m_media.end()){
4114                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4115                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
4116                         continue;
4117                 }
4118
4119                 //TODO get path + name
4120                 std::string tpath = m_media[name].path;
4121
4122                 // Read data
4123                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4124                 if(fis.good() == false){
4125                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4126                                         <<tpath<<"\" for reading"<<std::endl;
4127                         continue;
4128                 }
4129                 std::ostringstream tmp_os(std::ios_base::binary);
4130                 bool bad = false;
4131                 for(;;){
4132                         char buf[1024];
4133                         fis.read(buf, 1024);
4134                         std::streamsize len = fis.gcount();
4135                         tmp_os.write(buf, len);
4136                         file_size_bunch_total += len;
4137                         if(fis.eof())
4138                                 break;
4139                         if(!fis.good()){
4140                                 bad = true;
4141                                 break;
4142                         }
4143                 }
4144                 if(bad){
4145                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4146                                         <<name<<"\""<<std::endl;
4147                         continue;
4148                 }
4149                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4150                                 <<tname<<"\""<<std::endl;*/
4151                 // Put in list
4152                 file_bunches[file_bunches.size()-1].push_back(
4153                                 SendableMedia(name, tpath, tmp_os.str()));
4154
4155                 // Start next bunch if got enough data
4156                 if(file_size_bunch_total >= bytes_per_bunch){
4157                         file_bunches.push_back(std::list<SendableMedia>());
4158                         file_size_bunch_total = 0;
4159                 }
4160
4161         }
4162
4163         /* Create and send packets */
4164
4165         u32 num_bunches = file_bunches.size();
4166         for(u32 i=0; i<num_bunches; i++)
4167         {
4168                 std::ostringstream os(std::ios_base::binary);
4169
4170                 /*
4171                         u16 command
4172                         u16 total number of texture bunches
4173                         u16 index of this bunch
4174                         u32 number of files in this bunch
4175                         for each file {
4176                                 u16 length of name
4177                                 string name
4178                                 u32 length of data
4179                                 data
4180                         }
4181                 */
4182
4183                 writeU16(os, TOCLIENT_MEDIA);
4184                 writeU16(os, num_bunches);
4185                 writeU16(os, i);
4186                 writeU32(os, file_bunches[i].size());
4187
4188                 for(std::list<SendableMedia>::iterator
4189                                 j = file_bunches[i].begin();
4190                                 j != file_bunches[i].end(); ++j){
4191                         os<<serializeString(j->name);
4192                         os<<serializeLongString(j->data);
4193                 }
4194
4195                 // Make data buffer
4196                 std::string s = os.str();
4197                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4198                                 <<i<<"/"<<num_bunches
4199                                 <<" files="<<file_bunches[i].size()
4200                                 <<" size=" <<s.size()<<std::endl;
4201                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4202                 // Send as reliable
4203                 m_clients.send(peer_id, 2, data, true);
4204         }
4205 }
4206
4207 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4208 {
4209         if(m_detached_inventories.count(name) == 0){
4210                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4211                 return;
4212         }
4213         Inventory *inv = m_detached_inventories[name];
4214
4215         std::ostringstream os(std::ios_base::binary);
4216         writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4217         os<<serializeString(name);
4218         inv->serialize(os);
4219
4220         // Make data buffer
4221         std::string s = os.str();
4222         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4223
4224         if (peer_id != PEER_ID_INEXISTENT)
4225         {
4226                 // Send as reliable
4227                 m_clients.send(peer_id, 0, data, true);
4228         }
4229         else
4230         {
4231                 m_clients.sendToAll(0,data,true);
4232         }
4233 }
4234
4235 void Server::sendDetachedInventories(u16 peer_id)
4236 {
4237         DSTACK(__FUNCTION_NAME);
4238
4239         for(std::map<std::string, Inventory*>::iterator
4240                         i = m_detached_inventories.begin();
4241                         i != m_detached_inventories.end(); i++){
4242                 const std::string &name = i->first;
4243                 //Inventory *inv = i->second;
4244                 sendDetachedInventory(name, peer_id);
4245         }
4246 }
4247
4248 /*
4249         Something random
4250 */
4251
4252 void Server::DiePlayer(u16 peer_id)
4253 {
4254         DSTACK(__FUNCTION_NAME);
4255
4256         PlayerSAO *playersao = getPlayerSAO(peer_id);
4257         assert(playersao);
4258
4259         infostream<<"Server::DiePlayer(): Player "
4260                         <<playersao->getPlayer()->getName()
4261                         <<" dies"<<std::endl;
4262
4263         playersao->setHP(0);
4264
4265         // Trigger scripted stuff
4266         m_script->on_dieplayer(playersao);
4267
4268         SendPlayerHP(peer_id);
4269         SendDeathscreen(peer_id, false, v3f(0,0,0));
4270 }
4271
4272 void Server::RespawnPlayer(u16 peer_id)
4273 {
4274         DSTACK(__FUNCTION_NAME);
4275
4276         PlayerSAO *playersao = getPlayerSAO(peer_id);
4277         assert(playersao);
4278
4279         infostream<<"Server::RespawnPlayer(): Player "
4280                         <<playersao->getPlayer()->getName()
4281                         <<" respawns"<<std::endl;
4282
4283         playersao->setHP(PLAYER_MAX_HP);
4284
4285         bool repositioned = m_script->on_respawnplayer(playersao);
4286         if(!repositioned){
4287                 v3f pos = findSpawnPos(m_env->getServerMap());
4288                 playersao->setPos(pos);
4289         }
4290 }
4291
4292 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
4293 {
4294         DSTACK(__FUNCTION_NAME);
4295
4296         SendAccessDenied(peer_id, reason);
4297         m_clients.event(peer_id,SetDenied);
4298         m_con.DisconnectPeer(peer_id);
4299 }
4300
4301 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
4302 {
4303         DSTACK(__FUNCTION_NAME);
4304         std::wstring message;
4305         {
4306                 /*
4307                         Clear references to playing sounds
4308                 */
4309                 for(std::map<s32, ServerPlayingSound>::iterator
4310                                 i = m_playing_sounds.begin();
4311                                 i != m_playing_sounds.end();)
4312                 {
4313                         ServerPlayingSound &psound = i->second;
4314                         psound.clients.erase(peer_id);
4315                         if(psound.clients.size() == 0)
4316                                 m_playing_sounds.erase(i++);
4317                         else
4318                                 i++;
4319                 }
4320
4321                 Player *player = m_env->getPlayer(peer_id);
4322
4323                 // Collect information about leaving in chat
4324                 {
4325                         if(player != NULL && reason != CDR_DENY)
4326                         {
4327                                 std::wstring name = narrow_to_wide(player->getName());
4328                                 message += L"*** ";
4329                                 message += name;
4330                                 message += L" left the game.";
4331                                 if(reason == CDR_TIMEOUT)
4332                                         message += L" (timed out)";
4333                         }
4334                 }
4335
4336                 /* Run scripts and remove from environment */
4337                 {
4338                         if(player != NULL)
4339                         {
4340                                 PlayerSAO *playersao = player->getPlayerSAO();
4341                                 assert(playersao);
4342
4343                                 m_script->on_leaveplayer(playersao);
4344
4345                                 playersao->disconnected();
4346                         }
4347                 }
4348
4349                 /*
4350                         Print out action
4351                 */
4352                 {
4353                         if(player != NULL && reason != CDR_DENY)
4354                         {
4355                                 std::ostringstream os(std::ios_base::binary);
4356                                 std::list<u16> clients = m_clients.getClientIDs();
4357
4358                                 for(std::list<u16>::iterator
4359                                         i = clients.begin();
4360                                         i != clients.end(); ++i)
4361                                 {
4362                                         // Get player
4363                                         Player *player = m_env->getPlayer(*i);
4364                                         if(!player)
4365                                                 continue;
4366                                         // Get name of player
4367                                         os<<player->getName()<<" ";
4368                                 }
4369
4370                                 actionstream<<player->getName()<<" "
4371                                                 <<(reason==CDR_TIMEOUT?"times out.":"leaves game.")
4372                                                 <<" List of players: "<<os.str()<<std::endl;
4373                         }
4374                 }
4375                 {
4376                         JMutexAutoLock env_lock(m_env_mutex);
4377                         m_clients.DeleteClient(peer_id);
4378                 }
4379         }
4380
4381         // Send leave chat message to all remaining clients
4382         if(message.length() != 0)
4383                 SendChatMessage(PEER_ID_INEXISTENT,message);
4384 }
4385
4386 void Server::UpdateCrafting(u16 peer_id)
4387 {
4388         DSTACK(__FUNCTION_NAME);
4389
4390         Player* player = m_env->getPlayer(peer_id);
4391         assert(player);
4392
4393         // Get a preview for crafting
4394         ItemStack preview;
4395         InventoryLocation loc;
4396         loc.setPlayer(player->getName());
4397         getCraftingResult(&player->inventory, preview, false, this);
4398         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
4399
4400         // Put the new preview in
4401         InventoryList *plist = player->inventory.getList("craftpreview");
4402         assert(plist);
4403         assert(plist->getSize() >= 1);
4404         plist->changeItem(0, preview);
4405 }
4406
4407 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
4408 {
4409         RemoteClient *client = getClientNoEx(peer_id,state_min);
4410         if(!client)
4411                 throw ClientNotFoundException("Client not found");
4412
4413         return client;
4414 }
4415 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
4416 {
4417         return m_clients.getClientNoEx(peer_id, state_min);
4418 }
4419
4420 std::string Server::getPlayerName(u16 peer_id)
4421 {
4422         Player *player = m_env->getPlayer(peer_id);
4423         if(player == NULL)
4424                 return "[id="+itos(peer_id)+"]";
4425         return player->getName();
4426 }
4427
4428 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
4429 {
4430         Player *player = m_env->getPlayer(peer_id);
4431         if(player == NULL)
4432                 return NULL;
4433         return player->getPlayerSAO();
4434 }
4435
4436 std::wstring Server::getStatusString()
4437 {
4438         std::wostringstream os(std::ios_base::binary);
4439         os<<L"# Server: ";
4440         // Version
4441         os<<L"version="<<narrow_to_wide(minetest_version_simple);
4442         // Uptime
4443         os<<L", uptime="<<m_uptime.get();
4444         // Max lag estimate
4445         os<<L", max_lag="<<m_env->getMaxLagEstimate();
4446         // Information about clients
4447         bool first = true;
4448         os<<L", clients={";
4449         std::list<u16> clients = m_clients.getClientIDs();
4450         for(std::list<u16>::iterator i = clients.begin();
4451                 i != clients.end(); ++i)
4452         {
4453                 // Get player
4454                 Player *player = m_env->getPlayer(*i);
4455                 // Get name of player
4456                 std::wstring name = L"unknown";
4457                 if(player != NULL)
4458                         name = narrow_to_wide(player->getName());
4459                 // Add name to information string
4460                 if(!first)
4461                         os<<L",";
4462                 else
4463                         first = false;
4464                 os<<name;
4465         }
4466         os<<L"}";
4467         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4468                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4469         if(g_settings->get("motd") != "")
4470                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4471         return os.str();
4472 }
4473
4474 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4475 {
4476         std::set<std::string> privs;
4477         m_script->getAuth(name, NULL, &privs);
4478         return privs;
4479 }
4480
4481 bool Server::checkPriv(const std::string &name, const std::string &priv)
4482 {
4483         std::set<std::string> privs = getPlayerEffectivePrivs(name);
4484         return (privs.count(priv) != 0);
4485 }
4486
4487 void Server::reportPrivsModified(const std::string &name)
4488 {
4489         if(name == ""){
4490                 std::list<u16> clients = m_clients.getClientIDs();
4491                 for(std::list<u16>::iterator
4492                                 i = clients.begin();
4493                                 i != clients.end(); ++i){
4494                         Player *player = m_env->getPlayer(*i);
4495                         reportPrivsModified(player->getName());
4496                 }
4497         } else {
4498                 Player *player = m_env->getPlayer(name.c_str());
4499                 if(!player)
4500                         return;
4501                 SendPlayerPrivileges(player->peer_id);
4502                 PlayerSAO *sao = player->getPlayerSAO();
4503                 if(!sao)
4504                         return;
4505                 sao->updatePrivileges(
4506                                 getPlayerEffectivePrivs(name),
4507                                 isSingleplayer());
4508         }
4509 }
4510
4511 void Server::reportInventoryFormspecModified(const std::string &name)
4512 {
4513         Player *player = m_env->getPlayer(name.c_str());
4514         if(!player)
4515                 return;
4516         SendPlayerInventoryFormspec(player->peer_id);
4517 }
4518
4519 void Server::setIpBanned(const std::string &ip, const std::string &name)
4520 {
4521         m_banmanager->add(ip, name);
4522 }
4523
4524 void Server::unsetIpBanned(const std::string &ip_or_name)
4525 {
4526         m_banmanager->remove(ip_or_name);
4527 }
4528
4529 std::string Server::getBanDescription(const std::string &ip_or_name)
4530 {
4531         return m_banmanager->getBanDescription(ip_or_name);
4532 }
4533
4534 void Server::notifyPlayer(const char *name, const std::wstring &msg)
4535 {
4536         Player *player = m_env->getPlayer(name);
4537         if(!player)
4538                 return;
4539
4540         if (player->peer_id == PEER_ID_INEXISTENT)
4541                 return;
4542
4543         SendChatMessage(player->peer_id, msg);
4544 }
4545
4546 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4547 {
4548         Player *player = m_env->getPlayer(playername);
4549
4550         if(!player)
4551         {
4552                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4553                 return false;
4554         }
4555
4556         SendShowFormspecMessage(player->peer_id, formspec, formname);
4557         return true;
4558 }
4559
4560 u32 Server::hudAdd(Player *player, HudElement *form) {
4561         if (!player)
4562                 return -1;
4563
4564         u32 id = player->getFreeHudID();
4565         if (id < player->hud.size())
4566                 player->hud[id] = form;
4567         else
4568                 player->hud.push_back(form);
4569         
4570         SendHUDAdd(player->peer_id, id, form);
4571         return id;
4572 }
4573
4574 bool Server::hudRemove(Player *player, u32 id) {
4575         if (!player || id >= player->hud.size() || !player->hud[id])
4576                 return false;
4577
4578         delete player->hud[id];
4579         player->hud[id] = NULL;
4580         
4581         SendHUDRemove(player->peer_id, id);
4582         return true;
4583 }
4584
4585 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
4586         if (!player)
4587                 return false;
4588
4589         SendHUDChange(player->peer_id, id, stat, data);
4590         return true;
4591 }
4592
4593 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
4594         if (!player)
4595                 return false;
4596
4597         SendHUDSetFlags(player->peer_id, flags, mask);
4598
4599         m_script->player_event(player->getPlayerSAO(),"hud_changed");
4600         return true;
4601 }
4602
4603 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
4604         if (!player)
4605                 return false;
4606         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
4607                 return false;
4608
4609         std::ostringstream os(std::ios::binary);
4610         writeS32(os, hotbar_itemcount);
4611         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
4612         return true;
4613 }
4614
4615 void Server::hudSetHotbarImage(Player *player, std::string name) {
4616         if (!player)
4617                 return;
4618
4619         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
4620 }
4621
4622 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
4623         if (!player)
4624                 return;
4625
4626         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
4627 }
4628
4629 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
4630 {
4631         if (!player)
4632                 return false;
4633
4634         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
4635         return true;
4636 }
4637
4638 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
4639 {
4640         if (!player)
4641                 return false;
4642
4643         SendEyeOffset(player->peer_id, first, third);
4644         return true;
4645 }
4646
4647 bool Server::setSky(Player *player, const video::SColor &bgcolor,
4648                 const std::string &type, const std::vector<std::string> &params)
4649 {
4650         if (!player)
4651                 return false;
4652
4653         SendSetSky(player->peer_id, bgcolor, type, params);
4654         return true;
4655 }
4656
4657 bool Server::overrideDayNightRatio(Player *player, bool do_override,
4658                 float ratio)
4659 {
4660         if (!player)
4661                 return false;
4662
4663         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
4664         return true;
4665 }
4666
4667 void Server::notifyPlayers(const std::wstring &msg)
4668 {
4669         SendChatMessage(PEER_ID_INEXISTENT,msg);
4670 }
4671
4672 void Server::spawnParticle(const char *playername, v3f pos,
4673                 v3f velocity, v3f acceleration,
4674                 float expirationtime, float size, bool
4675                 collisiondetection, bool vertical, std::string texture)
4676 {
4677         Player *player = m_env->getPlayer(playername);
4678         if(!player)
4679                 return;
4680         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
4681                         expirationtime, size, collisiondetection, vertical, texture);
4682 }
4683
4684 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
4685                 float expirationtime, float size,
4686                 bool collisiondetection, bool vertical, std::string texture)
4687 {
4688         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
4689                         expirationtime, size, collisiondetection, vertical, texture);
4690 }
4691
4692 u32 Server::addParticleSpawner(const char *playername,
4693                 u16 amount, float spawntime,
4694                 v3f minpos, v3f maxpos,
4695                 v3f minvel, v3f maxvel,
4696                 v3f minacc, v3f maxacc,
4697                 float minexptime, float maxexptime,
4698                 float minsize, float maxsize,
4699                 bool collisiondetection, bool vertical, std::string texture)
4700 {
4701         Player *player = m_env->getPlayer(playername);
4702         if(!player)
4703                 return -1;
4704
4705         u32 id = 0;
4706         for(;;) // look for unused particlespawner id
4707         {
4708                 id++;
4709                 if (std::find(m_particlespawner_ids.begin(),
4710                                 m_particlespawner_ids.end(), id)
4711                                 == m_particlespawner_ids.end())
4712                 {
4713                         m_particlespawner_ids.push_back(id);
4714                         break;
4715                 }
4716         }
4717
4718         SendAddParticleSpawner(player->peer_id, amount, spawntime,
4719                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4720                 minexptime, maxexptime, minsize, maxsize,
4721                 collisiondetection, vertical, texture, id);
4722
4723         return id;
4724 }
4725
4726 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
4727                 v3f minpos, v3f maxpos,
4728                 v3f minvel, v3f maxvel,
4729                 v3f minacc, v3f maxacc,
4730                 float minexptime, float maxexptime,
4731                 float minsize, float maxsize,
4732                 bool collisiondetection, bool vertical, std::string texture)
4733 {
4734         u32 id = 0;
4735         for(;;) // look for unused particlespawner id
4736         {
4737                 id++;
4738                 if (std::find(m_particlespawner_ids.begin(),
4739                                 m_particlespawner_ids.end(), id)
4740                                 == m_particlespawner_ids.end())
4741                 {
4742                         m_particlespawner_ids.push_back(id);
4743                         break;
4744                 }
4745         }
4746
4747         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
4748                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4749                 minexptime, maxexptime, minsize, maxsize,
4750                 collisiondetection, vertical, texture, id);
4751
4752         return id;
4753 }
4754
4755 void Server::deleteParticleSpawner(const char *playername, u32 id)
4756 {
4757         Player *player = m_env->getPlayer(playername);
4758         if(!player)
4759                 return;
4760
4761         m_particlespawner_ids.erase(
4762                         std::remove(m_particlespawner_ids.begin(),
4763                         m_particlespawner_ids.end(), id),
4764                         m_particlespawner_ids.end());
4765         SendDeleteParticleSpawner(player->peer_id, id);
4766 }
4767
4768 void Server::deleteParticleSpawnerAll(u32 id)
4769 {
4770         m_particlespawner_ids.erase(
4771                         std::remove(m_particlespawner_ids.begin(),
4772                         m_particlespawner_ids.end(), id),
4773                         m_particlespawner_ids.end());
4774         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
4775 }
4776
4777 Inventory* Server::createDetachedInventory(const std::string &name)
4778 {
4779         if(m_detached_inventories.count(name) > 0){
4780                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
4781                 delete m_detached_inventories[name];
4782         } else {
4783                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
4784         }
4785         Inventory *inv = new Inventory(m_itemdef);
4786         assert(inv);
4787         m_detached_inventories[name] = inv;
4788         //TODO find a better way to do this
4789         sendDetachedInventory(name,PEER_ID_INEXISTENT);
4790         return inv;
4791 }
4792
4793 class BoolScopeSet
4794 {
4795 public:
4796         BoolScopeSet(bool *dst, bool val):
4797                 m_dst(dst)
4798         {
4799                 m_orig_state = *m_dst;
4800                 *m_dst = val;
4801         }
4802         ~BoolScopeSet()
4803         {
4804                 *m_dst = m_orig_state;
4805         }
4806 private:
4807         bool *m_dst;
4808         bool m_orig_state;
4809 };
4810
4811 // actions: time-reversed list
4812 // Return value: success/failure
4813 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
4814                 std::list<std::string> *log)
4815 {
4816         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
4817         ServerMap *map = (ServerMap*)(&m_env->getMap());
4818         // Disable rollback report sink while reverting
4819         BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
4820
4821         // Fail if no actions to handle
4822         if(actions.empty()){
4823                 log->push_back("Nothing to do.");
4824                 return false;
4825         }
4826
4827         int num_tried = 0;
4828         int num_failed = 0;
4829
4830         for(std::list<RollbackAction>::const_iterator
4831                         i = actions.begin();
4832                         i != actions.end(); i++)
4833         {
4834                 const RollbackAction &action = *i;
4835                 num_tried++;
4836                 bool success = action.applyRevert(map, this, this);
4837                 if(!success){
4838                         num_failed++;
4839                         std::ostringstream os;
4840                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
4841                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4842                         if(log)
4843                                 log->push_back(os.str());
4844                 }else{
4845                         std::ostringstream os;
4846                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
4847                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4848                         if(log)
4849                                 log->push_back(os.str());
4850                 }
4851         }
4852
4853         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
4854                         <<" failed"<<std::endl;
4855
4856         // Call it done if less than half failed
4857         return num_failed <= num_tried/2;
4858 }
4859
4860 // IGameDef interface
4861 // Under envlock
4862 IItemDefManager* Server::getItemDefManager()
4863 {
4864         return m_itemdef;
4865 }
4866 INodeDefManager* Server::getNodeDefManager()
4867 {
4868         return m_nodedef;
4869 }
4870 ICraftDefManager* Server::getCraftDefManager()
4871 {
4872         return m_craftdef;
4873 }
4874 ITextureSource* Server::getTextureSource()
4875 {
4876         return NULL;
4877 }
4878 IShaderSource* Server::getShaderSource()
4879 {
4880         return NULL;
4881 }
4882 u16 Server::allocateUnknownNodeId(const std::string &name)
4883 {
4884         return m_nodedef->allocateDummy(name);
4885 }
4886 ISoundManager* Server::getSoundManager()
4887 {
4888         return &dummySoundManager;
4889 }
4890 MtEventManager* Server::getEventManager()
4891 {
4892         return m_event;
4893 }
4894 IRollbackReportSink* Server::getRollbackReportSink()
4895 {
4896         if(!m_enable_rollback_recording)
4897                 return NULL;
4898         if(!m_rollback_sink_enabled)
4899                 return NULL;
4900         return m_rollback;
4901 }
4902
4903 IWritableItemDefManager* Server::getWritableItemDefManager()
4904 {
4905         return m_itemdef;
4906 }
4907 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4908 {
4909         return m_nodedef;
4910 }
4911 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4912 {
4913         return m_craftdef;
4914 }
4915
4916 const ModSpec* Server::getModSpec(const std::string &modname)
4917 {
4918         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4919                         i != m_mods.end(); i++){
4920                 const ModSpec &mod = *i;
4921                 if(mod.name == modname)
4922                         return &mod;
4923         }
4924         return NULL;
4925 }
4926 void Server::getModNames(std::list<std::string> &modlist)
4927 {
4928         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
4929         {
4930                 modlist.push_back(i->name);
4931         }
4932 }
4933 std::string Server::getBuiltinLuaPath()
4934 {
4935         return porting::path_share + DIR_DELIM + "builtin";
4936 }
4937
4938 v3f findSpawnPos(ServerMap &map)
4939 {
4940         //return v3f(50,50,50)*BS;
4941
4942         v3s16 nodepos;
4943
4944 #if 0
4945         nodepos = v2s16(0,0);
4946         groundheight = 20;
4947 #endif
4948
4949 #if 1
4950         s16 water_level = map.getWaterLevel();
4951
4952         // Try to find a good place a few times
4953         for(s32 i=0; i<1000; i++)
4954         {
4955                 s32 range = 1 + i;
4956                 // We're going to try to throw the player to this position
4957                 v2s16 nodepos2d = v2s16(
4958                                 -range + (myrand() % (range * 2)),
4959                                 -range + (myrand() % (range * 2)));
4960
4961                 // Get ground height at point
4962                 s16 groundheight = map.findGroundLevel(nodepos2d);
4963                 if (groundheight <= water_level) // Don't go underwater
4964                         continue;
4965                 if (groundheight > water_level + 6) // Don't go to high places
4966                         continue;
4967
4968                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
4969                 bool is_good = false;
4970                 s32 air_count = 0;
4971                 for (s32 i = 0; i < 10; i++) {
4972                         v3s16 blockpos = getNodeBlockPos(nodepos);
4973                         map.emergeBlock(blockpos, true);
4974                         content_t c = map.getNodeNoEx(nodepos).getContent();
4975                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
4976                                 air_count++;
4977                                 if (air_count >= 2){
4978                                         is_good = true;
4979                                         break;
4980                                 }
4981                         }
4982                         nodepos.Y++;
4983                 }
4984                 if(is_good){
4985                         // Found a good place
4986                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4987                         break;
4988                 }
4989         }
4990 #endif
4991
4992         return intToFloat(nodepos, BS);
4993 }
4994
4995 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
4996 {
4997         RemotePlayer *player = NULL;
4998         bool newplayer = false;
4999
5000         /*
5001                 Try to get an existing player
5002         */
5003         player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
5004
5005         // If player is already connected, cancel
5006         if(player != NULL && player->peer_id != 0)
5007         {
5008                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
5009                 return NULL;
5010         }
5011
5012         /*
5013                 If player with the wanted peer_id already exists, cancel.
5014         */
5015         if(m_env->getPlayer(peer_id) != NULL)
5016         {
5017                 infostream<<"emergePlayer(): Player with wrong name but same"
5018                                 " peer_id already exists"<<std::endl;
5019                 return NULL;
5020         }
5021
5022         /*
5023                 Create a new player if it doesn't exist yet
5024         */
5025         if(player == NULL)
5026         {
5027                 newplayer = true;
5028                 player = new RemotePlayer(this);
5029                 player->updateName(name);
5030
5031                 /* Set player position */
5032                 infostream<<"Server: Finding spawn place for player \""
5033                                 <<name<<"\""<<std::endl;
5034                 v3f pos = findSpawnPos(m_env->getServerMap());
5035                 player->setPosition(pos);
5036
5037                 /* Add player to environment */
5038                 m_env->addPlayer(player);
5039         }
5040
5041         /*
5042                 Create a new player active object
5043         */
5044         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5045                         getPlayerEffectivePrivs(player->getName()),
5046                         isSingleplayer());
5047
5048         /* Clean up old HUD elements from previous sessions */
5049         player->hud.clear();
5050
5051         /* Add object to environment */
5052         m_env->addActiveObject(playersao);
5053
5054         /* Run scripts */
5055         if(newplayer)
5056                 m_script->on_newplayer(playersao);
5057
5058         return playersao;
5059 }
5060
5061 void dedicated_server_loop(Server &server, bool &kill)
5062 {
5063         DSTACK(__FUNCTION_NAME);
5064
5065         verbosestream<<"dedicated_server_loop()"<<std::endl;
5066
5067         IntervalLimiter m_profiler_interval;
5068
5069         for(;;)
5070         {
5071                 float steplen = g_settings->getFloat("dedicated_server_step");
5072                 // This is kind of a hack but can be done like this
5073                 // because server.step() is very light
5074                 {
5075                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
5076                         sleep_ms((int)(steplen*1000.0));
5077                 }
5078                 server.step(steplen);
5079
5080                 if(server.getShutdownRequested() || kill)
5081                 {
5082                         infostream<<"Dedicated server quitting"<<std::endl;
5083 #if USE_CURL
5084                         if(g_settings->getBool("server_announce") == true)
5085                                 ServerList::sendAnnounce("delete");
5086 #endif
5087                         break;
5088                 }
5089
5090                 /*
5091                         Profiler
5092                 */
5093                 float profiler_print_interval =
5094                                 g_settings->getFloat("profiler_print_interval");
5095                 if(profiler_print_interval != 0)
5096                 {
5097                         if(m_profiler_interval.step(steplen, profiler_print_interval))
5098                         {
5099                                 infostream<<"Profiler:"<<std::endl;
5100                                 g_profiler->print(infostream);
5101                                 g_profiler->clear();
5102                         }
5103                 }
5104         }
5105 }
5106
5107