7c4c48c48f352dacf8de98cb78033dfc15867d73
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest
3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include "server.h"
21 #include <iostream>
22 #include <queue>
23 #include <algorithm>
24 #include "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         // Lock environment
298         JMutexAutoLock envlock(m_env_mutex);
299
300         // Initialize scripting
301         infostream<<"Server: Initializing Lua"<<std::endl;
302
303         m_script = new GameScripting(this);
304
305         std::string scriptpath = getBuiltinLuaPath() + DIR_DELIM "init.lua";
306
307         if (!m_script->loadScript(scriptpath)) {
308                 throw ModError("Failed to load and run " + scriptpath);
309         }
310
311
312         // Print 'em
313         infostream<<"Server: Loading mods: ";
314         for(std::vector<ModSpec>::iterator i = m_mods.begin();
315                         i != m_mods.end(); i++){
316                 const ModSpec &mod = *i;
317                 infostream<<mod.name<<" ";
318         }
319         infostream<<std::endl;
320         // Load and run "mod" scripts
321         for(std::vector<ModSpec>::iterator i = m_mods.begin();
322                         i != m_mods.end(); i++){
323                 const ModSpec &mod = *i;
324                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
325                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
326                                 <<scriptpath<<"\"]"<<std::endl;
327                 bool success = m_script->loadMod(scriptpath, mod.name);
328                 if(!success){
329                         errorstream<<"Server: Failed to load and run "
330                                         <<scriptpath<<std::endl;
331                         throw ModError("Failed to load and run "+scriptpath);
332                 }
333         }
334
335         // Read Textures and calculate sha1 sums
336         fillMediaCache();
337
338         // Apply item aliases in the node definition manager
339         m_nodedef->updateAliases(m_itemdef);
340
341         // Load the mapgen params from global settings now after any
342         // initial overrides have been set by the mods
343         m_emerge->loadMapgenParams();
344
345         // Initialize Environment
346         ServerMap *servermap = new ServerMap(path_world, this, m_emerge);
347         m_env = new ServerEnvironment(servermap, m_script, this);
348
349         m_clients.setEnv(m_env);
350
351         // Run some callbacks after the MG params have been set up but before activation
352         m_script->environment_OnMapgenInit(&m_emerge->params);
353
354         // Initialize mapgens
355         m_emerge->initMapgens();
356
357         // Give environment reference to scripting api
358         m_script->initializeEnvironment(m_env);
359
360         // Register us to receive map edit events
361         servermap->addEventReceiver(this);
362
363         // If file exists, load environment metadata
364         if(fs::PathExists(m_path_world+DIR_DELIM+"env_meta.txt"))
365         {
366                 infostream<<"Server: Loading environment metadata"<<std::endl;
367                 m_env->loadMeta(m_path_world);
368         }
369
370         // Load players
371         infostream<<"Server: Loading players"<<std::endl;
372         m_env->deSerializePlayers(m_path_world);
373
374         /*
375                 Add some test ActiveBlockModifiers to environment
376         */
377         add_legacy_abms(m_env, m_nodedef);
378
379         m_liquid_transform_every = g_settings->getFloat("liquid_update");
380 }
381
382 Server::~Server()
383 {
384         infostream<<"Server destructing"<<std::endl;
385
386         /*
387                 Send shutdown message
388         */
389         {
390                 std::wstring line = L"*** Server shutting down";
391                 SendChatMessage(PEER_ID_INEXISTENT, line);
392         }
393
394         {
395                 JMutexAutoLock envlock(m_env_mutex);
396
397                 /*
398                         Execute script shutdown hooks
399                 */
400                 m_script->on_shutdown();
401         }
402
403         {
404                 JMutexAutoLock envlock(m_env_mutex);
405
406                 /*
407                         Save players
408                 */
409                 infostream<<"Server: Saving players"<<std::endl;
410                 m_env->serializePlayers(m_path_world);
411
412                 /*
413                         Save environment metadata
414                 */
415                 infostream<<"Server: Saving environment metadata"<<std::endl;
416                 m_env->saveMeta(m_path_world);
417         }
418
419         /*
420                 Stop threads
421         */
422         stop();
423         delete m_thread;
424
425         // stop all emerge threads before deleting players that may have
426         // requested blocks to be emerged
427         m_emerge->stopThreads();
428
429         // Delete things in the reverse order of creation
430         delete m_env;
431
432         // N.B. the EmergeManager should be deleted after the Environment since Map
433         // depends on EmergeManager to write its current params to the map meta
434         delete m_emerge;
435         delete m_rollback;
436         delete m_banmanager;
437         delete m_event;
438         delete m_itemdef;
439         delete m_nodedef;
440         delete m_craftdef;
441
442         // Deinitialize scripting
443         infostream<<"Server: Deinitializing scripting"<<std::endl;
444         delete m_script;
445
446         // Delete detached inventories
447         {
448                 for(std::map<std::string, Inventory*>::iterator
449                                 i = m_detached_inventories.begin();
450                                 i != m_detached_inventories.end(); i++){
451                         delete i->second;
452                 }
453         }
454 }
455
456 void Server::start(Address bind_addr)
457 {
458         DSTACK(__FUNCTION_NAME);
459         infostream<<"Starting server on "
460                         << bind_addr.serializeString() <<"..."<<std::endl;
461
462         // Stop thread if already running
463         m_thread->Stop();
464
465         // Initialize connection
466         m_con.SetTimeoutMs(30);
467         m_con.Serve(bind_addr);
468
469         // Start thread
470         m_thread->Start();
471
472         // ASCII art for the win!
473         actionstream
474         <<"        .__               __                   __   "<<std::endl
475         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
476         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
477         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
478         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
479         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
480         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
481         actionstream<<"Server for gameid=\""<<m_gamespec.id
482                         <<"\" listening on "<<bind_addr.serializeString()<<":"
483                         <<bind_addr.getPort() << "."<<std::endl;
484 }
485
486 void Server::stop()
487 {
488         DSTACK(__FUNCTION_NAME);
489
490         infostream<<"Server: Stopping and waiting threads"<<std::endl;
491
492         // Stop threads (set run=false first so both start stopping)
493         m_thread->Stop();
494         //m_emergethread.setRun(false);
495         m_thread->Wait();
496         //m_emergethread.stop();
497
498         infostream<<"Server: Threads stopped"<<std::endl;
499 }
500
501 void Server::step(float dtime)
502 {
503         DSTACK(__FUNCTION_NAME);
504         // Limit a bit
505         if(dtime > 2.0)
506                 dtime = 2.0;
507         {
508                 JMutexAutoLock lock(m_step_dtime_mutex);
509                 m_step_dtime += dtime;
510         }
511         // Throw if fatal error occurred in thread
512         std::string async_err = m_async_fatal_error.get();
513         if(async_err != ""){
514                 throw ServerError(async_err);
515         }
516 }
517
518 void Server::AsyncRunStep(bool initial_step)
519 {
520         DSTACK(__FUNCTION_NAME);
521
522         g_profiler->add("Server::AsyncRunStep (num)", 1);
523
524         float dtime;
525         {
526                 JMutexAutoLock lock1(m_step_dtime_mutex);
527                 dtime = m_step_dtime;
528         }
529
530         {
531                 // Send blocks to clients
532                 SendBlocks(dtime);
533         }
534
535         if((dtime < 0.001) && (initial_step == false))
536                 return;
537
538         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
539
540         //infostream<<"Server steps "<<dtime<<std::endl;
541         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
542
543         {
544                 JMutexAutoLock lock1(m_step_dtime_mutex);
545                 m_step_dtime -= dtime;
546         }
547
548         /*
549                 Update uptime
550         */
551         {
552                 m_uptime.set(m_uptime.get() + dtime);
553         }
554
555         handlePeerChanges();
556
557         /*
558                 Update time of day and overall game time
559         */
560         {
561                 JMutexAutoLock envlock(m_env_mutex);
562
563                 m_env->setTimeOfDaySpeed(g_settings->getFloat("time_speed"));
564
565                 /*
566                         Send to clients at constant intervals
567                 */
568
569                 m_time_of_day_send_timer -= dtime;
570                 if(m_time_of_day_send_timer < 0.0)
571                 {
572                         m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
573                         u16 time = m_env->getTimeOfDay();
574                         float time_speed = g_settings->getFloat("time_speed");
575                         SendTimeOfDay(PEER_ID_INEXISTENT, time, time_speed);
576                 }
577         }
578
579         {
580                 JMutexAutoLock lock(m_env_mutex);
581                 // Figure out and report maximum lag to environment
582                 float max_lag = m_env->getMaxLagEstimate();
583                 max_lag *= 0.9998; // Decrease slowly (about half per 5 minutes)
584                 if(dtime > max_lag){
585                         if(dtime > 0.1 && dtime > max_lag * 2.0)
586                                 infostream<<"Server: Maximum lag peaked to "<<dtime
587                                                 <<" s"<<std::endl;
588                         max_lag = dtime;
589                 }
590                 m_env->reportMaxLagEstimate(max_lag);
591                 // Step environment
592                 ScopeProfiler sp(g_profiler, "SEnv step");
593                 ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
594                 m_env->step(dtime);
595         }
596
597         const float map_timer_and_unload_dtime = 2.92;
598         if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
599         {
600                 JMutexAutoLock lock(m_env_mutex);
601                 // Run Map's timers and unload unused data
602                 ScopeProfiler sp(g_profiler, "Server: map timer and unload");
603                 m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
604                                 g_settings->getFloat("server_unload_unused_data_timeout"));
605         }
606
607         /*
608                 Do background stuff
609         */
610
611         /*
612                 Handle players
613         */
614         {
615                 JMutexAutoLock lock(m_env_mutex);
616
617                 std::list<u16> clientids = m_clients.getClientIDs();
618
619                 ScopeProfiler sp(g_profiler, "Server: handle players");
620
621                 for(std::list<u16>::iterator
622                         i = clientids.begin();
623                         i != clientids.end(); ++i)
624                 {
625                         PlayerSAO *playersao = getPlayerSAO(*i);
626                         if(playersao == NULL)
627                                 continue;
628
629                         /*
630                                 Handle player HPs (die if hp=0)
631                         */
632                         if(playersao->m_hp_not_sent && g_settings->getBool("enable_damage"))
633                         {
634                                 if(playersao->getHP() == 0)
635                                         DiePlayer(*i);
636                                 else
637                                         SendPlayerHP(*i);
638                         }
639
640                         /*
641                                 Send player breath if changed
642                         */
643                         if(playersao->m_breath_not_sent) {
644                                 SendPlayerBreath(*i);
645                         }
646
647                         /*
648                                 Send player inventories if necessary
649                         */
650                         if(playersao->m_moved){
651                                 SendMovePlayer(*i);
652                                 playersao->m_moved = false;
653                         }
654                         if(playersao->m_inventory_not_sent){
655                                 UpdateCrafting(*i);
656                                 SendInventory(*i);
657                         }
658                 }
659         }
660
661         /* Transform liquids */
662         m_liquid_transform_timer += dtime;
663         if(m_liquid_transform_timer >= m_liquid_transform_every)
664         {
665                 m_liquid_transform_timer -= m_liquid_transform_every;
666
667                 JMutexAutoLock lock(m_env_mutex);
668
669                 ScopeProfiler sp(g_profiler, "Server: liquid transform");
670
671                 std::map<v3s16, MapBlock*> modified_blocks;
672                 m_env->getMap().transformLiquids(modified_blocks);
673 #if 0
674                 /*
675                         Update lighting
676                 */
677                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
678                 ServerMap &map = ((ServerMap&)m_env->getMap());
679                 map.updateLighting(modified_blocks, lighting_modified_blocks);
680
681                 // Add blocks modified by lighting to modified_blocks
682                 for(core::map<v3s16, MapBlock*>::Iterator
683                                 i = lighting_modified_blocks.getIterator();
684                                 i.atEnd() == false; i++)
685                 {
686                         MapBlock *block = i.getNode()->getValue();
687                         modified_blocks.insert(block->getPos(), block);
688                 }
689 #endif
690                 /*
691                         Set the modified blocks unsent for all the clients
692                 */
693                 if(modified_blocks.size() > 0)
694                 {
695                         SetBlocksNotSent(modified_blocks);
696                 }
697         }
698         m_clients.step(dtime);
699
700         m_lag += (m_lag > dtime ? -1 : 1) * dtime/100;
701 #if USE_CURL
702         // send masterserver announce
703         {
704                 float &counter = m_masterserver_timer;
705                 if(!isSingleplayer() && (!counter || counter >= 300.0) &&
706                                 g_settings->getBool("server_announce") == true)
707                 {
708                         ServerList::sendAnnounce(!counter ? "start" : "update",
709                                                                                 m_clients.getPlayerNames(),
710                                                                                 m_uptime.get(),
711                                                                                 m_env->getGameTime(),
712                                                                                 m_lag,
713                                                                                 m_gamespec.id,
714                                                                                 m_mods);
715                         counter = 0.01;
716                 }
717                 counter += dtime;
718         }
719 #endif
720
721         /*
722                 Check added and deleted active objects
723         */
724         {
725                 //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
726                 JMutexAutoLock envlock(m_env_mutex);
727
728                 m_clients.Lock();
729                 std::map<u16, RemoteClient*> clients = m_clients.getClientList();
730                 ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
731
732                 // Radius inside which objects are active
733                 s16 radius = g_settings->getS16("active_object_send_range_blocks");
734                 radius *= MAP_BLOCKSIZE;
735
736                 for(std::map<u16, RemoteClient*>::iterator
737                         i = clients.begin();
738                         i != clients.end(); ++i)
739                 {
740                         RemoteClient *client = i->second;
741
742                         // If definitions and textures have not been sent, don't
743                         // send objects either
744                         if (client->getState() < DefinitionsSent)
745                                 continue;
746
747                         Player *player = m_env->getPlayer(client->peer_id);
748                         if(player==NULL)
749                         {
750                                 // This can happen if the client timeouts somehow
751                                 /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
752                                                 <<client->peer_id
753                                                 <<" has no associated player"<<std::endl;*/
754                                 continue;
755                         }
756                         v3s16 pos = floatToInt(player->getPosition(), BS);
757
758                         std::set<u16> removed_objects;
759                         std::set<u16> added_objects;
760                         m_env->getRemovedActiveObjects(pos, radius,
761                                         client->m_known_objects, removed_objects);
762                         m_env->getAddedActiveObjects(pos, radius,
763                                         client->m_known_objects, added_objects);
764
765                         // Ignore if nothing happened
766                         if(removed_objects.size() == 0 && added_objects.size() == 0)
767                         {
768                                 //infostream<<"active objects: none changed"<<std::endl;
769                                 continue;
770                         }
771
772                         std::string data_buffer;
773
774                         char buf[4];
775
776                         // Handle removed objects
777                         writeU16((u8*)buf, removed_objects.size());
778                         data_buffer.append(buf, 2);
779                         for(std::set<u16>::iterator
780                                         i = removed_objects.begin();
781                                         i != removed_objects.end(); ++i)
782                         {
783                                 // Get object
784                                 u16 id = *i;
785                                 ServerActiveObject* obj = m_env->getActiveObject(id);
786
787                                 // Add to data buffer for sending
788                                 writeU16((u8*)buf, id);
789                                 data_buffer.append(buf, 2);
790
791                                 // Remove from known objects
792                                 client->m_known_objects.erase(id);
793
794                                 if(obj && obj->m_known_by_count > 0)
795                                         obj->m_known_by_count--;
796                         }
797
798                         // Handle added objects
799                         writeU16((u8*)buf, added_objects.size());
800                         data_buffer.append(buf, 2);
801                         for(std::set<u16>::iterator
802                                         i = added_objects.begin();
803                                         i != added_objects.end(); ++i)
804                         {
805                                 // Get object
806                                 u16 id = *i;
807                                 ServerActiveObject* obj = m_env->getActiveObject(id);
808
809                                 // Get object type
810                                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
811                                 if(obj == NULL)
812                                         infostream<<"WARNING: "<<__FUNCTION_NAME
813                                                         <<": NULL object"<<std::endl;
814                                 else
815                                         type = obj->getSendType();
816
817                                 // Add to data buffer for sending
818                                 writeU16((u8*)buf, id);
819                                 data_buffer.append(buf, 2);
820                                 writeU8((u8*)buf, type);
821                                 data_buffer.append(buf, 1);
822
823                                 if(obj)
824                                         data_buffer.append(serializeLongString(
825                                                         obj->getClientInitializationData(client->net_proto_version)));
826                                 else
827                                         data_buffer.append(serializeLongString(""));
828
829                                 // Add to known objects
830                                 client->m_known_objects.insert(id);
831
832                                 if(obj)
833                                         obj->m_known_by_count++;
834                         }
835
836                         // Send packet
837                         SharedBuffer<u8> reply(2 + data_buffer.size());
838                         writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
839                         memcpy((char*)&reply[2], data_buffer.c_str(),
840                                         data_buffer.size());
841                         // Send as reliable
842                         m_clients.send(client->peer_id, 0, reply, true);
843
844                         verbosestream<<"Server: Sent object remove/add: "
845                                         <<removed_objects.size()<<" removed, "
846                                         <<added_objects.size()<<" added, "
847                                         <<"packet size is "<<reply.getSize()<<std::endl;
848                 }
849                 m_clients.Unlock();
850 #if 0
851                 /*
852                         Collect a list of all the objects known by the clients
853                         and report it back to the environment.
854                 */
855
856                 core::map<u16, bool> all_known_objects;
857
858                 for(core::map<u16, RemoteClient*>::Iterator
859                         i = m_clients.getIterator();
860                         i.atEnd() == false; i++)
861                 {
862                         RemoteClient *client = i.getNode()->getValue();
863                         // Go through all known objects of client
864                         for(core::map<u16, bool>::Iterator
865                                         i = client->m_known_objects.getIterator();
866                                         i.atEnd()==false; i++)
867                         {
868                                 u16 id = i.getNode()->getKey();
869                                 all_known_objects[id] = true;
870                         }
871                 }
872
873                 m_env->setKnownActiveObjects(whatever);
874 #endif
875
876         }
877
878         /*
879                 Send object messages
880         */
881         {
882                 JMutexAutoLock envlock(m_env_mutex);
883                 ScopeProfiler sp(g_profiler, "Server: sending object messages");
884
885                 // Key = object id
886                 // Value = data sent by object
887                 std::map<u16, std::list<ActiveObjectMessage>* > buffered_messages;
888
889                 // Get active object messages from environment
890                 for(;;)
891                 {
892                         ActiveObjectMessage aom = m_env->getActiveObjectMessage();
893                         if(aom.id == 0)
894                                 break;
895
896                         std::list<ActiveObjectMessage>* message_list = NULL;
897                         std::map<u16, std::list<ActiveObjectMessage>* >::iterator n;
898                         n = buffered_messages.find(aom.id);
899                         if(n == buffered_messages.end())
900                         {
901                                 message_list = new std::list<ActiveObjectMessage>;
902                                 buffered_messages[aom.id] = message_list;
903                         }
904                         else
905                         {
906                                 message_list = n->second;
907                         }
908                         message_list->push_back(aom);
909                 }
910
911                 m_clients.Lock();
912                 std::map<u16, RemoteClient*> clients = m_clients.getClientList();
913                 // Route data to every client
914                 for(std::map<u16, RemoteClient*>::iterator
915                         i = clients.begin();
916                         i != clients.end(); ++i)
917                 {
918                         RemoteClient *client = i->second;
919                         std::string reliable_data;
920                         std::string unreliable_data;
921                         // Go through all objects in message buffer
922                         for(std::map<u16, std::list<ActiveObjectMessage>* >::iterator
923                                         j = buffered_messages.begin();
924                                         j != buffered_messages.end(); ++j)
925                         {
926                                 // If object is not known by client, skip it
927                                 u16 id = j->first;
928                                 if(client->m_known_objects.find(id) == client->m_known_objects.end())
929                                         continue;
930                                 // Get message list of object
931                                 std::list<ActiveObjectMessage>* list = j->second;
932                                 // Go through every message
933                                 for(std::list<ActiveObjectMessage>::iterator
934                                                 k = list->begin(); k != list->end(); ++k)
935                                 {
936                                         // Compose the full new data with header
937                                         ActiveObjectMessage aom = *k;
938                                         std::string new_data;
939                                         // Add object id
940                                         char buf[2];
941                                         writeU16((u8*)&buf[0], aom.id);
942                                         new_data.append(buf, 2);
943                                         // Add data
944                                         new_data += serializeString(aom.datastring);
945                                         // Add data to buffer
946                                         if(aom.reliable)
947                                                 reliable_data += new_data;
948                                         else
949                                                 unreliable_data += new_data;
950                                 }
951                         }
952                         /*
953                                 reliable_data and unreliable_data are now ready.
954                                 Send them.
955                         */
956                         if(reliable_data.size() > 0)
957                         {
958                                 SharedBuffer<u8> reply(2 + reliable_data.size());
959                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
960                                 memcpy((char*)&reply[2], reliable_data.c_str(),
961                                                 reliable_data.size());
962                                 // Send as reliable
963                                 m_clients.send(client->peer_id, 0, reply, true);
964                         }
965                         if(unreliable_data.size() > 0)
966                         {
967                                 SharedBuffer<u8> reply(2 + unreliable_data.size());
968                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
969                                 memcpy((char*)&reply[2], unreliable_data.c_str(),
970                                                 unreliable_data.size());
971                                 // Send as unreliable
972                                 m_clients.send(client->peer_id, 1, reply, false);
973                         }
974
975                         /*if(reliable_data.size() > 0 || unreliable_data.size() > 0)
976                         {
977                                 infostream<<"Server: Size of object message data: "
978                                                 <<"reliable: "<<reliable_data.size()
979                                                 <<", unreliable: "<<unreliable_data.size()
980                                                 <<std::endl;
981                         }*/
982                 }
983                 m_clients.Unlock();
984
985                 // Clear buffered_messages
986                 for(std::map<u16, std::list<ActiveObjectMessage>* >::iterator
987                                 i = buffered_messages.begin();
988                                 i != buffered_messages.end(); ++i)
989                 {
990                         delete i->second;
991                 }
992         }
993
994         /*
995                 Send queued-for-sending map edit events.
996         */
997         {
998                 // We will be accessing the environment
999                 JMutexAutoLock lock(m_env_mutex);
1000
1001                 // Don't send too many at a time
1002                 //u32 count = 0;
1003
1004                 // Single change sending is disabled if queue size is not small
1005                 bool disable_single_change_sending = false;
1006                 if(m_unsent_map_edit_queue.size() >= 4)
1007                         disable_single_change_sending = true;
1008
1009                 int event_count = m_unsent_map_edit_queue.size();
1010
1011                 // We'll log the amount of each
1012                 Profiler prof;
1013
1014                 while(m_unsent_map_edit_queue.size() != 0)
1015                 {
1016                         MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
1017
1018                         // Players far away from the change are stored here.
1019                         // Instead of sending the changes, MapBlocks are set not sent
1020                         // for them.
1021                         std::list<u16> far_players;
1022
1023                         if(event->type == MEET_ADDNODE || event->type == MEET_SWAPNODE)
1024                         {
1025                                 //infostream<<"Server: MEET_ADDNODE"<<std::endl;
1026                                 prof.add("MEET_ADDNODE", 1);
1027                                 if(disable_single_change_sending)
1028                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1029                                                         &far_players, 5, event->type == MEET_ADDNODE);
1030                                 else
1031                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1032                                                         &far_players, 30, event->type == MEET_ADDNODE);
1033                         }
1034                         else if(event->type == MEET_REMOVENODE)
1035                         {
1036                                 //infostream<<"Server: MEET_REMOVENODE"<<std::endl;
1037                                 prof.add("MEET_REMOVENODE", 1);
1038                                 if(disable_single_change_sending)
1039                                         sendRemoveNode(event->p, event->already_known_by_peer,
1040                                                         &far_players, 5);
1041                                 else
1042                                         sendRemoveNode(event->p, event->already_known_by_peer,
1043                                                         &far_players, 30);
1044                         }
1045                         else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
1046                         {
1047                                 infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
1048                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
1049                                 setBlockNotSent(event->p);
1050                         }
1051                         else if(event->type == MEET_OTHER)
1052                         {
1053                                 infostream<<"Server: MEET_OTHER"<<std::endl;
1054                                 prof.add("MEET_OTHER", 1);
1055                                 for(std::set<v3s16>::iterator
1056                                                 i = event->modified_blocks.begin();
1057                                                 i != event->modified_blocks.end(); ++i)
1058                                 {
1059                                         setBlockNotSent(*i);
1060                                 }
1061                         }
1062                         else
1063                         {
1064                                 prof.add("unknown", 1);
1065                                 infostream<<"WARNING: Server: Unknown MapEditEvent "
1066                                                 <<((u32)event->type)<<std::endl;
1067                         }
1068
1069                         /*
1070                                 Set blocks not sent to far players
1071                         */
1072                         if(far_players.size() > 0)
1073                         {
1074                                 // Convert list format to that wanted by SetBlocksNotSent
1075                                 std::map<v3s16, MapBlock*> modified_blocks2;
1076                                 for(std::set<v3s16>::iterator
1077                                                 i = event->modified_blocks.begin();
1078                                                 i != event->modified_blocks.end(); ++i)
1079                                 {
1080                                         modified_blocks2[*i] =
1081                                                         m_env->getMap().getBlockNoCreateNoEx(*i);
1082                                 }
1083                                 // Set blocks not sent
1084                                 for(std::list<u16>::iterator
1085                                                 i = far_players.begin();
1086                                                 i != far_players.end(); ++i)
1087                                 {
1088                                         u16 peer_id = *i;
1089                                         RemoteClient *client = getClient(peer_id);
1090                                         if(client==NULL)
1091                                                 continue;
1092                                         client->SetBlocksNotSent(modified_blocks2);
1093                                 }
1094                         }
1095
1096                         delete event;
1097
1098                         /*// Don't send too many at a time
1099                         count++;
1100                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
1101                                 break;*/
1102                 }
1103
1104                 if(event_count >= 5){
1105                         infostream<<"Server: MapEditEvents:"<<std::endl;
1106                         prof.print(infostream);
1107                 } else if(event_count != 0){
1108                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
1109                         prof.print(verbosestream);
1110                 }
1111
1112         }
1113
1114         /*
1115                 Trigger emergethread (it somehow gets to a non-triggered but
1116                 bysy state sometimes)
1117         */
1118         {
1119                 float &counter = m_emergethread_trigger_timer;
1120                 counter += dtime;
1121                 if(counter >= 2.0)
1122                 {
1123                         counter = 0.0;
1124
1125                         m_emerge->startThreads();
1126
1127                         // Update m_enable_rollback_recording here too
1128                         m_enable_rollback_recording =
1129                                         g_settings->getBool("enable_rollback_recording");
1130                 }
1131         }
1132
1133         // Save map, players and auth stuff
1134         {
1135                 float &counter = m_savemap_timer;
1136                 counter += dtime;
1137                 if(counter >= g_settings->getFloat("server_map_save_interval"))
1138                 {
1139                         counter = 0.0;
1140                         JMutexAutoLock lock(m_env_mutex);
1141
1142                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1143
1144                         //Ban stuff
1145                         if(m_banmanager->isModified())
1146                                 m_banmanager->save();
1147
1148                         // Save changed parts of map
1149                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1150
1151                         // Save players
1152                         m_env->serializePlayers(m_path_world);
1153
1154                         // Save environment metadata
1155                         m_env->saveMeta(m_path_world);
1156                 }
1157         }
1158 }
1159
1160 void Server::Receive()
1161 {
1162         DSTACK(__FUNCTION_NAME);
1163         SharedBuffer<u8> data;
1164         u16 peer_id;
1165         u32 datasize;
1166         try{
1167                 datasize = m_con.Receive(peer_id,data);
1168                 ProcessData(*data, datasize, peer_id);
1169         }
1170         catch(con::InvalidIncomingDataException &e)
1171         {
1172                 infostream<<"Server::Receive(): "
1173                                 "InvalidIncomingDataException: what()="
1174                                 <<e.what()<<std::endl;
1175         }
1176         catch(con::PeerNotFoundException &e)
1177         {
1178                 //NOTE: This is not needed anymore
1179
1180                 // The peer has been disconnected.
1181                 // Find the associated player and remove it.
1182
1183                 /*JMutexAutoLock envlock(m_env_mutex);
1184
1185                 infostream<<"ServerThread: peer_id="<<peer_id
1186                                 <<" has apparently closed connection. "
1187                                 <<"Removing player."<<std::endl;
1188
1189                 m_env->removePlayer(peer_id);*/
1190         }
1191         catch(ClientStateError &e)
1192         {
1193                 errorstream << "ProcessData: peer=" << peer_id  << e.what() << std::endl;
1194                 DenyAccess(peer_id, L"Your client sent something server didn't expect."
1195                                 L"Try reconnecting or updating your client");
1196         }
1197 }
1198
1199 PlayerSAO* Server::StageTwoClientInit(u16 peer_id)
1200 {
1201         std::string playername = "";
1202         PlayerSAO *playersao = NULL;
1203         m_clients.Lock();
1204         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,InitDone);
1205         if (client != NULL) {
1206                 playername = client->getName();
1207                 playersao = emergePlayer(playername.c_str(), peer_id);
1208         }
1209         m_clients.Unlock();
1210
1211         RemotePlayer *player =
1212                 static_cast<RemotePlayer*>(m_env->getPlayer(playername.c_str()));
1213
1214         // If failed, cancel
1215         if((playersao == NULL) || (player == NULL))
1216         {
1217                 if(player && player->peer_id != 0){
1218                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1219                                         <<" (player allocated to an another client)"<<std::endl;
1220                         DenyAccess(peer_id, L"Another client is connected with this "
1221                                         L"name. If your client closed unexpectedly, try again in "
1222                                         L"a minute.");
1223                 } else {
1224                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1225                                         <<std::endl;
1226                         DenyAccess(peer_id, L"Could not allocate player.");
1227                 }
1228                 return NULL;
1229         }
1230
1231         /*
1232                 Send complete position information
1233         */
1234         SendMovePlayer(peer_id);
1235
1236         // Send privileges
1237         SendPlayerPrivileges(peer_id);
1238
1239         // Send inventory formspec
1240         SendPlayerInventoryFormspec(peer_id);
1241
1242         // Send inventory
1243         UpdateCrafting(peer_id);
1244         SendInventory(peer_id);
1245
1246         // Send HP
1247         if(g_settings->getBool("enable_damage"))
1248                 SendPlayerHP(peer_id);
1249
1250         // Send Breath
1251         SendPlayerBreath(peer_id);
1252
1253         // Show death screen if necessary
1254         if(player->hp == 0)
1255                 SendDeathscreen(peer_id, false, v3f(0,0,0));
1256
1257         // Note things in chat if not in simple singleplayer mode
1258         if(!m_simple_singleplayer_mode)
1259         {
1260                 // Send information about server to player in chat
1261                 SendChatMessage(peer_id, getStatusString());
1262
1263                 // Send information about joining in chat
1264                 {
1265                         std::wstring name = L"unknown";
1266                         Player *player = m_env->getPlayer(peer_id);
1267                         if(player != NULL)
1268                                 name = narrow_to_wide(player->getName());
1269
1270                         std::wstring message;
1271                         message += L"*** ";
1272                         message += name;
1273                         message += L" joined the game.";
1274                         SendChatMessage(PEER_ID_INEXISTENT,message);
1275                 }
1276         }
1277         Address addr = getPeerAddress(player->peer_id);
1278         std::string ip_str = addr.serializeString();
1279         actionstream<<player->getName() <<" [" << ip_str << "] joins game. " << std::endl;
1280         /*
1281                 Print out action
1282         */
1283         {
1284                 std::vector<std::string> names = m_clients.getPlayerNames();
1285
1286                 actionstream<<player->getName() <<" joins game. List of players: ";
1287
1288                 for (std::vector<std::string>::iterator i = names.begin();
1289                                 i != names.end(); i++)
1290                 {
1291                         actionstream << *i << " ";
1292                 }
1293
1294                 actionstream << player->getName() <<std::endl;
1295         }
1296         return playersao;
1297 }
1298
1299 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1300 {
1301         DSTACK(__FUNCTION_NAME);
1302         // Environment is locked first.
1303         JMutexAutoLock envlock(m_env_mutex);
1304
1305         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1306
1307         std::string addr_s;
1308         try{
1309                 Address address = getPeerAddress(peer_id);
1310                 addr_s = address.serializeString();
1311
1312                 // drop player if is ip is banned
1313                 if(m_banmanager->isIpBanned(addr_s)){
1314                         std::string ban_name = m_banmanager->getBanName(addr_s);
1315                         infostream<<"Server: A banned client tried to connect from "
1316                                         <<addr_s<<"; banned name was "
1317                                         <<ban_name<<std::endl;
1318                         // This actually doesn't seem to transfer to the client
1319                         DenyAccess(peer_id, L"Your ip is banned. Banned name was "
1320                                         +narrow_to_wide(ban_name));
1321                         return;
1322                 }
1323         }
1324         catch(con::PeerNotFoundException &e)
1325         {
1326                 /*
1327                  * no peer for this packet found
1328                  * most common reason is peer timeout, e.g. peer didn't
1329                  * respond for some time, your server was overloaded or
1330                  * things like that.
1331                  */
1332                 infostream<<"Server::ProcessData(): Cancelling: peer "
1333                                 <<peer_id<<" not found"<<std::endl;
1334                 return;
1335         }
1336
1337         try
1338         {
1339
1340         if(datasize < 2)
1341                 return;
1342
1343         ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1344
1345         if(command == TOSERVER_INIT)
1346         {
1347                 // [0] u16 TOSERVER_INIT
1348                 // [2] u8 SER_FMT_VER_HIGHEST_READ
1349                 // [3] u8[20] player_name
1350                 // [23] u8[28] password <--- can be sent without this, from old versions
1351
1352                 if(datasize < 2+1+PLAYERNAME_SIZE)
1353                         return;
1354
1355                 RemoteClient* client = getClient(peer_id,Created);
1356
1357                 // If net_proto_version is set, this client has already been handled
1358                 if(client->getState() > Created)
1359                 {
1360                         verbosestream<<"Server: Ignoring multiple TOSERVER_INITs from "
1361                                         <<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1362                         return;
1363                 }
1364
1365                 verbosestream<<"Server: Got TOSERVER_INIT from "<<addr_s<<" (peer_id="
1366                                 <<peer_id<<")"<<std::endl;
1367
1368                 // Do not allow multiple players in simple singleplayer mode.
1369                 // This isn't a perfect way to do it, but will suffice for now
1370                 if(m_simple_singleplayer_mode && m_clients.getClientIDs().size() > 1){
1371                         infostream<<"Server: Not allowing another client ("<<addr_s
1372                                         <<") to connect in simple singleplayer mode"<<std::endl;
1373                         DenyAccess(peer_id, L"Running in simple singleplayer mode.");
1374                         return;
1375                 }
1376
1377                 // First byte after command is maximum supported
1378                 // serialization version
1379                 u8 client_max = data[2];
1380                 u8 our_max = SER_FMT_VER_HIGHEST_READ;
1381                 // Use the highest version supported by both
1382                 u8 deployed = std::min(client_max, our_max);
1383                 // If it's lower than the lowest supported, give up.
1384                 if(deployed < SER_FMT_VER_LOWEST)
1385                         deployed = SER_FMT_VER_INVALID;
1386
1387                 if(deployed == SER_FMT_VER_INVALID)
1388                 {
1389                         actionstream<<"Server: A mismatched client tried to connect from "
1390                                         <<addr_s<<std::endl;
1391                         infostream<<"Server: Cannot negotiate serialization version with "
1392                                         <<addr_s<<std::endl;
1393                         DenyAccess(peer_id, std::wstring(
1394                                         L"Your client's version is not supported.\n"
1395                                         L"Server version is ")
1396                                         + narrow_to_wide(minetest_version_simple) + L"."
1397                         );
1398                         return;
1399                 }
1400
1401                 client->setPendingSerializationVersion(deployed);
1402
1403                 /*
1404                         Read and check network protocol version
1405                 */
1406
1407                 u16 min_net_proto_version = 0;
1408                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1409                         min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1410
1411                 // Use same version as minimum and maximum if maximum version field
1412                 // doesn't exist (backwards compatibility)
1413                 u16 max_net_proto_version = min_net_proto_version;
1414                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
1415                         max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
1416
1417                 // Start with client's maximum version
1418                 u16 net_proto_version = max_net_proto_version;
1419
1420                 // Figure out a working version if it is possible at all
1421                 if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN ||
1422                                 min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX)
1423                 {
1424                         // If maximum is larger than our maximum, go with our maximum
1425                         if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1426                                 net_proto_version = SERVER_PROTOCOL_VERSION_MAX;
1427                         // Else go with client's maximum
1428                         else
1429                                 net_proto_version = max_net_proto_version;
1430                 }
1431
1432                 verbosestream<<"Server: "<<addr_s<<": Protocol version: min: "
1433                                 <<min_net_proto_version<<", max: "<<max_net_proto_version
1434                                 <<", chosen: "<<net_proto_version<<std::endl;
1435
1436                 client->net_proto_version = net_proto_version;
1437
1438                 if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN ||
1439                                 net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
1440                 {
1441                         actionstream<<"Server: A mismatched client tried to connect from "
1442                                         <<addr_s<<std::endl;
1443                         DenyAccess(peer_id, std::wstring(
1444                                         L"Your client's version is not supported.\n"
1445                                         L"Server version is ")
1446                                         + narrow_to_wide(minetest_version_simple) + L",\n"
1447                                         + L"server's PROTOCOL_VERSION is "
1448                                         + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN))
1449                                         + L"..."
1450                                         + narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX))
1451                                         + L", client's PROTOCOL_VERSION is "
1452                                         + narrow_to_wide(itos(min_net_proto_version))
1453                                         + L"..."
1454                                         + narrow_to_wide(itos(max_net_proto_version))
1455                         );
1456                         return;
1457                 }
1458
1459                 if(g_settings->getBool("strict_protocol_version_checking"))
1460                 {
1461                         if(net_proto_version != LATEST_PROTOCOL_VERSION)
1462                         {
1463                                 actionstream<<"Server: A mismatched (strict) client tried to "
1464                                                 <<"connect from "<<addr_s<<std::endl;
1465                                 DenyAccess(peer_id, std::wstring(
1466                                                 L"Your client's version is not supported.\n"
1467                                                 L"Server version is ")
1468                                                 + narrow_to_wide(minetest_version_simple) + L",\n"
1469                                                 + L"server's PROTOCOL_VERSION (strict) is "
1470                                                 + narrow_to_wide(itos(LATEST_PROTOCOL_VERSION))
1471                                                 + L", client's PROTOCOL_VERSION is "
1472                                                 + narrow_to_wide(itos(min_net_proto_version))
1473                                                 + L"..."
1474                                                 + narrow_to_wide(itos(max_net_proto_version))
1475                                 );
1476                                 return;
1477                         }
1478                 }
1479
1480                 /*
1481                         Set up player
1482                 */
1483
1484                 // Get player name
1485                 char playername[PLAYERNAME_SIZE];
1486                 for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
1487                 {
1488                         playername[i] = data[3+i];
1489                 }
1490                 playername[PLAYERNAME_SIZE-1] = 0;
1491
1492                 if(playername[0]=='\0')
1493                 {
1494                         actionstream<<"Server: Player with an empty name "
1495                                         <<"tried to connect from "<<addr_s<<std::endl;
1496                         DenyAccess(peer_id, L"Empty name");
1497                         return;
1498                 }
1499
1500                 if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
1501                 {
1502                         actionstream<<"Server: Player with an invalid name "
1503                                         <<"tried to connect from "<<addr_s<<std::endl;
1504                         DenyAccess(peer_id, L"Name contains unallowed characters");
1505                         return;
1506                 }
1507
1508                 if(!isSingleplayer() && strcasecmp(playername, "singleplayer") == 0)
1509                 {
1510                         actionstream<<"Server: Player with the name \"singleplayer\" "
1511                                         <<"tried to connect from "<<addr_s<<std::endl;
1512                         DenyAccess(peer_id, L"Name is not allowed");
1513                         return;
1514                 }
1515
1516                 {
1517                         std::string reason;
1518                         if(m_script->on_prejoinplayer(playername, addr_s, reason))
1519                         {
1520                                 actionstream<<"Server: Player with the name \""<<playername<<"\" "
1521                                                 <<"tried to connect from "<<addr_s<<" "
1522                                                 <<"but it was disallowed for the following reason: "
1523                                                 <<reason<<std::endl;
1524                                 DenyAccess(peer_id, narrow_to_wide(reason.c_str()));
1525                                 return;
1526                         }
1527                 }
1528
1529                 infostream<<"Server: New connection: \""<<playername<<"\" from "
1530                                 <<addr_s<<" (peer_id="<<peer_id<<")"<<std::endl;
1531
1532                 // Get password
1533                 char given_password[PASSWORD_SIZE];
1534                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
1535                 {
1536                         // old version - assume blank password
1537                         given_password[0] = 0;
1538                 }
1539                 else
1540                 {
1541                         for(u32 i=0; i<PASSWORD_SIZE-1; i++)
1542                         {
1543                                 given_password[i] = data[23+i];
1544                         }
1545                         given_password[PASSWORD_SIZE-1] = 0;
1546                 }
1547
1548                 if(!base64_is_valid(given_password)){
1549                         actionstream<<"Server: "<<playername
1550                                         <<" supplied invalid password hash"<<std::endl;
1551                         DenyAccess(peer_id, L"Invalid password hash");
1552                         return;
1553                 }
1554
1555                 // Enforce user limit.
1556                 // Don't enforce for users that have some admin right
1557                 if(m_clients.getClientIDs(Created).size() >= g_settings->getU16("max_users") &&
1558                                 !checkPriv(playername, "server") &&
1559                                 !checkPriv(playername, "ban") &&
1560                                 !checkPriv(playername, "privs") &&
1561                                 !checkPriv(playername, "password") &&
1562                                 playername != g_settings->get("name"))
1563                 {
1564                         actionstream<<"Server: "<<playername<<" tried to join, but there"
1565                                         <<" are already max_users="
1566                                         <<g_settings->getU16("max_users")<<" players."<<std::endl;
1567                         DenyAccess(peer_id, L"Too many users.");
1568                         return;
1569                 }
1570
1571                 std::string checkpwd; // Password hash to check against
1572                 bool has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1573
1574                 // If no authentication info exists for user, create it
1575                 if(!has_auth){
1576                         if(!isSingleplayer() &&
1577                                         g_settings->getBool("disallow_empty_password") &&
1578                                         std::string(given_password) == ""){
1579                                 actionstream<<"Server: "<<playername
1580                                                 <<" supplied empty password"<<std::endl;
1581                                 DenyAccess(peer_id, L"Empty passwords are "
1582                                                 L"disallowed. Set a password and try again.");
1583                                 return;
1584                         }
1585                         std::wstring raw_default_password =
1586                                 narrow_to_wide(g_settings->get("default_password"));
1587                         std::string initial_password =
1588                                 translatePassword(playername, raw_default_password);
1589
1590                         // If default_password is empty, allow any initial password
1591                         if (raw_default_password.length() == 0)
1592                                 initial_password = given_password;
1593
1594                         m_script->createAuth(playername, initial_password);
1595                 }
1596
1597                 has_auth = m_script->getAuth(playername, &checkpwd, NULL);
1598
1599                 if(!has_auth){
1600                         actionstream<<"Server: "<<playername<<" cannot be authenticated"
1601                                         <<" (auth handler does not work?)"<<std::endl;
1602                         DenyAccess(peer_id, L"Not allowed to login");
1603                         return;
1604                 }
1605
1606                 if(given_password != checkpwd){
1607                         actionstream<<"Server: "<<playername<<" supplied wrong password"
1608                                         <<std::endl;
1609                         DenyAccess(peer_id, L"Wrong password");
1610                         return;
1611                 }
1612
1613                 RemotePlayer *player =
1614                                 static_cast<RemotePlayer*>(m_env->getPlayer(playername));
1615
1616                 if(player && player->peer_id != 0){
1617                         errorstream<<"Server: "<<playername<<": Failed to emerge player"
1618                                         <<" (player allocated to an another client)"<<std::endl;
1619                         DenyAccess(peer_id, L"Another client is connected with this "
1620                                         L"name. If your client closed unexpectedly, try again in "
1621                                         L"a minute.");
1622                 }
1623
1624                 m_clients.setPlayerName(peer_id,playername);
1625
1626                 /*
1627                         Answer with a TOCLIENT_INIT
1628                 */
1629                 {
1630                         SharedBuffer<u8> reply(2+1+6+8+4);
1631                         writeU16(&reply[0], TOCLIENT_INIT);
1632                         writeU8(&reply[2], deployed);
1633                         //send dummy pos for legacy reasons only
1634                         writeV3S16(&reply[2+1], floatToInt(v3f(0,0,0), BS));
1635                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
1636                         writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
1637
1638                         // Send as reliable
1639                         m_clients.send(peer_id, 0, reply, true);
1640                         m_clients.event(peer_id, Init);
1641                 }
1642
1643                 return;
1644         }
1645
1646         if(command == TOSERVER_INIT2)
1647         {
1648
1649                 verbosestream<<"Server: Got TOSERVER_INIT2 from "
1650                                 <<peer_id<<std::endl;
1651
1652                 m_clients.event(peer_id, GotInit2);
1653                 u16 protocol_version = m_clients.getProtocolVersion(peer_id);
1654
1655
1656                 ///// begin compatibility code
1657                 PlayerSAO* playersao = NULL;
1658                 if (protocol_version <= 22) {
1659                         playersao = StageTwoClientInit(peer_id);
1660
1661                         if (playersao == NULL) {
1662                                 errorstream
1663                                         << "TOSERVER_INIT2 stage 2 client init failed for peer "
1664                                         << peer_id << std::endl;
1665                                 return;
1666                         }
1667                 }
1668                 ///// end compatibility code
1669
1670                 /*
1671                         Send some initialization data
1672                 */
1673
1674                 infostream<<"Server: Sending content to "
1675                                 <<getPlayerName(peer_id)<<std::endl;
1676
1677                 // Send player movement settings
1678                 SendMovement(peer_id);
1679
1680                 // Send item definitions
1681                 SendItemDef(peer_id, m_itemdef, protocol_version);
1682
1683                 // Send node definitions
1684                 SendNodeDef(peer_id, m_nodedef, protocol_version);
1685
1686                 m_clients.event(peer_id, SetDefinitionsSent);
1687
1688                 // Send media announcement
1689                 sendMediaAnnouncement(peer_id);
1690
1691                 // Send detached inventories
1692                 sendDetachedInventories(peer_id);
1693
1694                 // Send time of day
1695                 u16 time = m_env->getTimeOfDay();
1696                 float time_speed = g_settings->getFloat("time_speed");
1697                 SendTimeOfDay(peer_id, time, time_speed);
1698
1699                 ///// begin compatibility code
1700                 if (protocol_version <= 22) {
1701                         m_clients.event(peer_id, SetClientReady);
1702                         m_script->on_joinplayer(playersao);
1703                 }
1704                 ///// end compatibility code
1705
1706                 // Warnings about protocol version can be issued here
1707                 if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
1708                 {
1709                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S "
1710                                         L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
1711                 }
1712
1713                 return;
1714         }
1715
1716         u8 peer_ser_ver = getClient(peer_id,InitDone)->serialization_version;
1717         u16 peer_proto_ver = getClient(peer_id,InitDone)->net_proto_version;
1718
1719         if(peer_ser_ver == SER_FMT_VER_INVALID)
1720         {
1721                 errorstream<<"Server::ProcessData(): Cancelling: Peer"
1722                                 " serialization format invalid or not initialized."
1723                                 " Skipping incoming command="<<command<<std::endl;
1724                 return;
1725         }
1726
1727         /* Handle commands relate to client startup */
1728         if(command == TOSERVER_REQUEST_MEDIA) {
1729                 std::string datastring((char*)&data[2], datasize-2);
1730                 std::istringstream is(datastring, std::ios_base::binary);
1731
1732                 std::list<std::string> tosend;
1733                 u16 numfiles = readU16(is);
1734
1735                 infostream<<"Sending "<<numfiles<<" files to "
1736                                 <<getPlayerName(peer_id)<<std::endl;
1737                 verbosestream<<"TOSERVER_REQUEST_MEDIA: "<<std::endl;
1738
1739                 for(int i = 0; i < numfiles; i++) {
1740                         std::string name = deSerializeString(is);
1741                         tosend.push_back(name);
1742                         verbosestream<<"TOSERVER_REQUEST_MEDIA: requested file "
1743                                         <<name<<std::endl;
1744                 }
1745
1746                 sendRequestedMedia(peer_id, tosend);
1747                 return;
1748         }
1749         else if(command == TOSERVER_RECEIVED_MEDIA) {
1750                 return;
1751         }
1752         else if(command == TOSERVER_CLIENT_READY) {
1753                 // clients <= protocol version 22 did not send ready message,
1754                 // they're already initialized
1755                 if (peer_proto_ver <= 22) {
1756                         infostream << "Client sent message not expected by a "
1757                                 << "client using protocol version <= 22,"
1758                                 << "disconnecing peer_id: " << peer_id << std::endl;
1759                         m_con.DisconnectPeer(peer_id);
1760                         return;
1761                 }
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                 m_clients.Unlock();
2905                 return false;
2906                 }
2907
2908         *uptime = client->uptime();
2909         *ser_vers = client->serialization_version;
2910         *prot_vers = client->net_proto_version;
2911
2912         *major = client->getMajor();
2913         *minor = client->getMinor();
2914         *patch = client->getPatch();
2915         *vers_string = client->getPatch();
2916
2917         m_clients.Unlock();
2918
2919         return true;
2920 }
2921
2922 void Server::handlePeerChanges()
2923 {
2924         while(m_peer_change_queue.size() > 0)
2925         {
2926                 con::PeerChange c = m_peer_change_queue.pop_front();
2927
2928                 verbosestream<<"Server: Handling peer change: "
2929                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
2930                                 <<std::endl;
2931
2932                 switch(c.type)
2933                 {
2934                 case con::PEER_ADDED:
2935                         m_clients.CreateClient(c.peer_id);
2936                         break;
2937
2938                 case con::PEER_REMOVED:
2939                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
2940                         break;
2941
2942                 default:
2943                         assert("Invalid peer change event received!" == 0);
2944                         break;
2945                 }
2946         }
2947 }
2948
2949 void Server::SendMovement(u16 peer_id)
2950 {
2951         DSTACK(__FUNCTION_NAME);
2952         std::ostringstream os(std::ios_base::binary);
2953
2954         writeU16(os, TOCLIENT_MOVEMENT);
2955         writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
2956         writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
2957         writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
2958         writeF1000(os, g_settings->getFloat("movement_speed_walk"));
2959         writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
2960         writeF1000(os, g_settings->getFloat("movement_speed_fast"));
2961         writeF1000(os, g_settings->getFloat("movement_speed_climb"));
2962         writeF1000(os, g_settings->getFloat("movement_speed_jump"));
2963         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
2964         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
2965         writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
2966         writeF1000(os, g_settings->getFloat("movement_gravity"));
2967
2968         // Make data buffer
2969         std::string s = os.str();
2970         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2971         // Send as reliable
2972         m_clients.send(peer_id, 0, data, true);
2973 }
2974
2975 void Server::SendHP(u16 peer_id, u8 hp)
2976 {
2977         DSTACK(__FUNCTION_NAME);
2978         std::ostringstream os(std::ios_base::binary);
2979
2980         writeU16(os, TOCLIENT_HP);
2981         writeU8(os, hp);
2982
2983         // Make data buffer
2984         std::string s = os.str();
2985         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2986         // Send as reliable
2987         m_clients.send(peer_id, 0, data, true);
2988 }
2989
2990 void Server::SendBreath(u16 peer_id, u16 breath)
2991 {
2992         DSTACK(__FUNCTION_NAME);
2993         std::ostringstream os(std::ios_base::binary);
2994
2995         writeU16(os, TOCLIENT_BREATH);
2996         writeU16(os, breath);
2997
2998         // Make data buffer
2999         std::string s = os.str();
3000         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3001         // Send as reliable
3002         m_clients.send(peer_id, 0, data, true);
3003 }
3004
3005 void Server::SendAccessDenied(u16 peer_id,const std::wstring &reason)
3006 {
3007         DSTACK(__FUNCTION_NAME);
3008         std::ostringstream os(std::ios_base::binary);
3009
3010         writeU16(os, TOCLIENT_ACCESS_DENIED);
3011         os<<serializeWideString(reason);
3012
3013         // Make data buffer
3014         std::string s = os.str();
3015         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3016         // Send as reliable
3017         m_clients.send(peer_id, 0, data, true);
3018 }
3019
3020 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
3021                 v3f camera_point_target)
3022 {
3023         DSTACK(__FUNCTION_NAME);
3024         std::ostringstream os(std::ios_base::binary);
3025
3026         writeU16(os, TOCLIENT_DEATHSCREEN);
3027         writeU8(os, set_camera_point_target);
3028         writeV3F1000(os, camera_point_target);
3029
3030         // Make data buffer
3031         std::string s = os.str();
3032         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3033         // Send as reliable
3034         m_clients.send(peer_id, 0, data, true);
3035 }
3036
3037 void Server::SendItemDef(u16 peer_id,
3038                 IItemDefManager *itemdef, u16 protocol_version)
3039 {
3040         DSTACK(__FUNCTION_NAME);
3041         std::ostringstream os(std::ios_base::binary);
3042
3043         /*
3044                 u16 command
3045                 u32 length of the next item
3046                 zlib-compressed serialized ItemDefManager
3047         */
3048         writeU16(os, TOCLIENT_ITEMDEF);
3049         std::ostringstream tmp_os(std::ios::binary);
3050         itemdef->serialize(tmp_os, protocol_version);
3051         std::ostringstream tmp_os2(std::ios::binary);
3052         compressZlib(tmp_os.str(), tmp_os2);
3053         os<<serializeLongString(tmp_os2.str());
3054
3055         // Make data buffer
3056         std::string s = os.str();
3057         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3058                         <<"): size="<<s.size()<<std::endl;
3059         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3060         // Send as reliable
3061         m_clients.send(peer_id, 0, data, true);
3062 }
3063
3064 void Server::SendNodeDef(u16 peer_id,
3065                 INodeDefManager *nodedef, u16 protocol_version)
3066 {
3067         DSTACK(__FUNCTION_NAME);
3068         std::ostringstream os(std::ios_base::binary);
3069
3070         /*
3071                 u16 command
3072                 u32 length of the next item
3073                 zlib-compressed serialized NodeDefManager
3074         */
3075         writeU16(os, TOCLIENT_NODEDEF);
3076         std::ostringstream tmp_os(std::ios::binary);
3077         nodedef->serialize(tmp_os, protocol_version);
3078         std::ostringstream tmp_os2(std::ios::binary);
3079         compressZlib(tmp_os.str(), tmp_os2);
3080         os<<serializeLongString(tmp_os2.str());
3081
3082         // Make data buffer
3083         std::string s = os.str();
3084         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3085                         <<"): size="<<s.size()<<std::endl;
3086         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3087         // Send as reliable
3088         m_clients.send(peer_id, 0, data, true);
3089 }
3090
3091 /*
3092         Non-static send methods
3093 */
3094
3095 void Server::SendInventory(u16 peer_id)
3096 {
3097         DSTACK(__FUNCTION_NAME);
3098
3099         PlayerSAO *playersao = getPlayerSAO(peer_id);
3100         assert(playersao);
3101
3102         playersao->m_inventory_not_sent = false;
3103
3104         /*
3105                 Serialize it
3106         */
3107
3108         std::ostringstream os;
3109         playersao->getInventory()->serialize(os);
3110
3111         std::string s = os.str();
3112
3113         SharedBuffer<u8> data(s.size()+2);
3114         writeU16(&data[0], TOCLIENT_INVENTORY);
3115         memcpy(&data[2], s.c_str(), s.size());
3116
3117         // Send as reliable
3118         m_clients.send(peer_id, 0, data, true);
3119 }
3120
3121 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3122 {
3123         DSTACK(__FUNCTION_NAME);
3124
3125         std::ostringstream os(std::ios_base::binary);
3126         u8 buf[12];
3127
3128         // Write command
3129         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3130         os.write((char*)buf, 2);
3131
3132         // Write length
3133         writeU16(buf, message.size());
3134         os.write((char*)buf, 2);
3135
3136         // Write string
3137         for(u32 i=0; i<message.size(); i++)
3138         {
3139                 u16 w = message[i];
3140                 writeU16(buf, w);
3141                 os.write((char*)buf, 2);
3142         }
3143
3144         // Make data buffer
3145         std::string s = os.str();
3146         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3147
3148         if (peer_id != PEER_ID_INEXISTENT)
3149         {
3150                 // Send as reliable
3151                 m_clients.send(peer_id, 0, data, true);
3152         }
3153         else
3154         {
3155                 m_clients.sendToAll(0,data,true);
3156         }
3157 }
3158
3159 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
3160                                      const std::string &formname)
3161 {
3162         DSTACK(__FUNCTION_NAME);
3163
3164         std::ostringstream os(std::ios_base::binary);
3165         u8 buf[12];
3166
3167         // Write command
3168         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3169         os.write((char*)buf, 2);
3170         os<<serializeLongString(formspec);
3171         os<<serializeString(formname);
3172
3173         // Make data buffer
3174         std::string s = os.str();
3175         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3176         // Send as reliable
3177         m_clients.send(peer_id, 0, data, true);
3178 }
3179
3180 // Spawns a particle on peer with peer_id
3181 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3182                                 float expirationtime, float size, bool collisiondetection,
3183                                 bool vertical, std::string texture)
3184 {
3185         DSTACK(__FUNCTION_NAME);
3186
3187         std::ostringstream os(std::ios_base::binary);
3188         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3189         writeV3F1000(os, pos);
3190         writeV3F1000(os, velocity);
3191         writeV3F1000(os, acceleration);
3192         writeF1000(os, expirationtime);
3193         writeF1000(os, size);
3194         writeU8(os,  collisiondetection);
3195         os<<serializeLongString(texture);
3196         writeU8(os, vertical);
3197
3198         // Make data buffer
3199         std::string s = os.str();
3200         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3201
3202         if (peer_id != PEER_ID_INEXISTENT)
3203         {
3204         // Send as reliable
3205                 m_clients.send(peer_id, 0, data, true);
3206         }
3207         else
3208         {
3209                 m_clients.sendToAll(0,data,true);
3210         }
3211 }
3212
3213 // Adds a ParticleSpawner on peer with peer_id
3214 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3215         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3216         float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
3217 {
3218         DSTACK(__FUNCTION_NAME);
3219
3220         std::ostringstream os(std::ios_base::binary);
3221         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3222
3223         writeU16(os, amount);
3224         writeF1000(os, spawntime);
3225         writeV3F1000(os, minpos);
3226         writeV3F1000(os, maxpos);
3227         writeV3F1000(os, minvel);
3228         writeV3F1000(os, maxvel);
3229         writeV3F1000(os, minacc);
3230         writeV3F1000(os, maxacc);
3231         writeF1000(os, minexptime);
3232         writeF1000(os, maxexptime);
3233         writeF1000(os, minsize);
3234         writeF1000(os, maxsize);
3235         writeU8(os,  collisiondetection);
3236         os<<serializeLongString(texture);
3237         writeU32(os, id);
3238         writeU8(os, vertical);
3239
3240         // Make data buffer
3241         std::string s = os.str();
3242         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3243
3244         if (peer_id != PEER_ID_INEXISTENT)
3245         {
3246                 // Send as reliable
3247                 m_clients.send(peer_id, 0, data, true);
3248         }
3249         else {
3250                 m_clients.sendToAll(0,data,true);
3251         }
3252 }
3253
3254 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3255 {
3256         DSTACK(__FUNCTION_NAME);
3257
3258         std::ostringstream os(std::ios_base::binary);
3259         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3260
3261         writeU16(os, id);
3262
3263         // Make data buffer
3264         std::string s = os.str();
3265         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3266
3267         if (peer_id != PEER_ID_INEXISTENT) {
3268                 // Send as reliable
3269                 m_clients.send(peer_id, 0, data, true);
3270         }
3271         else {
3272                 m_clients.sendToAll(0,data,true);
3273         }
3274
3275 }
3276
3277 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3278 {
3279         std::ostringstream os(std::ios_base::binary);
3280
3281         // Write command
3282         writeU16(os, TOCLIENT_HUDADD);
3283         writeU32(os, id);
3284         writeU8(os, (u8)form->type);
3285         writeV2F1000(os, form->pos);
3286         os << serializeString(form->name);
3287         writeV2F1000(os, form->scale);
3288         os << serializeString(form->text);
3289         writeU32(os, form->number);
3290         writeU32(os, form->item);
3291         writeU32(os, form->dir);
3292         writeV2F1000(os, form->align);
3293         writeV2F1000(os, form->offset);
3294         writeV3F1000(os, form->world_pos);
3295         writeV2S32(os,form->size);
3296
3297         // Make data buffer
3298         std::string s = os.str();
3299         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3300         // Send as reliable
3301         m_clients.send(peer_id, 1, data, true);
3302 }
3303
3304 void Server::SendHUDRemove(u16 peer_id, u32 id)
3305 {
3306         std::ostringstream os(std::ios_base::binary);
3307
3308         // Write command
3309         writeU16(os, TOCLIENT_HUDRM);
3310         writeU32(os, id);
3311
3312         // Make data buffer
3313         std::string s = os.str();
3314         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3315         // Send as reliable
3316
3317         m_clients.send(peer_id, 1, data, true);
3318 }
3319
3320 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3321 {
3322         std::ostringstream os(std::ios_base::binary);
3323
3324         // Write command
3325         writeU16(os, TOCLIENT_HUDCHANGE);
3326         writeU32(os, id);
3327         writeU8(os, (u8)stat);
3328         switch (stat) {
3329                 case HUD_STAT_POS:
3330                 case HUD_STAT_SCALE:
3331                 case HUD_STAT_ALIGN:
3332                 case HUD_STAT_OFFSET:
3333                         writeV2F1000(os, *(v2f *)value);
3334                         break;
3335                 case HUD_STAT_NAME:
3336                 case HUD_STAT_TEXT:
3337                         os << serializeString(*(std::string *)value);
3338                         break;
3339                 case HUD_STAT_WORLD_POS:
3340                         writeV3F1000(os, *(v3f *)value);
3341                         break;
3342                 case HUD_STAT_SIZE:
3343                         writeV2S32(os,*(v2s32 *)value);
3344                         break;
3345                 case HUD_STAT_NUMBER:
3346                 case HUD_STAT_ITEM:
3347                 case HUD_STAT_DIR:
3348                 default:
3349                         writeU32(os, *(u32 *)value);
3350                         break;
3351         }
3352
3353         // Make data buffer
3354         std::string s = os.str();
3355         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3356         // Send as reliable
3357         m_clients.send(peer_id, 0, data, true);
3358 }
3359
3360 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3361 {
3362         std::ostringstream os(std::ios_base::binary);
3363
3364         // Write command
3365         writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3366
3367         //////////////////////////// compatibility code to be removed //////////////
3368         flags &= ~(HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_BREATHBAR_VISIBLE);
3369         ////////////////////////////////////////////////////////////////////////////
3370         writeU32(os, flags);
3371         writeU32(os, mask);
3372
3373         // Make data buffer
3374         std::string s = os.str();
3375         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3376         // Send as reliable
3377         m_clients.send(peer_id, 0, data, true);
3378 }
3379
3380 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3381 {
3382         std::ostringstream os(std::ios_base::binary);
3383
3384         // Write command
3385         writeU16(os, TOCLIENT_HUD_SET_PARAM);
3386         writeU16(os, param);
3387         os<<serializeString(value);
3388
3389         // Make data buffer
3390         std::string s = os.str();
3391         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3392         // Send as reliable
3393         m_clients.send(peer_id, 0, data, true);
3394 }
3395
3396 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
3397                 const std::string &type, const std::vector<std::string> &params)
3398 {
3399         std::ostringstream os(std::ios_base::binary);
3400
3401         // Write command
3402         writeU16(os, TOCLIENT_SET_SKY);
3403         writeARGB8(os, bgcolor);
3404         os<<serializeString(type);
3405         writeU16(os, params.size());
3406         for(size_t i=0; i<params.size(); i++)
3407                 os<<serializeString(params[i]);
3408
3409         // Make data buffer
3410         std::string s = os.str();
3411         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3412         // Send as reliable
3413         m_clients.send(peer_id, 0, data, true);
3414 }
3415
3416 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
3417                 float ratio)
3418 {
3419         std::ostringstream os(std::ios_base::binary);
3420
3421         // Write command
3422         writeU16(os, TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO);
3423         writeU8(os, do_override);
3424         writeU16(os, ratio*65535);
3425
3426         // Make data buffer
3427         std::string s = os.str();
3428         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3429         // Send as reliable
3430         m_clients.send(peer_id, 0, data, true);
3431 }
3432
3433 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
3434 {
3435         DSTACK(__FUNCTION_NAME);
3436
3437         // Make packet
3438         SharedBuffer<u8> data(2+2+4);
3439         writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
3440         writeU16(&data[2], time);
3441         writeF1000(&data[4], time_speed);
3442
3443         if (peer_id == PEER_ID_INEXISTENT) {
3444                 m_clients.sendToAll(0,data,true);
3445         }
3446         else {
3447                 // Send as reliable
3448                 m_clients.send(peer_id, 0, data, true);
3449         }
3450 }
3451
3452 void Server::SendPlayerHP(u16 peer_id)
3453 {
3454         DSTACK(__FUNCTION_NAME);
3455         PlayerSAO *playersao = getPlayerSAO(peer_id);
3456         assert(playersao);
3457         playersao->m_hp_not_sent = false;
3458         SendHP(peer_id, playersao->getHP());
3459         m_script->player_event(playersao,"health_changed");
3460
3461         // Send to other clients
3462         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
3463         ActiveObjectMessage aom(playersao->getId(), true, str);
3464         playersao->m_messages_out.push_back(aom);
3465 }
3466
3467 void Server::SendPlayerBreath(u16 peer_id)
3468 {
3469         DSTACK(__FUNCTION_NAME);
3470         PlayerSAO *playersao = getPlayerSAO(peer_id);
3471         assert(playersao);
3472         playersao->m_breath_not_sent = false;
3473         m_script->player_event(playersao,"breath_changed");
3474         SendBreath(peer_id, playersao->getBreath());
3475 }
3476
3477 void Server::SendMovePlayer(u16 peer_id)
3478 {
3479         DSTACK(__FUNCTION_NAME);
3480         Player *player = m_env->getPlayer(peer_id);
3481         assert(player);
3482
3483         std::ostringstream os(std::ios_base::binary);
3484         writeU16(os, TOCLIENT_MOVE_PLAYER);
3485         writeV3F1000(os, player->getPosition());
3486         writeF1000(os, player->getPitch());
3487         writeF1000(os, player->getYaw());
3488
3489         {
3490                 v3f pos = player->getPosition();
3491                 f32 pitch = player->getPitch();
3492                 f32 yaw = player->getYaw();
3493                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3494                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3495                                 <<" pitch="<<pitch
3496                                 <<" yaw="<<yaw
3497                                 <<std::endl;
3498         }
3499
3500         // Make data buffer
3501         std::string s = os.str();
3502         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3503         // Send as reliable
3504         m_clients.send(peer_id, 0, data, true);
3505 }
3506
3507 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
3508 {
3509         std::ostringstream os(std::ios_base::binary);
3510
3511         writeU16(os, TOCLIENT_LOCAL_PLAYER_ANIMATIONS);
3512         writeV2S32(os, animation_frames[0]);
3513         writeV2S32(os, animation_frames[1]);
3514         writeV2S32(os, animation_frames[2]);
3515         writeV2S32(os, animation_frames[3]);
3516         writeF1000(os, animation_speed);
3517
3518         // Make data buffer
3519         std::string s = os.str();
3520         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3521         // Send as reliable
3522         m_clients.send(peer_id, 0, data, true);
3523 }
3524
3525 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
3526 {
3527         std::ostringstream os(std::ios_base::binary);
3528
3529         writeU16(os, TOCLIENT_EYE_OFFSET);
3530         writeV3F1000(os, first);
3531         writeV3F1000(os, third);
3532
3533         // Make data buffer
3534         std::string s = os.str();
3535         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3536         // Send as reliable
3537         m_clients.send(peer_id, 0, data, true);
3538 }
3539 void Server::SendPlayerPrivileges(u16 peer_id)
3540 {
3541         Player *player = m_env->getPlayer(peer_id);
3542         assert(player);
3543         if(player->peer_id == PEER_ID_INEXISTENT)
3544                 return;
3545
3546         std::set<std::string> privs;
3547         m_script->getAuth(player->getName(), NULL, &privs);
3548
3549         std::ostringstream os(std::ios_base::binary);
3550         writeU16(os, TOCLIENT_PRIVILEGES);
3551         writeU16(os, privs.size());
3552         for(std::set<std::string>::const_iterator i = privs.begin();
3553                         i != privs.end(); i++){
3554                 os<<serializeString(*i);
3555         }
3556
3557         // Make data buffer
3558         std::string s = os.str();
3559         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3560         // Send as reliable
3561         m_clients.send(peer_id, 0, data, true);
3562 }
3563
3564 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3565 {
3566         Player *player = m_env->getPlayer(peer_id);
3567         assert(player);
3568         if(player->peer_id == PEER_ID_INEXISTENT)
3569                 return;
3570
3571         std::ostringstream os(std::ios_base::binary);
3572         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3573         os<<serializeLongString(player->inventory_formspec);
3574
3575         // Make data buffer
3576         std::string s = os.str();
3577         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3578         // Send as reliable
3579         m_clients.send(peer_id, 0, data, true);
3580 }
3581
3582 s32 Server::playSound(const SimpleSoundSpec &spec,
3583                 const ServerSoundParams &params)
3584 {
3585         // Find out initial position of sound
3586         bool pos_exists = false;
3587         v3f pos = params.getPos(m_env, &pos_exists);
3588         // If position is not found while it should be, cancel sound
3589         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3590                 return -1;
3591
3592         // Filter destination clients
3593         std::list<u16> dst_clients;
3594         if(params.to_player != "")
3595         {
3596                 Player *player = m_env->getPlayer(params.to_player.c_str());
3597                 if(!player){
3598                         infostream<<"Server::playSound: Player \""<<params.to_player
3599                                         <<"\" not found"<<std::endl;
3600                         return -1;
3601                 }
3602                 if(player->peer_id == PEER_ID_INEXISTENT){
3603                         infostream<<"Server::playSound: Player \""<<params.to_player
3604                                         <<"\" not connected"<<std::endl;
3605                         return -1;
3606                 }
3607                 dst_clients.push_back(player->peer_id);
3608         }
3609         else
3610         {
3611                 std::list<u16> clients = m_clients.getClientIDs();
3612
3613                 for(std::list<u16>::iterator
3614                                 i = clients.begin(); i != clients.end(); ++i)
3615                 {
3616                         Player *player = m_env->getPlayer(*i);
3617                         if(!player)
3618                                 continue;
3619                         if(pos_exists){
3620                                 if(player->getPosition().getDistanceFrom(pos) >
3621                                                 params.max_hear_distance)
3622                                         continue;
3623                         }
3624                         dst_clients.push_back(*i);
3625                 }
3626         }
3627         if(dst_clients.size() == 0)
3628                 return -1;
3629
3630         // Create the sound
3631         s32 id = m_next_sound_id++;
3632         // The sound will exist as a reference in m_playing_sounds
3633         m_playing_sounds[id] = ServerPlayingSound();
3634         ServerPlayingSound &psound = m_playing_sounds[id];
3635         psound.params = params;
3636         for(std::list<u16>::iterator i = dst_clients.begin();
3637                         i != dst_clients.end(); i++)
3638                 psound.clients.insert(*i);
3639         // Create packet
3640         std::ostringstream os(std::ios_base::binary);
3641         writeU16(os, TOCLIENT_PLAY_SOUND);
3642         writeS32(os, id);
3643         os<<serializeString(spec.name);
3644         writeF1000(os, spec.gain * params.gain);
3645         writeU8(os, params.type);
3646         writeV3F1000(os, pos);
3647         writeU16(os, params.object);
3648         writeU8(os, params.loop);
3649         // Make data buffer
3650         std::string s = os.str();
3651         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3652         // Send
3653         for(std::list<u16>::iterator i = dst_clients.begin();
3654                         i != dst_clients.end(); i++){
3655                 // Send as reliable
3656                 m_clients.send(*i, 0, data, true);
3657         }
3658         return id;
3659 }
3660 void Server::stopSound(s32 handle)
3661 {
3662         // Get sound reference
3663         std::map<s32, ServerPlayingSound>::iterator i =
3664                         m_playing_sounds.find(handle);
3665         if(i == m_playing_sounds.end())
3666                 return;
3667         ServerPlayingSound &psound = i->second;
3668         // Create packet
3669         std::ostringstream os(std::ios_base::binary);
3670         writeU16(os, TOCLIENT_STOP_SOUND);
3671         writeS32(os, handle);
3672         // Make data buffer
3673         std::string s = os.str();
3674         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3675         // Send
3676         for(std::set<u16>::iterator i = psound.clients.begin();
3677                         i != psound.clients.end(); i++){
3678                 // Send as reliable
3679                 m_clients.send(*i, 0, data, true);
3680         }
3681         // Remove sound reference
3682         m_playing_sounds.erase(i);
3683 }
3684
3685 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3686         std::list<u16> *far_players, float far_d_nodes)
3687 {
3688         float maxd = far_d_nodes*BS;
3689         v3f p_f = intToFloat(p, BS);
3690
3691         // Create packet
3692         u32 replysize = 8;
3693         SharedBuffer<u8> reply(replysize);
3694         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3695         writeS16(&reply[2], p.X);
3696         writeS16(&reply[4], p.Y);
3697         writeS16(&reply[6], p.Z);
3698
3699         std::list<u16> clients = m_clients.getClientIDs();
3700         for(std::list<u16>::iterator
3701                 i = clients.begin();
3702                 i != clients.end(); ++i)
3703         {
3704                 if(far_players)
3705                 {
3706                         // Get player
3707                         Player *player = m_env->getPlayer(*i);
3708                         if(player)
3709                         {
3710                                 // If player is far away, only set modified blocks not sent
3711                                 v3f player_pos = player->getPosition();
3712                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3713                                 {
3714                                         far_players->push_back(*i);
3715                                         continue;
3716                                 }
3717                         }
3718                 }
3719
3720                 // Send as reliable
3721                 m_clients.send(*i, 0, reply, true);
3722         }
3723 }
3724
3725 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3726                 std::list<u16> *far_players, float far_d_nodes,
3727                 bool remove_metadata)
3728 {
3729         float maxd = far_d_nodes*BS;
3730         v3f p_f = intToFloat(p, BS);
3731
3732         std::list<u16> clients = m_clients.getClientIDs();
3733                 for(std::list<u16>::iterator
3734                         i = clients.begin();
3735                         i != clients.end(); ++i)
3736                 {
3737
3738                 if(far_players)
3739                 {
3740                         // Get player
3741                         Player *player = m_env->getPlayer(*i);
3742                         if(player)
3743                         {
3744                                 // If player is far away, only set modified blocks not sent
3745                                 v3f player_pos = player->getPosition();
3746                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3747                                 {
3748                                         far_players->push_back(*i);
3749                                         continue;
3750                                 }
3751                         }
3752                 }
3753                 SharedBuffer<u8> reply(0);
3754                 m_clients.Lock();
3755                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
3756                 if (client != 0)
3757                 {
3758                         // Create packet
3759                         u32 replysize = 9 + MapNode::serializedLength(client->serialization_version);
3760                         reply = SharedBuffer<u8>(replysize);
3761                         writeU16(&reply[0], TOCLIENT_ADDNODE);
3762                         writeS16(&reply[2], p.X);
3763                         writeS16(&reply[4], p.Y);
3764                         writeS16(&reply[6], p.Z);
3765                         n.serialize(&reply[8], client->serialization_version);
3766                         u32 index = 8 + MapNode::serializedLength(client->serialization_version);
3767                         writeU8(&reply[index], remove_metadata ? 0 : 1);
3768
3769                         if (!remove_metadata) {
3770                                 if (client->net_proto_version <= 21) {
3771                                         // Old clients always clear metadata; fix it
3772                                         // by sending the full block again.
3773                                         client->SetBlockNotSent(p);
3774                                 }
3775                         }
3776                 }
3777                 m_clients.Unlock();
3778
3779                 // Send as reliable
3780                 if (reply.getSize() > 0)
3781                         m_clients.send(*i, 0, reply, true);
3782         }
3783 }
3784
3785 void Server::setBlockNotSent(v3s16 p)
3786 {
3787         std::list<u16> clients = m_clients.getClientIDs();
3788         m_clients.Lock();
3789         for(std::list<u16>::iterator
3790                 i = clients.begin();
3791                 i != clients.end(); ++i)
3792         {
3793                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
3794                 client->SetBlockNotSent(p);
3795         }
3796         m_clients.Unlock();
3797 }
3798
3799 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
3800 {
3801         DSTACK(__FUNCTION_NAME);
3802
3803         v3s16 p = block->getPos();
3804
3805 #if 0
3806         // Analyze it a bit
3807         bool completely_air = true;
3808         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3809         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3810         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3811         {
3812                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3813                 {
3814                         completely_air = false;
3815                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3816                 }
3817         }
3818
3819         // Print result
3820         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3821         if(completely_air)
3822                 infostream<<"[completely air] ";
3823         infostream<<std::endl;
3824 #endif
3825
3826         /*
3827                 Create a packet with the block in the right format
3828         */
3829
3830         std::ostringstream os(std::ios_base::binary);
3831         block->serialize(os, ver, false);
3832         block->serializeNetworkSpecific(os, net_proto_version);
3833         std::string s = os.str();
3834         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3835
3836         u32 replysize = 8 + blockdata.getSize();
3837         SharedBuffer<u8> reply(replysize);
3838         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3839         writeS16(&reply[2], p.X);
3840         writeS16(&reply[4], p.Y);
3841         writeS16(&reply[6], p.Z);
3842         memcpy(&reply[8], *blockdata, blockdata.getSize());
3843
3844         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3845                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3846
3847         /*
3848                 Send packet
3849         */
3850         m_clients.send(peer_id, 2, reply, true);
3851 }
3852
3853 void Server::SendBlocks(float dtime)
3854 {
3855         DSTACK(__FUNCTION_NAME);
3856
3857         JMutexAutoLock envlock(m_env_mutex);
3858         //TODO check if one big lock could be faster then multiple small ones
3859
3860         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
3861
3862         std::vector<PrioritySortedBlockTransfer> queue;
3863
3864         s32 total_sending = 0;
3865
3866         {
3867                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3868
3869                 std::list<u16> clients = m_clients.getClientIDs();
3870
3871                 m_clients.Lock();
3872                 for(std::list<u16>::iterator
3873                         i = clients.begin();
3874                         i != clients.end(); ++i)
3875                 {
3876                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i,Active);
3877
3878                         if (client == NULL)
3879                                 return;
3880
3881                         total_sending += client->SendingCount();
3882                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
3883                 }
3884                 m_clients.Unlock();
3885         }
3886
3887         // Sort.
3888         // Lowest priority number comes first.
3889         // Lowest is most important.
3890         std::sort(queue.begin(), queue.end());
3891
3892         m_clients.Lock();
3893         for(u32 i=0; i<queue.size(); i++)
3894         {
3895                 //TODO: Calculate limit dynamically
3896                 if(total_sending >= g_settings->getS32
3897                                 ("max_simultaneous_block_sends_server_total"))
3898                         break;
3899
3900                 PrioritySortedBlockTransfer q = queue[i];
3901
3902                 MapBlock *block = NULL;
3903                 try
3904                 {
3905                         block = m_env->getMap().getBlockNoCreate(q.pos);
3906                 }
3907                 catch(InvalidPositionException &e)
3908                 {
3909                         continue;
3910                 }
3911
3912                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id,Active);
3913
3914                 if(!client)
3915                         continue;
3916
3917                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
3918
3919                 client->SentBlock(q.pos);
3920                 total_sending++;
3921         }
3922         m_clients.Unlock();
3923 }
3924
3925 void Server::fillMediaCache()
3926 {
3927         DSTACK(__FUNCTION_NAME);
3928
3929         infostream<<"Server: Calculating media file checksums"<<std::endl;
3930
3931         // Collect all media file paths
3932         std::list<std::string> paths;
3933         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3934                         i != m_mods.end(); i++){
3935                 const ModSpec &mod = *i;
3936                 paths.push_back(mod.path + DIR_DELIM + "textures");
3937                 paths.push_back(mod.path + DIR_DELIM + "sounds");
3938                 paths.push_back(mod.path + DIR_DELIM + "media");
3939                 paths.push_back(mod.path + DIR_DELIM + "models");
3940         }
3941         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
3942
3943         // Collect media file information from paths into cache
3944         for(std::list<std::string>::iterator i = paths.begin();
3945                         i != paths.end(); i++)
3946         {
3947                 std::string mediapath = *i;
3948                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
3949                 for(u32 j=0; j<dirlist.size(); j++){
3950                         if(dirlist[j].dir) // Ignode dirs
3951                                 continue;
3952                         std::string filename = dirlist[j].name;
3953                         // If name contains illegal characters, ignore the file
3954                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
3955                                 infostream<<"Server: ignoring illegal file name: \""
3956                                                 <<filename<<"\""<<std::endl;
3957                                 continue;
3958                         }
3959                         // If name is not in a supported format, ignore it
3960                         const char *supported_ext[] = {
3961                                 ".png", ".jpg", ".bmp", ".tga",
3962                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
3963                                 ".ogg",
3964                                 ".x", ".b3d", ".md2", ".obj",
3965                                 NULL
3966                         };
3967                         if(removeStringEnd(filename, supported_ext) == ""){
3968                                 infostream<<"Server: ignoring unsupported file extension: \""
3969                                                 <<filename<<"\""<<std::endl;
3970                                 continue;
3971                         }
3972                         // Ok, attempt to load the file and add to cache
3973                         std::string filepath = mediapath + DIR_DELIM + filename;
3974                         // Read data
3975                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
3976                         if(fis.good() == false){
3977                                 errorstream<<"Server::fillMediaCache(): Could not open \""
3978                                                 <<filename<<"\" for reading"<<std::endl;
3979                                 continue;
3980                         }
3981                         std::ostringstream tmp_os(std::ios_base::binary);
3982                         bool bad = false;
3983                         for(;;){
3984                                 char buf[1024];
3985                                 fis.read(buf, 1024);
3986                                 std::streamsize len = fis.gcount();
3987                                 tmp_os.write(buf, len);
3988                                 if(fis.eof())
3989                                         break;
3990                                 if(!fis.good()){
3991                                         bad = true;
3992                                         break;
3993                                 }
3994                         }
3995                         if(bad){
3996                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
3997                                                 <<filename<<"\""<<std::endl;
3998                                 continue;
3999                         }
4000                         if(tmp_os.str().length() == 0){
4001                                 errorstream<<"Server::fillMediaCache(): Empty file \""
4002                                                 <<filepath<<"\""<<std::endl;
4003                                 continue;
4004                         }
4005
4006                         SHA1 sha1;
4007                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
4008
4009                         unsigned char *digest = sha1.getDigest();
4010                         std::string sha1_base64 = base64_encode(digest, 20);
4011                         std::string sha1_hex = hex_encode((char*)digest, 20);
4012                         free(digest);
4013
4014                         // Put in list
4015                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4016                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4017                 }
4018         }
4019 }
4020
4021 struct SendableMediaAnnouncement
4022 {
4023         std::string name;
4024         std::string sha1_digest;
4025
4026         SendableMediaAnnouncement(const std::string &name_="",
4027                                   const std::string &sha1_digest_=""):
4028                 name(name_),
4029                 sha1_digest(sha1_digest_)
4030         {}
4031 };
4032
4033 void Server::sendMediaAnnouncement(u16 peer_id)
4034 {
4035         DSTACK(__FUNCTION_NAME);
4036
4037         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4038                         <<std::endl;
4039
4040         std::list<SendableMediaAnnouncement> file_announcements;
4041
4042         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4043                         i != m_media.end(); i++){
4044                 // Put in list
4045                 file_announcements.push_back(
4046                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4047         }
4048
4049         // Make packet
4050         std::ostringstream os(std::ios_base::binary);
4051
4052         /*
4053                 u16 command
4054                 u32 number of files
4055                 for each texture {
4056                         u16 length of name
4057                         string name
4058                         u16 length of sha1_digest
4059                         string sha1_digest
4060                 }
4061         */
4062
4063         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4064         writeU16(os, file_announcements.size());
4065
4066         for(std::list<SendableMediaAnnouncement>::iterator
4067                         j = file_announcements.begin();
4068                         j != file_announcements.end(); ++j){
4069                 os<<serializeString(j->name);
4070                 os<<serializeString(j->sha1_digest);
4071         }
4072         os<<serializeString(g_settings->get("remote_media"));
4073
4074         // Make data buffer
4075         std::string s = os.str();
4076         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4077
4078         // Send as reliable
4079         m_clients.send(peer_id, 0, data, true);
4080 }
4081
4082 struct SendableMedia
4083 {
4084         std::string name;
4085         std::string path;
4086         std::string data;
4087
4088         SendableMedia(const std::string &name_="", const std::string &path_="",
4089                       const std::string &data_=""):
4090                 name(name_),
4091                 path(path_),
4092                 data(data_)
4093         {}
4094 };
4095
4096 void Server::sendRequestedMedia(u16 peer_id,
4097                 const std::list<std::string> &tosend)
4098 {
4099         DSTACK(__FUNCTION_NAME);
4100
4101         verbosestream<<"Server::sendRequestedMedia(): "
4102                         <<"Sending files to client"<<std::endl;
4103
4104         /* Read files */
4105
4106         // Put 5kB in one bunch (this is not accurate)
4107         u32 bytes_per_bunch = 5000;
4108
4109         std::vector< std::list<SendableMedia> > file_bunches;
4110         file_bunches.push_back(std::list<SendableMedia>());
4111
4112         u32 file_size_bunch_total = 0;
4113
4114         for(std::list<std::string>::const_iterator i = tosend.begin();
4115                         i != tosend.end(); ++i)
4116         {
4117                 const std::string &name = *i;
4118
4119                 if(m_media.find(name) == m_media.end()){
4120                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4121                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
4122                         continue;
4123                 }
4124
4125                 //TODO get path + name
4126                 std::string tpath = m_media[name].path;
4127
4128                 // Read data
4129                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4130                 if(fis.good() == false){
4131                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4132                                         <<tpath<<"\" for reading"<<std::endl;
4133                         continue;
4134                 }
4135                 std::ostringstream tmp_os(std::ios_base::binary);
4136                 bool bad = false;
4137                 for(;;){
4138                         char buf[1024];
4139                         fis.read(buf, 1024);
4140                         std::streamsize len = fis.gcount();
4141                         tmp_os.write(buf, len);
4142                         file_size_bunch_total += len;
4143                         if(fis.eof())
4144                                 break;
4145                         if(!fis.good()){
4146                                 bad = true;
4147                                 break;
4148                         }
4149                 }
4150                 if(bad){
4151                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4152                                         <<name<<"\""<<std::endl;
4153                         continue;
4154                 }
4155                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4156                                 <<tname<<"\""<<std::endl;*/
4157                 // Put in list
4158                 file_bunches[file_bunches.size()-1].push_back(
4159                                 SendableMedia(name, tpath, tmp_os.str()));
4160
4161                 // Start next bunch if got enough data
4162                 if(file_size_bunch_total >= bytes_per_bunch){
4163                         file_bunches.push_back(std::list<SendableMedia>());
4164                         file_size_bunch_total = 0;
4165                 }
4166
4167         }
4168
4169         /* Create and send packets */
4170
4171         u32 num_bunches = file_bunches.size();
4172         for(u32 i=0; i<num_bunches; i++)
4173         {
4174                 std::ostringstream os(std::ios_base::binary);
4175
4176                 /*
4177                         u16 command
4178                         u16 total number of texture bunches
4179                         u16 index of this bunch
4180                         u32 number of files in this bunch
4181                         for each file {
4182                                 u16 length of name
4183                                 string name
4184                                 u32 length of data
4185                                 data
4186                         }
4187                 */
4188
4189                 writeU16(os, TOCLIENT_MEDIA);
4190                 writeU16(os, num_bunches);
4191                 writeU16(os, i);
4192                 writeU32(os, file_bunches[i].size());
4193
4194                 for(std::list<SendableMedia>::iterator
4195                                 j = file_bunches[i].begin();
4196                                 j != file_bunches[i].end(); ++j){
4197                         os<<serializeString(j->name);
4198                         os<<serializeLongString(j->data);
4199                 }
4200
4201                 // Make data buffer
4202                 std::string s = os.str();
4203                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4204                                 <<i<<"/"<<num_bunches
4205                                 <<" files="<<file_bunches[i].size()
4206                                 <<" size=" <<s.size()<<std::endl;
4207                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4208                 // Send as reliable
4209                 m_clients.send(peer_id, 2, data, true);
4210         }
4211 }
4212
4213 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4214 {
4215         if(m_detached_inventories.count(name) == 0){
4216                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4217                 return;
4218         }
4219         Inventory *inv = m_detached_inventories[name];
4220
4221         std::ostringstream os(std::ios_base::binary);
4222         writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4223         os<<serializeString(name);
4224         inv->serialize(os);
4225
4226         // Make data buffer
4227         std::string s = os.str();
4228         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4229
4230         if (peer_id != PEER_ID_INEXISTENT)
4231         {
4232                 // Send as reliable
4233                 m_clients.send(peer_id, 0, data, true);
4234         }
4235         else
4236         {
4237                 m_clients.sendToAll(0,data,true);
4238         }
4239 }
4240
4241 void Server::sendDetachedInventories(u16 peer_id)
4242 {
4243         DSTACK(__FUNCTION_NAME);
4244
4245         for(std::map<std::string, Inventory*>::iterator
4246                         i = m_detached_inventories.begin();
4247                         i != m_detached_inventories.end(); i++){
4248                 const std::string &name = i->first;
4249                 //Inventory *inv = i->second;
4250                 sendDetachedInventory(name, peer_id);
4251         }
4252 }
4253
4254 /*
4255         Something random
4256 */
4257
4258 void Server::DiePlayer(u16 peer_id)
4259 {
4260         DSTACK(__FUNCTION_NAME);
4261
4262         PlayerSAO *playersao = getPlayerSAO(peer_id);
4263         assert(playersao);
4264
4265         infostream<<"Server::DiePlayer(): Player "
4266                         <<playersao->getPlayer()->getName()
4267                         <<" dies"<<std::endl;
4268
4269         playersao->setHP(0);
4270
4271         // Trigger scripted stuff
4272         m_script->on_dieplayer(playersao);
4273
4274         SendPlayerHP(peer_id);
4275         SendDeathscreen(peer_id, false, v3f(0,0,0));
4276 }
4277
4278 void Server::RespawnPlayer(u16 peer_id)
4279 {
4280         DSTACK(__FUNCTION_NAME);
4281
4282         PlayerSAO *playersao = getPlayerSAO(peer_id);
4283         assert(playersao);
4284
4285         infostream<<"Server::RespawnPlayer(): Player "
4286                         <<playersao->getPlayer()->getName()
4287                         <<" respawns"<<std::endl;
4288
4289         playersao->setHP(PLAYER_MAX_HP);
4290
4291         bool repositioned = m_script->on_respawnplayer(playersao);
4292         if(!repositioned){
4293                 v3f pos = findSpawnPos(m_env->getServerMap());
4294                 playersao->setPos(pos);
4295         }
4296 }
4297
4298 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
4299 {
4300         DSTACK(__FUNCTION_NAME);
4301
4302         SendAccessDenied(peer_id, reason);
4303         m_clients.event(peer_id,SetDenied);
4304         m_con.DisconnectPeer(peer_id);
4305 }
4306
4307 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
4308 {
4309         DSTACK(__FUNCTION_NAME);
4310         std::wstring message;
4311         {
4312                 /*
4313                         Clear references to playing sounds
4314                 */
4315                 for(std::map<s32, ServerPlayingSound>::iterator
4316                                 i = m_playing_sounds.begin();
4317                                 i != m_playing_sounds.end();)
4318                 {
4319                         ServerPlayingSound &psound = i->second;
4320                         psound.clients.erase(peer_id);
4321                         if(psound.clients.size() == 0)
4322                                 m_playing_sounds.erase(i++);
4323                         else
4324                                 i++;
4325                 }
4326
4327                 Player *player = m_env->getPlayer(peer_id);
4328
4329                 // Collect information about leaving in chat
4330                 {
4331                         if(player != NULL && reason != CDR_DENY)
4332                         {
4333                                 std::wstring name = narrow_to_wide(player->getName());
4334                                 message += L"*** ";
4335                                 message += name;
4336                                 message += L" left the game.";
4337                                 if(reason == CDR_TIMEOUT)
4338                                         message += L" (timed out)";
4339                         }
4340                 }
4341
4342                 /* Run scripts and remove from environment */
4343                 {
4344                         if(player != NULL)
4345                         {
4346                                 PlayerSAO *playersao = player->getPlayerSAO();
4347                                 assert(playersao);
4348
4349                                 m_script->on_leaveplayer(playersao);
4350
4351                                 playersao->disconnected();
4352                         }
4353                 }
4354
4355                 /*
4356                         Print out action
4357                 */
4358                 {
4359                         if(player != NULL && reason != CDR_DENY)
4360                         {
4361                                 std::ostringstream os(std::ios_base::binary);
4362                                 std::list<u16> clients = m_clients.getClientIDs();
4363
4364                                 for(std::list<u16>::iterator
4365                                         i = clients.begin();
4366                                         i != clients.end(); ++i)
4367                                 {
4368                                         // Get player
4369                                         Player *player = m_env->getPlayer(*i);
4370                                         if(!player)
4371                                                 continue;
4372                                         // Get name of player
4373                                         os<<player->getName()<<" ";
4374                                 }
4375
4376                                 actionstream<<player->getName()<<" "
4377                                                 <<(reason==CDR_TIMEOUT?"times out.":"leaves game.")
4378                                                 <<" List of players: "<<os.str()<<std::endl;
4379                         }
4380                 }
4381                 {
4382                         JMutexAutoLock env_lock(m_env_mutex);
4383                         m_clients.DeleteClient(peer_id);
4384                 }
4385         }
4386
4387         // Send leave chat message to all remaining clients
4388         if(message.length() != 0)
4389                 SendChatMessage(PEER_ID_INEXISTENT,message);
4390 }
4391
4392 void Server::UpdateCrafting(u16 peer_id)
4393 {
4394         DSTACK(__FUNCTION_NAME);
4395
4396         Player* player = m_env->getPlayer(peer_id);
4397         assert(player);
4398
4399         // Get a preview for crafting
4400         ItemStack preview;
4401         InventoryLocation loc;
4402         loc.setPlayer(player->getName());
4403         getCraftingResult(&player->inventory, preview, false, this);
4404         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
4405
4406         // Put the new preview in
4407         InventoryList *plist = player->inventory.getList("craftpreview");
4408         assert(plist);
4409         assert(plist->getSize() >= 1);
4410         plist->changeItem(0, preview);
4411 }
4412
4413 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
4414 {
4415         RemoteClient *client = getClientNoEx(peer_id,state_min);
4416         if(!client)
4417                 throw ClientNotFoundException("Client not found");
4418
4419         return client;
4420 }
4421 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
4422 {
4423         return m_clients.getClientNoEx(peer_id, state_min);
4424 }
4425
4426 std::string Server::getPlayerName(u16 peer_id)
4427 {
4428         Player *player = m_env->getPlayer(peer_id);
4429         if(player == NULL)
4430                 return "[id="+itos(peer_id)+"]";
4431         return player->getName();
4432 }
4433
4434 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
4435 {
4436         Player *player = m_env->getPlayer(peer_id);
4437         if(player == NULL)
4438                 return NULL;
4439         return player->getPlayerSAO();
4440 }
4441
4442 std::wstring Server::getStatusString()
4443 {
4444         std::wostringstream os(std::ios_base::binary);
4445         os<<L"# Server: ";
4446         // Version
4447         os<<L"version="<<narrow_to_wide(minetest_version_simple);
4448         // Uptime
4449         os<<L", uptime="<<m_uptime.get();
4450         // Max lag estimate
4451         os<<L", max_lag="<<m_env->getMaxLagEstimate();
4452         // Information about clients
4453         bool first = true;
4454         os<<L", clients={";
4455         std::list<u16> clients = m_clients.getClientIDs();
4456         for(std::list<u16>::iterator i = clients.begin();
4457                 i != clients.end(); ++i)
4458         {
4459                 // Get player
4460                 Player *player = m_env->getPlayer(*i);
4461                 // Get name of player
4462                 std::wstring name = L"unknown";
4463                 if(player != NULL)
4464                         name = narrow_to_wide(player->getName());
4465                 // Add name to information string
4466                 if(!first)
4467                         os<<L",";
4468                 else
4469                         first = false;
4470                 os<<name;
4471         }
4472         os<<L"}";
4473         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4474                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4475         if(g_settings->get("motd") != "")
4476                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4477         return os.str();
4478 }
4479
4480 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4481 {
4482         std::set<std::string> privs;
4483         m_script->getAuth(name, NULL, &privs);
4484         return privs;
4485 }
4486
4487 bool Server::checkPriv(const std::string &name, const std::string &priv)
4488 {
4489         std::set<std::string> privs = getPlayerEffectivePrivs(name);
4490         return (privs.count(priv) != 0);
4491 }
4492
4493 void Server::reportPrivsModified(const std::string &name)
4494 {
4495         if(name == ""){
4496                 std::list<u16> clients = m_clients.getClientIDs();
4497                 for(std::list<u16>::iterator
4498                                 i = clients.begin();
4499                                 i != clients.end(); ++i){
4500                         Player *player = m_env->getPlayer(*i);
4501                         reportPrivsModified(player->getName());
4502                 }
4503         } else {
4504                 Player *player = m_env->getPlayer(name.c_str());
4505                 if(!player)
4506                         return;
4507                 SendPlayerPrivileges(player->peer_id);
4508                 PlayerSAO *sao = player->getPlayerSAO();
4509                 if(!sao)
4510                         return;
4511                 sao->updatePrivileges(
4512                                 getPlayerEffectivePrivs(name),
4513                                 isSingleplayer());
4514         }
4515 }
4516
4517 void Server::reportInventoryFormspecModified(const std::string &name)
4518 {
4519         Player *player = m_env->getPlayer(name.c_str());
4520         if(!player)
4521                 return;
4522         SendPlayerInventoryFormspec(player->peer_id);
4523 }
4524
4525 void Server::setIpBanned(const std::string &ip, const std::string &name)
4526 {
4527         m_banmanager->add(ip, name);
4528 }
4529
4530 void Server::unsetIpBanned(const std::string &ip_or_name)
4531 {
4532         m_banmanager->remove(ip_or_name);
4533 }
4534
4535 std::string Server::getBanDescription(const std::string &ip_or_name)
4536 {
4537         return m_banmanager->getBanDescription(ip_or_name);
4538 }
4539
4540 void Server::notifyPlayer(const char *name, const std::wstring &msg)
4541 {
4542         Player *player = m_env->getPlayer(name);
4543         if(!player)
4544                 return;
4545
4546         if (player->peer_id == PEER_ID_INEXISTENT)
4547                 return;
4548
4549         SendChatMessage(player->peer_id, msg);
4550 }
4551
4552 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4553 {
4554         Player *player = m_env->getPlayer(playername);
4555
4556         if(!player)
4557         {
4558                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4559                 return false;
4560         }
4561
4562         SendShowFormspecMessage(player->peer_id, formspec, formname);
4563         return true;
4564 }
4565
4566 u32 Server::hudAdd(Player *player, HudElement *form) {
4567         if (!player)
4568                 return -1;
4569         
4570         u32 id = player->addHud(form);
4571
4572         SendHUDAdd(player->peer_id, id, form);
4573
4574         return id;
4575 }
4576
4577 bool Server::hudRemove(Player *player, u32 id) {
4578         if (!player)
4579                 return false;
4580
4581         HudElement* todel = player->removeHud(id);
4582
4583         if (!todel)
4584                 return false;
4585         
4586         delete todel;
4587
4588         SendHUDRemove(player->peer_id, id);
4589         return true;
4590 }
4591
4592 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
4593         if (!player)
4594                 return false;
4595
4596         SendHUDChange(player->peer_id, id, stat, data);
4597         return true;
4598 }
4599
4600 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
4601         if (!player)
4602                 return false;
4603
4604         SendHUDSetFlags(player->peer_id, flags, mask);
4605         player->hud_flags = flags;
4606
4607         m_script->player_event(player->getPlayerSAO(),"hud_changed");
4608         return true;
4609 }
4610
4611 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
4612         if (!player)
4613                 return false;
4614         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
4615                 return false;
4616
4617         std::ostringstream os(std::ios::binary);
4618         writeS32(os, hotbar_itemcount);
4619         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
4620         return true;
4621 }
4622
4623 void Server::hudSetHotbarImage(Player *player, std::string name) {
4624         if (!player)
4625                 return;
4626
4627         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
4628 }
4629
4630 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
4631         if (!player)
4632                 return;
4633
4634         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
4635 }
4636
4637 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
4638 {
4639         if (!player)
4640                 return false;
4641
4642         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
4643         return true;
4644 }
4645
4646 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
4647 {
4648         if (!player)
4649                 return false;
4650
4651         SendEyeOffset(player->peer_id, first, third);
4652         return true;
4653 }
4654
4655 bool Server::setSky(Player *player, const video::SColor &bgcolor,
4656                 const std::string &type, const std::vector<std::string> &params)
4657 {
4658         if (!player)
4659                 return false;
4660
4661         SendSetSky(player->peer_id, bgcolor, type, params);
4662         return true;
4663 }
4664
4665 bool Server::overrideDayNightRatio(Player *player, bool do_override,
4666                 float ratio)
4667 {
4668         if (!player)
4669                 return false;
4670
4671         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
4672         return true;
4673 }
4674
4675 void Server::notifyPlayers(const std::wstring &msg)
4676 {
4677         SendChatMessage(PEER_ID_INEXISTENT,msg);
4678 }
4679
4680 void Server::spawnParticle(const char *playername, v3f pos,
4681                 v3f velocity, v3f acceleration,
4682                 float expirationtime, float size, bool
4683                 collisiondetection, bool vertical, std::string texture)
4684 {
4685         Player *player = m_env->getPlayer(playername);
4686         if(!player)
4687                 return;
4688         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
4689                         expirationtime, size, collisiondetection, vertical, texture);
4690 }
4691
4692 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
4693                 float expirationtime, float size,
4694                 bool collisiondetection, bool vertical, std::string texture)
4695 {
4696         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
4697                         expirationtime, size, collisiondetection, vertical, texture);
4698 }
4699
4700 u32 Server::addParticleSpawner(const char *playername,
4701                 u16 amount, float spawntime,
4702                 v3f minpos, v3f maxpos,
4703                 v3f minvel, v3f maxvel,
4704                 v3f minacc, v3f maxacc,
4705                 float minexptime, float maxexptime,
4706                 float minsize, float maxsize,
4707                 bool collisiondetection, bool vertical, std::string texture)
4708 {
4709         Player *player = m_env->getPlayer(playername);
4710         if(!player)
4711                 return -1;
4712
4713         u32 id = 0;
4714         for(;;) // look for unused particlespawner id
4715         {
4716                 id++;
4717                 if (std::find(m_particlespawner_ids.begin(),
4718                                 m_particlespawner_ids.end(), id)
4719                                 == m_particlespawner_ids.end())
4720                 {
4721                         m_particlespawner_ids.push_back(id);
4722                         break;
4723                 }
4724         }
4725
4726         SendAddParticleSpawner(player->peer_id, amount, spawntime,
4727                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4728                 minexptime, maxexptime, minsize, maxsize,
4729                 collisiondetection, vertical, texture, id);
4730
4731         return id;
4732 }
4733
4734 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
4735                 v3f minpos, v3f maxpos,
4736                 v3f minvel, v3f maxvel,
4737                 v3f minacc, v3f maxacc,
4738                 float minexptime, float maxexptime,
4739                 float minsize, float maxsize,
4740                 bool collisiondetection, bool vertical, std::string texture)
4741 {
4742         u32 id = 0;
4743         for(;;) // look for unused particlespawner id
4744         {
4745                 id++;
4746                 if (std::find(m_particlespawner_ids.begin(),
4747                                 m_particlespawner_ids.end(), id)
4748                                 == m_particlespawner_ids.end())
4749                 {
4750                         m_particlespawner_ids.push_back(id);
4751                         break;
4752                 }
4753         }
4754
4755         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
4756                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4757                 minexptime, maxexptime, minsize, maxsize,
4758                 collisiondetection, vertical, texture, id);
4759
4760         return id;
4761 }
4762
4763 void Server::deleteParticleSpawner(const char *playername, u32 id)
4764 {
4765         Player *player = m_env->getPlayer(playername);
4766         if(!player)
4767                 return;
4768
4769         m_particlespawner_ids.erase(
4770                         std::remove(m_particlespawner_ids.begin(),
4771                         m_particlespawner_ids.end(), id),
4772                         m_particlespawner_ids.end());
4773         SendDeleteParticleSpawner(player->peer_id, id);
4774 }
4775
4776 void Server::deleteParticleSpawnerAll(u32 id)
4777 {
4778         m_particlespawner_ids.erase(
4779                         std::remove(m_particlespawner_ids.begin(),
4780                         m_particlespawner_ids.end(), id),
4781                         m_particlespawner_ids.end());
4782         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
4783 }
4784
4785 Inventory* Server::createDetachedInventory(const std::string &name)
4786 {
4787         if(m_detached_inventories.count(name) > 0){
4788                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
4789                 delete m_detached_inventories[name];
4790         } else {
4791                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
4792         }
4793         Inventory *inv = new Inventory(m_itemdef);
4794         assert(inv);
4795         m_detached_inventories[name] = inv;
4796         //TODO find a better way to do this
4797         sendDetachedInventory(name,PEER_ID_INEXISTENT);
4798         return inv;
4799 }
4800
4801 class BoolScopeSet
4802 {
4803 public:
4804         BoolScopeSet(bool *dst, bool val):
4805                 m_dst(dst)
4806         {
4807                 m_orig_state = *m_dst;
4808                 *m_dst = val;
4809         }
4810         ~BoolScopeSet()
4811         {
4812                 *m_dst = m_orig_state;
4813         }
4814 private:
4815         bool *m_dst;
4816         bool m_orig_state;
4817 };
4818
4819 // actions: time-reversed list
4820 // Return value: success/failure
4821 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
4822                 std::list<std::string> *log)
4823 {
4824         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
4825         ServerMap *map = (ServerMap*)(&m_env->getMap());
4826         // Disable rollback report sink while reverting
4827         BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
4828
4829         // Fail if no actions to handle
4830         if(actions.empty()){
4831                 log->push_back("Nothing to do.");
4832                 return false;
4833         }
4834
4835         int num_tried = 0;
4836         int num_failed = 0;
4837
4838         for(std::list<RollbackAction>::const_iterator
4839                         i = actions.begin();
4840                         i != actions.end(); i++)
4841         {
4842                 const RollbackAction &action = *i;
4843                 num_tried++;
4844                 bool success = action.applyRevert(map, this, this);
4845                 if(!success){
4846                         num_failed++;
4847                         std::ostringstream os;
4848                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
4849                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4850                         if(log)
4851                                 log->push_back(os.str());
4852                 }else{
4853                         std::ostringstream os;
4854                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
4855                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4856                         if(log)
4857                                 log->push_back(os.str());
4858                 }
4859         }
4860
4861         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
4862                         <<" failed"<<std::endl;
4863
4864         // Call it done if less than half failed
4865         return num_failed <= num_tried/2;
4866 }
4867
4868 // IGameDef interface
4869 // Under envlock
4870 IItemDefManager* Server::getItemDefManager()
4871 {
4872         return m_itemdef;
4873 }
4874 INodeDefManager* Server::getNodeDefManager()
4875 {
4876         return m_nodedef;
4877 }
4878 ICraftDefManager* Server::getCraftDefManager()
4879 {
4880         return m_craftdef;
4881 }
4882 ITextureSource* Server::getTextureSource()
4883 {
4884         return NULL;
4885 }
4886 IShaderSource* Server::getShaderSource()
4887 {
4888         return NULL;
4889 }
4890 u16 Server::allocateUnknownNodeId(const std::string &name)
4891 {
4892         return m_nodedef->allocateDummy(name);
4893 }
4894 ISoundManager* Server::getSoundManager()
4895 {
4896         return &dummySoundManager;
4897 }
4898 MtEventManager* Server::getEventManager()
4899 {
4900         return m_event;
4901 }
4902 IRollbackReportSink* Server::getRollbackReportSink()
4903 {
4904         if(!m_enable_rollback_recording)
4905                 return NULL;
4906         if(!m_rollback_sink_enabled)
4907                 return NULL;
4908         return m_rollback;
4909 }
4910
4911 IWritableItemDefManager* Server::getWritableItemDefManager()
4912 {
4913         return m_itemdef;
4914 }
4915 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4916 {
4917         return m_nodedef;
4918 }
4919 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4920 {
4921         return m_craftdef;
4922 }
4923
4924 const ModSpec* Server::getModSpec(const std::string &modname)
4925 {
4926         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4927                         i != m_mods.end(); i++){
4928                 const ModSpec &mod = *i;
4929                 if(mod.name == modname)
4930                         return &mod;
4931         }
4932         return NULL;
4933 }
4934 void Server::getModNames(std::list<std::string> &modlist)
4935 {
4936         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
4937         {
4938                 modlist.push_back(i->name);
4939         }
4940 }
4941 std::string Server::getBuiltinLuaPath()
4942 {
4943         return porting::path_share + DIR_DELIM + "builtin";
4944 }
4945
4946 v3f findSpawnPos(ServerMap &map)
4947 {
4948         //return v3f(50,50,50)*BS;
4949
4950         v3s16 nodepos;
4951
4952 #if 0
4953         nodepos = v2s16(0,0);
4954         groundheight = 20;
4955 #endif
4956
4957 #if 1
4958         s16 water_level = map.getWaterLevel();
4959
4960         // Try to find a good place a few times
4961         for(s32 i=0; i<1000; i++)
4962         {
4963                 s32 range = 1 + i;
4964                 // We're going to try to throw the player to this position
4965                 v2s16 nodepos2d = v2s16(
4966                                 -range + (myrand() % (range * 2)),
4967                                 -range + (myrand() % (range * 2)));
4968
4969                 // Get ground height at point
4970                 s16 groundheight = map.findGroundLevel(nodepos2d);
4971                 if (groundheight <= water_level) // Don't go underwater
4972                         continue;
4973                 if (groundheight > water_level + 6) // Don't go to high places
4974                         continue;
4975
4976                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
4977                 bool is_good = false;
4978                 s32 air_count = 0;
4979                 for (s32 i = 0; i < 10; i++) {
4980                         v3s16 blockpos = getNodeBlockPos(nodepos);
4981                         map.emergeBlock(blockpos, true);
4982                         content_t c = map.getNodeNoEx(nodepos).getContent();
4983                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
4984                                 air_count++;
4985                                 if (air_count >= 2){
4986                                         is_good = true;
4987                                         break;
4988                                 }
4989                         }
4990                         nodepos.Y++;
4991                 }
4992                 if(is_good){
4993                         // Found a good place
4994                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4995                         break;
4996                 }
4997         }
4998 #endif
4999
5000         return intToFloat(nodepos, BS);
5001 }
5002
5003 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
5004 {
5005         RemotePlayer *player = NULL;
5006         bool newplayer = false;
5007
5008         /*
5009                 Try to get an existing player
5010         */
5011         player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
5012
5013         // If player is already connected, cancel
5014         if(player != NULL && player->peer_id != 0)
5015         {
5016                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
5017                 return NULL;
5018         }
5019
5020         /*
5021                 If player with the wanted peer_id already exists, cancel.
5022         */
5023         if(m_env->getPlayer(peer_id) != NULL)
5024         {
5025                 infostream<<"emergePlayer(): Player with wrong name but same"
5026                                 " peer_id already exists"<<std::endl;
5027                 return NULL;
5028         }
5029
5030         /*
5031                 Create a new player if it doesn't exist yet
5032         */
5033         if(player == NULL)
5034         {
5035                 newplayer = true;
5036                 player = new RemotePlayer(this);
5037                 player->updateName(name);
5038
5039                 /* Set player position */
5040                 infostream<<"Server: Finding spawn place for player \""
5041                                 <<name<<"\""<<std::endl;
5042                 v3f pos = findSpawnPos(m_env->getServerMap());
5043                 player->setPosition(pos);
5044
5045                 /* Add player to environment */
5046                 m_env->addPlayer(player);
5047         }
5048
5049         /*
5050                 Create a new player active object
5051         */
5052         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5053                         getPlayerEffectivePrivs(player->getName()),
5054                         isSingleplayer());
5055
5056         /* Clean up old HUD elements from previous sessions */
5057         player->clearHud();
5058
5059         /* Add object to environment */
5060         m_env->addActiveObject(playersao);
5061
5062         /* Run scripts */
5063         if(newplayer)
5064                 m_script->on_newplayer(playersao);
5065
5066         return playersao;
5067 }
5068
5069 void dedicated_server_loop(Server &server, bool &kill)
5070 {
5071         DSTACK(__FUNCTION_NAME);
5072
5073         verbosestream<<"dedicated_server_loop()"<<std::endl;
5074
5075         IntervalLimiter m_profiler_interval;
5076
5077         for(;;)
5078         {
5079                 float steplen = g_settings->getFloat("dedicated_server_step");
5080                 // This is kind of a hack but can be done like this
5081                 // because server.step() is very light
5082                 {
5083                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
5084                         sleep_ms((int)(steplen*1000.0));
5085                 }
5086                 server.step(steplen);
5087
5088                 if(server.getShutdownRequested() || kill)
5089                 {
5090                         infostream<<"Dedicated server quitting"<<std::endl;
5091 #if USE_CURL
5092                         if(g_settings->getBool("server_announce") == true)
5093                                 ServerList::sendAnnounce("delete");
5094 #endif
5095                         break;
5096                 }
5097
5098                 /*
5099                         Profiler
5100                 */
5101                 float profiler_print_interval =
5102                                 g_settings->getFloat("profiler_print_interval");
5103                 if(profiler_print_interval != 0)
5104                 {
5105                         if(m_profiler_interval.step(steplen, profiler_print_interval))
5106                         {
5107                                 infostream<<"Profiler:"<<std::endl;
5108                                 g_profiler->print(infostream);
5109                                 g_profiler->clear();
5110                         }
5111                 }
5112         }
5113 }
5114
5115