288f254ed5b815b27bb357253f5d41f90f76c085
[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<<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                 assert(peer_proto_ver > 22);
1756
1757                 PlayerSAO* playersao = StageTwoClientInit(peer_id);
1758
1759                 if (playersao == NULL) {
1760                         errorstream
1761                                 << "TOSERVER_CLIENT_READY stage 2 client init failed for peer "
1762                                 << peer_id << std::endl;
1763                         return;
1764                 }
1765
1766
1767                 if(datasize < 2+8)
1768                         return;
1769
1770                 m_clients.setClientVersion(
1771                                 peer_id,
1772                                 data[2], data[3], data[4],
1773                                 std::string((char*) &data[8],(u16) data[6]));
1774
1775                 m_clients.event(peer_id, SetClientReady);
1776                 m_script->on_joinplayer(playersao);
1777
1778         }
1779         else if(command == TOSERVER_GOTBLOCKS)
1780         {
1781                 if(datasize < 2+1)
1782                         return;
1783
1784                 /*
1785                         [0] u16 command
1786                         [2] u8 count
1787                         [3] v3s16 pos_0
1788                         [3+6] v3s16 pos_1
1789                         ...
1790                 */
1791
1792                 u16 count = data[2];
1793                 for(u16 i=0; i<count; i++)
1794                 {
1795                         if((s16)datasize < 2+1+(i+1)*6)
1796                                 throw con::InvalidIncomingDataException
1797                                         ("GOTBLOCKS length is too short");
1798                         v3s16 p = readV3S16(&data[2+1+i*6]);
1799                         /*infostream<<"Server: GOTBLOCKS ("
1800                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
1801                         RemoteClient *client = getClient(peer_id);
1802                         client->GotBlock(p);
1803                 }
1804                 return;
1805         }
1806
1807         if (m_clients.getClientState(peer_id) < Active)
1808         {
1809                 if (command == TOSERVER_PLAYERPOS) return;
1810
1811                 errorstream<<"Got packet command: " << command << " for peer id "
1812                                 << peer_id << " but client isn't active yet. Dropping packet "
1813                                 <<std::endl;
1814                 return;
1815         }
1816
1817         Player *player = m_env->getPlayer(peer_id);
1818         if(player == NULL){
1819                 errorstream<<"Server::ProcessData(): Cancelling: "
1820                                 "No player for peer_id="<<peer_id
1821                                 <<std::endl;
1822                 return;
1823         }
1824
1825         PlayerSAO *playersao = player->getPlayerSAO();
1826         if(playersao == NULL){
1827                 errorstream<<"Server::ProcessData(): Cancelling: "
1828                                 "No player object for peer_id="<<peer_id
1829                                 <<std::endl;
1830                 return;
1831         }
1832
1833         if(command == TOSERVER_PLAYERPOS)
1834         {
1835                 if(datasize < 2+12+12+4+4)
1836                         return;
1837
1838                 u32 start = 0;
1839                 v3s32 ps = readV3S32(&data[start+2]);
1840                 v3s32 ss = readV3S32(&data[start+2+12]);
1841                 f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
1842                 f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
1843                 u32 keyPressed = 0;
1844                 if(datasize >= 2+12+12+4+4+4)
1845                         keyPressed = (u32)readU32(&data[2+12+12+4+4]);
1846                 v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
1847                 v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
1848                 pitch = wrapDegrees(pitch);
1849                 yaw = wrapDegrees(yaw);
1850
1851                 player->setPosition(position);
1852                 player->setSpeed(speed);
1853                 player->setPitch(pitch);
1854                 player->setYaw(yaw);
1855                 player->keyPressed=keyPressed;
1856                 player->control.up = (bool)(keyPressed&1);
1857                 player->control.down = (bool)(keyPressed&2);
1858                 player->control.left = (bool)(keyPressed&4);
1859                 player->control.right = (bool)(keyPressed&8);
1860                 player->control.jump = (bool)(keyPressed&16);
1861                 player->control.aux1 = (bool)(keyPressed&32);
1862                 player->control.sneak = (bool)(keyPressed&64);
1863                 player->control.LMB = (bool)(keyPressed&128);
1864                 player->control.RMB = (bool)(keyPressed&256);
1865
1866                 bool cheated = playersao->checkMovementCheat();
1867                 if(cheated){
1868                         // Call callbacks
1869                         m_script->on_cheat(playersao, "moved_too_fast");
1870                 }
1871
1872                 /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
1873                                 <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
1874                                 <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
1875         }
1876         else if(command == TOSERVER_DELETEDBLOCKS)
1877         {
1878                 if(datasize < 2+1)
1879                         return;
1880
1881                 /*
1882                         [0] u16 command
1883                         [2] u8 count
1884                         [3] v3s16 pos_0
1885                         [3+6] v3s16 pos_1
1886                         ...
1887                 */
1888
1889                 u16 count = data[2];
1890                 for(u16 i=0; i<count; i++)
1891                 {
1892                         if((s16)datasize < 2+1+(i+1)*6)
1893                                 throw con::InvalidIncomingDataException
1894                                         ("DELETEDBLOCKS length is too short");
1895                         v3s16 p = readV3S16(&data[2+1+i*6]);
1896                         /*infostream<<"Server: DELETEDBLOCKS ("
1897                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
1898                         RemoteClient *client = getClient(peer_id);
1899                         client->SetBlockNotSent(p);
1900                 }
1901         }
1902         else if(command == TOSERVER_CLICK_OBJECT)
1903         {
1904                 infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
1905                 return;
1906         }
1907         else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
1908         {
1909                 infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
1910                 return;
1911         }
1912         else if(command == TOSERVER_GROUND_ACTION)
1913         {
1914                 infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
1915                 return;
1916
1917         }
1918         else if(command == TOSERVER_RELEASE)
1919         {
1920                 infostream<<"Server: RELEASE not supported anymore"<<std::endl;
1921                 return;
1922         }
1923         else if(command == TOSERVER_SIGNTEXT)
1924         {
1925                 infostream<<"Server: SIGNTEXT not supported anymore"
1926                                 <<std::endl;
1927                 return;
1928         }
1929         else if(command == TOSERVER_SIGNNODETEXT)
1930         {
1931                 infostream<<"Server: SIGNNODETEXT not supported anymore"
1932                                 <<std::endl;
1933                 return;
1934         }
1935         else if(command == TOSERVER_INVENTORY_ACTION)
1936         {
1937                 // Strip command and create a stream
1938                 std::string datastring((char*)&data[2], datasize-2);
1939                 verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
1940                 std::istringstream is(datastring, std::ios_base::binary);
1941                 // Create an action
1942                 InventoryAction *a = InventoryAction::deSerialize(is);
1943                 if(a == NULL)
1944                 {
1945                         infostream<<"TOSERVER_INVENTORY_ACTION: "
1946                                         <<"InventoryAction::deSerialize() returned NULL"
1947                                         <<std::endl;
1948                         return;
1949                 }
1950
1951                 // If something goes wrong, this player is to blame
1952                 RollbackScopeActor rollback_scope(m_rollback,
1953                                 std::string("player:")+player->getName());
1954
1955                 /*
1956                         Note: Always set inventory not sent, to repair cases
1957                         where the client made a bad prediction.
1958                 */
1959
1960                 /*
1961                         Handle restrictions and special cases of the move action
1962                 */
1963                 if(a->getType() == IACTION_MOVE)
1964                 {
1965                         IMoveAction *ma = (IMoveAction*)a;
1966
1967                         ma->from_inv.applyCurrentPlayer(player->getName());
1968                         ma->to_inv.applyCurrentPlayer(player->getName());
1969
1970                         setInventoryModified(ma->from_inv);
1971                         setInventoryModified(ma->to_inv);
1972
1973                         bool from_inv_is_current_player =
1974                                 (ma->from_inv.type == InventoryLocation::PLAYER) &&
1975                                 (ma->from_inv.name == player->getName());
1976
1977                         bool to_inv_is_current_player =
1978                                 (ma->to_inv.type == InventoryLocation::PLAYER) &&
1979                                 (ma->to_inv.name == player->getName());
1980
1981                         /*
1982                                 Disable moving items out of craftpreview
1983                         */
1984                         if(ma->from_list == "craftpreview")
1985                         {
1986                                 infostream<<"Ignoring IMoveAction from "
1987                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
1988                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
1989                                                 <<" because src is "<<ma->from_list<<std::endl;
1990                                 delete a;
1991                                 return;
1992                         }
1993
1994                         /*
1995                                 Disable moving items into craftresult and craftpreview
1996                         */
1997                         if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
1998                         {
1999                                 infostream<<"Ignoring IMoveAction from "
2000                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2001                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2002                                                 <<" because dst is "<<ma->to_list<<std::endl;
2003                                 delete a;
2004                                 return;
2005                         }
2006
2007                         // Disallow moving items in elsewhere than player's inventory
2008                         // if not allowed to interact
2009                         if(!checkPriv(player->getName(), "interact") &&
2010                                         (!from_inv_is_current_player ||
2011                                         !to_inv_is_current_player))
2012                         {
2013                                 infostream<<"Cannot move outside of player's inventory: "
2014                                                 <<"No interact privilege"<<std::endl;
2015                                 delete a;
2016                                 return;
2017                         }
2018                 }
2019                 /*
2020                         Handle restrictions and special cases of the drop action
2021                 */
2022                 else if(a->getType() == IACTION_DROP)
2023                 {
2024                         IDropAction *da = (IDropAction*)a;
2025
2026                         da->from_inv.applyCurrentPlayer(player->getName());
2027
2028                         setInventoryModified(da->from_inv);
2029
2030                         /*
2031                                 Disable dropping items out of craftpreview
2032                         */
2033                         if(da->from_list == "craftpreview")
2034                         {
2035                                 infostream<<"Ignoring IDropAction from "
2036                                                 <<(da->from_inv.dump())<<":"<<da->from_list
2037                                                 <<" because src is "<<da->from_list<<std::endl;
2038                                 delete a;
2039                                 return;
2040                         }
2041
2042                         // Disallow dropping items if not allowed to interact
2043                         if(!checkPriv(player->getName(), "interact"))
2044                         {
2045                                 delete a;
2046                                 return;
2047                         }
2048                 }
2049                 /*
2050                         Handle restrictions and special cases of the craft action
2051                 */
2052                 else if(a->getType() == IACTION_CRAFT)
2053                 {
2054                         ICraftAction *ca = (ICraftAction*)a;
2055
2056                         ca->craft_inv.applyCurrentPlayer(player->getName());
2057
2058                         setInventoryModified(ca->craft_inv);
2059
2060                         //bool craft_inv_is_current_player =
2061                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2062                         //      (ca->craft_inv.name == player->getName());
2063
2064                         // Disallow crafting if not allowed to interact
2065                         if(!checkPriv(player->getName(), "interact"))
2066                         {
2067                                 infostream<<"Cannot craft: "
2068                                                 <<"No interact privilege"<<std::endl;
2069                                 delete a;
2070                                 return;
2071                         }
2072                 }
2073
2074                 // Do the action
2075                 a->apply(this, playersao, this);
2076                 // Eat the action
2077                 delete a;
2078         }
2079         else if(command == TOSERVER_CHAT_MESSAGE)
2080         {
2081                 /*
2082                         u16 command
2083                         u16 length
2084                         wstring message
2085                 */
2086                 u8 buf[6];
2087                 std::string datastring((char*)&data[2], datasize-2);
2088                 std::istringstream is(datastring, std::ios_base::binary);
2089
2090                 // Read stuff
2091                 is.read((char*)buf, 2);
2092                 u16 len = readU16(buf);
2093
2094                 std::wstring message;
2095                 for(u16 i=0; i<len; i++)
2096                 {
2097                         is.read((char*)buf, 2);
2098                         message += (wchar_t)readU16(buf);
2099                 }
2100
2101                 // If something goes wrong, this player is to blame
2102                 RollbackScopeActor rollback_scope(m_rollback,
2103                                 std::string("player:")+player->getName());
2104
2105                 // Get player name of this client
2106                 std::wstring name = narrow_to_wide(player->getName());
2107
2108                 // Run script hook
2109                 bool ate = m_script->on_chat_message(player->getName(),
2110                                 wide_to_narrow(message));
2111                 // If script ate the message, don't proceed
2112                 if(ate)
2113                         return;
2114
2115                 // Line to send to players
2116                 std::wstring line;
2117                 // Whether to send to the player that sent the line
2118                 bool send_to_sender_only = false;
2119
2120                 // Commands are implemented in Lua, so only catch invalid
2121                 // commands that were not "eaten" and send an error back
2122                 if(message[0] == L'/')
2123                 {
2124                         message = message.substr(1);
2125                         send_to_sender_only = true;
2126                         if(message.length() == 0)
2127                                 line += L"-!- Empty command";
2128                         else
2129                                 line += L"-!- Invalid command: " + str_split(message, L' ')[0];
2130                 }
2131                 else
2132                 {
2133                         if(checkPriv(player->getName(), "shout")){
2134                                 line += L"<";
2135                                 line += name;
2136                                 line += L"> ";
2137                                 line += message;
2138                         } else {
2139                                 line += L"-!- You don't have permission to shout.";
2140                                 send_to_sender_only = true;
2141                         }
2142                 }
2143
2144                 if(line != L"")
2145                 {
2146                         /*
2147                                 Send the message to sender
2148                         */
2149                         if (send_to_sender_only)
2150                         {
2151                                 SendChatMessage(peer_id, line);
2152                         }
2153                         /*
2154                                 Send the message to others
2155                         */
2156                         else
2157                         {
2158                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2159
2160                                 std::list<u16> clients = m_clients.getClientIDs();
2161
2162                                 for(std::list<u16>::iterator
2163                                         i = clients.begin();
2164                                         i != clients.end(); ++i)
2165                                 {
2166                                         if (*i != peer_id)
2167                                                 SendChatMessage(*i, line);
2168                                 }
2169                         }
2170                 }
2171         }
2172         else if(command == TOSERVER_DAMAGE)
2173         {
2174                 std::string datastring((char*)&data[2], datasize-2);
2175                 std::istringstream is(datastring, std::ios_base::binary);
2176                 u8 damage = readU8(is);
2177
2178                 if(g_settings->getBool("enable_damage"))
2179                 {
2180                         actionstream<<player->getName()<<" damaged by "
2181                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2182                                         <<std::endl;
2183
2184                         playersao->setHP(playersao->getHP() - damage);
2185
2186                         if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
2187                                 DiePlayer(peer_id);
2188
2189                         if(playersao->m_hp_not_sent)
2190                                 SendPlayerHP(peer_id);
2191                 }
2192         }
2193         else if(command == TOSERVER_BREATH)
2194         {
2195                 std::string datastring((char*)&data[2], datasize-2);
2196                 std::istringstream is(datastring, std::ios_base::binary);
2197                 u16 breath = readU16(is);
2198                 playersao->setBreath(breath);
2199                 m_script->player_event(playersao,"breath_changed");
2200         }
2201         else if(command == TOSERVER_PASSWORD)
2202         {
2203                 /*
2204                         [0] u16 TOSERVER_PASSWORD
2205                         [2] u8[28] old password
2206                         [30] u8[28] new password
2207                 */
2208
2209                 if(datasize != 2+PASSWORD_SIZE*2)
2210                         return;
2211                 /*char password[PASSWORD_SIZE];
2212                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2213                         password[i] = data[2+i];
2214                 password[PASSWORD_SIZE-1] = 0;*/
2215                 std::string oldpwd;
2216                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2217                 {
2218                         char c = data[2+i];
2219                         if(c == 0)
2220                                 break;
2221                         oldpwd += c;
2222                 }
2223                 std::string newpwd;
2224                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2225                 {
2226                         char c = data[2+PASSWORD_SIZE+i];
2227                         if(c == 0)
2228                                 break;
2229                         newpwd += c;
2230                 }
2231
2232                 if(!base64_is_valid(newpwd)){
2233                         infostream<<"Server: "<<player->getName()<<" supplied invalid password hash"<<std::endl;
2234                         // Wrong old password supplied!!
2235                         SendChatMessage(peer_id, L"Invalid new password hash supplied. Password NOT changed.");
2236                         return;
2237                 }
2238
2239                 infostream<<"Server: Client requests a password change from "
2240                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2241
2242                 std::string playername = player->getName();
2243
2244                 std::string checkpwd;
2245                 m_script->getAuth(playername, &checkpwd, NULL);
2246
2247                 if(oldpwd != checkpwd)
2248                 {
2249                         infostream<<"Server: invalid old password"<<std::endl;
2250                         // Wrong old password supplied!!
2251                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2252                         return;
2253                 }
2254
2255                 bool success = m_script->setPassword(playername, newpwd);
2256                 if(success){
2257                         actionstream<<player->getName()<<" changes password"<<std::endl;
2258                         SendChatMessage(peer_id, L"Password change successful.");
2259                 } else {
2260                         actionstream<<player->getName()<<" tries to change password but "
2261                                         <<"it fails"<<std::endl;
2262                         SendChatMessage(peer_id, L"Password change failed or inavailable.");
2263                 }
2264         }
2265         else if(command == TOSERVER_PLAYERITEM)
2266         {
2267                 if (datasize < 2+2)
2268                         return;
2269
2270                 u16 item = readU16(&data[2]);
2271                 playersao->setWieldIndex(item);
2272         }
2273         else if(command == TOSERVER_RESPAWN)
2274         {
2275                 if(player->hp != 0 || !g_settings->getBool("enable_damage"))
2276                         return;
2277
2278                 RespawnPlayer(peer_id);
2279
2280                 actionstream<<player->getName()<<" respawns at "
2281                                 <<PP(player->getPosition()/BS)<<std::endl;
2282
2283                 // ActiveObject is added to environment in AsyncRunStep after
2284                 // the previous addition has been succesfully removed
2285         }
2286         else if(command == TOSERVER_INTERACT)
2287         {
2288                 std::string datastring((char*)&data[2], datasize-2);
2289                 std::istringstream is(datastring, std::ios_base::binary);
2290
2291                 /*
2292                         [0] u16 command
2293                         [2] u8 action
2294                         [3] u16 item
2295                         [5] u32 length of the next item
2296                         [9] serialized PointedThing
2297                         actions:
2298                         0: start digging (from undersurface) or use
2299                         1: stop digging (all parameters ignored)
2300                         2: digging completed
2301                         3: place block or item (to abovesurface)
2302                         4: use item
2303                 */
2304                 u8 action = readU8(is);
2305                 u16 item_i = readU16(is);
2306                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2307                 PointedThing pointed;
2308                 pointed.deSerialize(tmp_is);
2309
2310                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2311                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2312
2313                 if(player->hp == 0)
2314                 {
2315                         verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
2316                                 <<" tried to interact, but is dead!"<<std::endl;
2317                         return;
2318                 }
2319
2320                 v3f player_pos = playersao->getLastGoodPosition();
2321
2322                 // Update wielded item
2323                 playersao->setWieldIndex(item_i);
2324
2325                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2326                 v3s16 p_under = pointed.node_undersurface;
2327                 v3s16 p_above = pointed.node_abovesurface;
2328
2329                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2330                 ServerActiveObject *pointed_object = NULL;
2331                 if(pointed.type == POINTEDTHING_OBJECT)
2332                 {
2333                         pointed_object = m_env->getActiveObject(pointed.object_id);
2334                         if(pointed_object == NULL)
2335                         {
2336                                 verbosestream<<"TOSERVER_INTERACT: "
2337                                         "pointed object is NULL"<<std::endl;
2338                                 return;
2339                         }
2340
2341                 }
2342
2343                 v3f pointed_pos_under = player_pos;
2344                 v3f pointed_pos_above = player_pos;
2345                 if(pointed.type == POINTEDTHING_NODE)
2346                 {
2347                         pointed_pos_under = intToFloat(p_under, BS);
2348                         pointed_pos_above = intToFloat(p_above, BS);
2349                 }
2350                 else if(pointed.type == POINTEDTHING_OBJECT)
2351                 {
2352                         pointed_pos_under = pointed_object->getBasePosition();
2353                         pointed_pos_above = pointed_pos_under;
2354                 }
2355
2356                 /*
2357                         Check that target is reasonably close
2358                         (only when digging or placing things)
2359                 */
2360                 if(action == 0 || action == 2 || action == 3)
2361                 {
2362                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2363                         float max_d = BS * 14; // Just some large enough value
2364                         if(d > max_d){
2365                                 actionstream<<"Player "<<player->getName()
2366                                                 <<" tried to access "<<pointed.dump()
2367                                                 <<" from too far: "
2368                                                 <<"d="<<d<<", max_d="<<max_d
2369                                                 <<". ignoring."<<std::endl;
2370                                 // Re-send block to revert change on client-side
2371                                 RemoteClient *client = getClient(peer_id);
2372                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2373                                 client->SetBlockNotSent(blockpos);
2374                                 // Call callbacks
2375                                 m_script->on_cheat(playersao, "interacted_too_far");
2376                                 // Do nothing else
2377                                 return;
2378                         }
2379                 }
2380
2381                 /*
2382                         Make sure the player is allowed to do it
2383                 */
2384                 if(!checkPriv(player->getName(), "interact"))
2385                 {
2386                         actionstream<<player->getName()<<" attempted to interact with "
2387                                         <<pointed.dump()<<" without 'interact' privilege"
2388                                         <<std::endl;
2389                         // Re-send block to revert change on client-side
2390                         RemoteClient *client = getClient(peer_id);
2391                         // Digging completed -> under
2392                         if(action == 2){
2393                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2394                                 client->SetBlockNotSent(blockpos);
2395                         }
2396                         // Placement -> above
2397                         if(action == 3){
2398                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2399                                 client->SetBlockNotSent(blockpos);
2400                         }
2401                         return;
2402                 }
2403
2404                 /*
2405                         If something goes wrong, this player is to blame
2406                 */
2407                 RollbackScopeActor rollback_scope(m_rollback,
2408                                 std::string("player:")+player->getName());
2409
2410                 /*
2411                         0: start digging or punch object
2412                 */
2413                 if(action == 0)
2414                 {
2415                         if(pointed.type == POINTEDTHING_NODE)
2416                         {
2417                                 /*
2418                                         NOTE: This can be used in the future to check if
2419                                         somebody is cheating, by checking the timing.
2420                                 */
2421                                 MapNode n(CONTENT_IGNORE);
2422                                 try
2423                                 {
2424                                         n = m_env->getMap().getNode(p_under);
2425                                 }
2426                                 catch(InvalidPositionException &e)
2427                                 {
2428                                         infostream<<"Server: Not punching: Node not found."
2429                                                         <<" Adding block to emerge queue."
2430                                                         <<std::endl;
2431                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2432                                 }
2433                                 if(n.getContent() != CONTENT_IGNORE)
2434                                         m_script->node_on_punch(p_under, n, playersao, pointed);
2435                                 // Cheat prevention
2436                                 playersao->noCheatDigStart(p_under);
2437                         }
2438                         else if(pointed.type == POINTEDTHING_OBJECT)
2439                         {
2440                                 // Skip if object has been removed
2441                                 if(pointed_object->m_removed)
2442                                         return;
2443
2444                                 actionstream<<player->getName()<<" punches object "
2445                                                 <<pointed.object_id<<": "
2446                                                 <<pointed_object->getDescription()<<std::endl;
2447
2448                                 ItemStack punchitem = playersao->getWieldedItem();
2449                                 ToolCapabilities toolcap =
2450                                                 punchitem.getToolCapabilities(m_itemdef);
2451                                 v3f dir = (pointed_object->getBasePosition() -
2452                                                 (player->getPosition() + player->getEyeOffset())
2453                                                         ).normalize();
2454                                 float time_from_last_punch =
2455                                         playersao->resetTimeFromLastPunch();
2456                                 pointed_object->punch(dir, &toolcap, playersao,
2457                                                 time_from_last_punch);
2458                         }
2459
2460                 } // action == 0
2461
2462                 /*
2463                         1: stop digging
2464                 */
2465                 else if(action == 1)
2466                 {
2467                 } // action == 1
2468
2469                 /*
2470                         2: Digging completed
2471                 */
2472                 else if(action == 2)
2473                 {
2474                         // Only digging of nodes
2475                         if(pointed.type == POINTEDTHING_NODE)
2476                         {
2477                                 MapNode n(CONTENT_IGNORE);
2478                                 try
2479                                 {
2480                                         n = m_env->getMap().getNode(p_under);
2481                                 }
2482                                 catch(InvalidPositionException &e)
2483                                 {
2484                                         infostream<<"Server: Not finishing digging: Node not found."
2485                                                         <<" Adding block to emerge queue."
2486                                                         <<std::endl;
2487                                         m_emerge->enqueueBlockEmerge(peer_id, getNodeBlockPos(p_above), false);
2488                                 }
2489
2490                                 /* Cheat prevention */
2491                                 bool is_valid_dig = true;
2492                                 if(!isSingleplayer() && !g_settings->getBool("disable_anticheat"))
2493                                 {
2494                                         v3s16 nocheat_p = playersao->getNoCheatDigPos();
2495                                         float nocheat_t = playersao->getNoCheatDigTime();
2496                                         playersao->noCheatDigEnd();
2497                                         // If player didn't start digging this, ignore dig
2498                                         if(nocheat_p != p_under){
2499                                                 infostream<<"Server: NoCheat: "<<player->getName()
2500                                                                 <<" started digging "
2501                                                                 <<PP(nocheat_p)<<" and completed digging "
2502                                                                 <<PP(p_under)<<"; not digging."<<std::endl;
2503                                                 is_valid_dig = false;
2504                                                 // Call callbacks
2505                                                 m_script->on_cheat(playersao, "finished_unknown_dig");
2506                                         }
2507                                         // Get player's wielded item
2508                                         ItemStack playeritem;
2509                                         InventoryList *mlist = playersao->getInventory()->getList("main");
2510                                         if(mlist != NULL)
2511                                                 playeritem = mlist->getItem(playersao->getWieldIndex());
2512                                         ToolCapabilities playeritem_toolcap =
2513                                                         playeritem.getToolCapabilities(m_itemdef);
2514                                         // Get diggability and expected digging time
2515                                         DigParams params = getDigParams(m_nodedef->get(n).groups,
2516                                                         &playeritem_toolcap);
2517                                         // If can't dig, try hand
2518                                         if(!params.diggable){
2519                                                 const ItemDefinition &hand = m_itemdef->get("");
2520                                                 const ToolCapabilities *tp = hand.tool_capabilities;
2521                                                 if(tp)
2522                                                         params = getDigParams(m_nodedef->get(n).groups, tp);
2523                                         }
2524                                         // If can't dig, ignore dig
2525                                         if(!params.diggable){
2526                                                 infostream<<"Server: NoCheat: "<<player->getName()
2527                                                                 <<" completed digging "<<PP(p_under)
2528                                                                 <<", which is not diggable with tool. not digging."
2529                                                                 <<std::endl;
2530                                                 is_valid_dig = false;
2531                                                 // Call callbacks
2532                                                 m_script->on_cheat(playersao, "dug_unbreakable");
2533                                         }
2534                                         // Check digging time
2535                                         // If already invalidated, we don't have to
2536                                         if(!is_valid_dig){
2537                                                 // Well not our problem then
2538                                         }
2539                                         // Clean and long dig
2540                                         else if(params.time > 2.0 && nocheat_t * 1.2 > params.time){
2541                                                 // All is good, but grab time from pool; don't care if
2542                                                 // it's actually available
2543                                                 playersao->getDigPool().grab(params.time);
2544                                         }
2545                                         // Short or laggy dig
2546                                         // Try getting the time from pool
2547                                         else if(playersao->getDigPool().grab(params.time)){
2548                                                 // All is good
2549                                         }
2550                                         // Dig not possible
2551                                         else{
2552                                                 infostream<<"Server: NoCheat: "<<player->getName()
2553                                                                 <<" completed digging "<<PP(p_under)
2554                                                                 <<"too fast; not digging."<<std::endl;
2555                                                 is_valid_dig = false;
2556                                                 // Call callbacks
2557                                                 m_script->on_cheat(playersao, "dug_too_fast");
2558                                         }
2559                                 }
2560
2561                                 /* Actually dig node */
2562
2563                                 if(is_valid_dig && n.getContent() != CONTENT_IGNORE)
2564                                         m_script->node_on_dig(p_under, n, playersao);
2565
2566                                 // Send unusual result (that is, node not being removed)
2567                                 if(m_env->getMap().getNodeNoEx(p_under).getContent() != CONTENT_AIR)
2568                                 {
2569                                         // Re-send block to revert change on client-side
2570                                         RemoteClient *client = getClient(peer_id);
2571                                         v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2572                                         client->SetBlockNotSent(blockpos);
2573                                 }
2574                         }
2575                 } // action == 2
2576
2577                 /*
2578                         3: place block or right-click object
2579                 */
2580                 else if(action == 3)
2581                 {
2582                         ItemStack item = playersao->getWieldedItem();
2583
2584                         // Reset build time counter
2585                         if(pointed.type == POINTEDTHING_NODE &&
2586                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
2587                                 getClient(peer_id)->m_time_from_building = 0.0;
2588
2589                         if(pointed.type == POINTEDTHING_OBJECT)
2590                         {
2591                                 // Right click object
2592
2593                                 // Skip if object has been removed
2594                                 if(pointed_object->m_removed)
2595                                         return;
2596
2597                                 actionstream<<player->getName()<<" right-clicks object "
2598                                                 <<pointed.object_id<<": "
2599                                                 <<pointed_object->getDescription()<<std::endl;
2600
2601                                 // Do stuff
2602                                 pointed_object->rightClick(playersao);
2603                         }
2604                         else if(m_script->item_OnPlace(
2605                                         item, playersao, pointed))
2606                         {
2607                                 // Placement was handled in lua
2608
2609                                 // Apply returned ItemStack
2610                                 playersao->setWieldedItem(item);
2611                         }
2612
2613                         // If item has node placement prediction, always send the
2614                         // blocks to make sure the client knows what exactly happened
2615                         if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
2616                                 RemoteClient *client = getClient(peer_id);
2617                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_above, BS));
2618                                 client->SetBlockNotSent(blockpos);
2619                                 v3s16 blockpos2 = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2620                                 if(blockpos2 != blockpos){
2621                                         client->SetBlockNotSent(blockpos2);
2622                                 }
2623                         }
2624                 } // action == 3
2625
2626                 /*
2627                         4: use
2628                 */
2629                 else if(action == 4)
2630                 {
2631                         ItemStack item = playersao->getWieldedItem();
2632
2633                         actionstream<<player->getName()<<" uses "<<item.name
2634                                         <<", pointing at "<<pointed.dump()<<std::endl;
2635
2636                         if(m_script->item_OnUse(
2637                                         item, playersao, pointed))
2638                         {
2639                                 // Apply returned ItemStack
2640                                 playersao->setWieldedItem(item);
2641                         }
2642
2643                 } // action == 4
2644                 
2645
2646                 /*
2647                         Catch invalid actions
2648                 */
2649                 else
2650                 {
2651                         infostream<<"WARNING: Server: Invalid action "
2652                                         <<action<<std::endl;
2653                 }
2654         }
2655         else if(command == TOSERVER_REMOVED_SOUNDS)
2656         {
2657                 std::string datastring((char*)&data[2], datasize-2);
2658                 std::istringstream is(datastring, std::ios_base::binary);
2659
2660                 int num = readU16(is);
2661                 for(int k=0; k<num; k++){
2662                         s32 id = readS32(is);
2663                         std::map<s32, ServerPlayingSound>::iterator i =
2664                                         m_playing_sounds.find(id);
2665                         if(i == m_playing_sounds.end())
2666                                 continue;
2667                         ServerPlayingSound &psound = i->second;
2668                         psound.clients.erase(peer_id);
2669                         if(psound.clients.size() == 0)
2670                                 m_playing_sounds.erase(i++);
2671                 }
2672         }
2673         else if(command == TOSERVER_NODEMETA_FIELDS)
2674         {
2675                 std::string datastring((char*)&data[2], datasize-2);
2676                 std::istringstream is(datastring, std::ios_base::binary);
2677
2678                 v3s16 p = readV3S16(is);
2679                 std::string formname = deSerializeString(is);
2680                 int num = readU16(is);
2681                 std::map<std::string, std::string> fields;
2682                 for(int k=0; k<num; k++){
2683                         std::string fieldname = deSerializeString(is);
2684                         std::string fieldvalue = deSerializeLongString(is);
2685                         fields[fieldname] = fieldvalue;
2686                 }
2687
2688                 // If something goes wrong, this player is to blame
2689                 RollbackScopeActor rollback_scope(m_rollback,
2690                                 std::string("player:")+player->getName());
2691
2692                 // Check the target node for rollback data; leave others unnoticed
2693                 RollbackNode rn_old(&m_env->getMap(), p, this);
2694
2695                 m_script->node_on_receive_fields(p, formname, fields,playersao);
2696
2697                 // Report rollback data
2698                 RollbackNode rn_new(&m_env->getMap(), p, this);
2699                 if(rollback() && rn_new != rn_old){
2700                         RollbackAction action;
2701                         action.setSetNode(p, rn_old, rn_new);
2702                         rollback()->reportAction(action);
2703                 }
2704         }
2705         else if(command == TOSERVER_INVENTORY_FIELDS)
2706         {
2707                 std::string datastring((char*)&data[2], datasize-2);
2708                 std::istringstream is(datastring, std::ios_base::binary);
2709
2710                 std::string formname = deSerializeString(is);
2711                 int num = readU16(is);
2712                 std::map<std::string, std::string> fields;
2713                 for(int k=0; k<num; k++){
2714                         std::string fieldname = deSerializeString(is);
2715                         std::string fieldvalue = deSerializeLongString(is);
2716                         fields[fieldname] = fieldvalue;
2717                 }
2718
2719                 m_script->on_playerReceiveFields(playersao, formname, fields);
2720         }
2721         else
2722         {
2723                 infostream<<"Server::ProcessData(): Ignoring "
2724                                 "unknown command "<<command<<std::endl;
2725         }
2726
2727         } //try
2728         catch(SendFailedException &e)
2729         {
2730                 errorstream<<"Server::ProcessData(): SendFailedException: "
2731                                 <<"what="<<e.what()
2732                                 <<std::endl;
2733         }
2734 }
2735
2736 void Server::setTimeOfDay(u32 time)
2737 {
2738         m_env->setTimeOfDay(time);
2739         m_time_of_day_send_timer = 0;
2740 }
2741
2742 void Server::onMapEditEvent(MapEditEvent *event)
2743 {
2744         //infostream<<"Server::onMapEditEvent()"<<std::endl;
2745         if(m_ignore_map_edit_events)
2746                 return;
2747         if(m_ignore_map_edit_events_area.contains(event->getArea()))
2748                 return;
2749         MapEditEvent *e = event->clone();
2750         m_unsent_map_edit_queue.push_back(e);
2751 }
2752
2753 Inventory* Server::getInventory(const InventoryLocation &loc)
2754 {
2755         switch(loc.type){
2756         case InventoryLocation::UNDEFINED:
2757         {}
2758         break;
2759         case InventoryLocation::CURRENT_PLAYER:
2760         {}
2761         break;
2762         case InventoryLocation::PLAYER:
2763         {
2764                 Player *player = m_env->getPlayer(loc.name.c_str());
2765                 if(!player)
2766                         return NULL;
2767                 PlayerSAO *playersao = player->getPlayerSAO();
2768                 if(!playersao)
2769                         return NULL;
2770                 return playersao->getInventory();
2771         }
2772         break;
2773         case InventoryLocation::NODEMETA:
2774         {
2775                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
2776                 if(!meta)
2777                         return NULL;
2778                 return meta->getInventory();
2779         }
2780         break;
2781         case InventoryLocation::DETACHED:
2782         {
2783                 if(m_detached_inventories.count(loc.name) == 0)
2784                         return NULL;
2785                 return m_detached_inventories[loc.name];
2786         }
2787         break;
2788         default:
2789                 assert(0);
2790         }
2791         return NULL;
2792 }
2793 void Server::setInventoryModified(const InventoryLocation &loc)
2794 {
2795         switch(loc.type){
2796         case InventoryLocation::UNDEFINED:
2797         {}
2798         break;
2799         case InventoryLocation::PLAYER:
2800         {
2801                 Player *player = m_env->getPlayer(loc.name.c_str());
2802                 if(!player)
2803                         return;
2804                 PlayerSAO *playersao = player->getPlayerSAO();
2805                 if(!playersao)
2806                         return;
2807                 playersao->m_inventory_not_sent = true;
2808                 playersao->m_wielded_item_not_sent = true;
2809         }
2810         break;
2811         case InventoryLocation::NODEMETA:
2812         {
2813                 v3s16 blockpos = getNodeBlockPos(loc.p);
2814
2815                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2816                 if(block)
2817                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
2818
2819                 setBlockNotSent(blockpos);
2820         }
2821         break;
2822         case InventoryLocation::DETACHED:
2823         {
2824                 sendDetachedInventory(loc.name,PEER_ID_INEXISTENT);
2825         }
2826         break;
2827         default:
2828                 assert(0);
2829         }
2830 }
2831
2832 void Server::SetBlocksNotSent(std::map<v3s16, MapBlock *>& block)
2833 {
2834         std::list<u16> clients = m_clients.getClientIDs();
2835         m_clients.Lock();
2836         // Set the modified blocks unsent for all the clients
2837         for (std::list<u16>::iterator
2838                  i = clients.begin();
2839                  i != clients.end(); ++i) {
2840                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
2841                         if (client != NULL)
2842                                 client->SetBlocksNotSent(block);
2843                 }
2844         m_clients.Unlock();
2845 }
2846
2847 void Server::peerAdded(con::Peer *peer)
2848 {
2849         DSTACK(__FUNCTION_NAME);
2850         verbosestream<<"Server::peerAdded(): peer->id="
2851                         <<peer->id<<std::endl;
2852
2853         con::PeerChange c;
2854         c.type = con::PEER_ADDED;
2855         c.peer_id = peer->id;
2856         c.timeout = false;
2857         m_peer_change_queue.push_back(c);
2858 }
2859
2860 void Server::deletingPeer(con::Peer *peer, bool timeout)
2861 {
2862         DSTACK(__FUNCTION_NAME);
2863         verbosestream<<"Server::deletingPeer(): peer->id="
2864                         <<peer->id<<", timeout="<<timeout<<std::endl;
2865
2866         m_clients.event(peer->id,Disconnect);
2867         con::PeerChange c;
2868         c.type = con::PEER_REMOVED;
2869         c.peer_id = peer->id;
2870         c.timeout = timeout;
2871         m_peer_change_queue.push_back(c);
2872 }
2873
2874 bool Server::getClientConInfo(u16 peer_id, con::rtt_stat_type type, float* retval)
2875 {
2876         *retval = m_con.getPeerStat(peer_id,type);
2877         if (*retval == -1) return false;
2878         return true;
2879 }
2880
2881 bool Server::getClientInfo(
2882                 u16          peer_id,
2883                 ClientState* state,
2884                 u32*         uptime,
2885                 u8*          ser_vers,
2886                 u16*         prot_vers,
2887                 u8*          major,
2888                 u8*          minor,
2889                 u8*          patch,
2890                 std::string* vers_string
2891         )
2892 {
2893         *state = m_clients.getClientState(peer_id);
2894         m_clients.Lock();
2895         RemoteClient* client = m_clients.lockedGetClientNoEx(peer_id,Invalid);
2896
2897         if (client == NULL)
2898                 return false;
2899
2900         *uptime = client->uptime();
2901         *ser_vers = client->serialization_version;
2902         *prot_vers = client->net_proto_version;
2903
2904         *major = client->getMajor();
2905         *minor = client->getMinor();
2906         *patch = client->getPatch();
2907         *vers_string = client->getPatch();
2908
2909         m_clients.Unlock();
2910
2911         return true;
2912 }
2913
2914 void Server::handlePeerChanges()
2915 {
2916         while(m_peer_change_queue.size() > 0)
2917         {
2918                 con::PeerChange c = m_peer_change_queue.pop_front();
2919
2920                 verbosestream<<"Server: Handling peer change: "
2921                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
2922                                 <<std::endl;
2923
2924                 switch(c.type)
2925                 {
2926                 case con::PEER_ADDED:
2927                         m_clients.CreateClient(c.peer_id);
2928                         break;
2929
2930                 case con::PEER_REMOVED:
2931                         DeleteClient(c.peer_id, c.timeout?CDR_TIMEOUT:CDR_LEAVE);
2932                         break;
2933
2934                 default:
2935                         assert("Invalid peer change event received!" == 0);
2936                         break;
2937                 }
2938         }
2939 }
2940
2941 void Server::SendMovement(u16 peer_id)
2942 {
2943         DSTACK(__FUNCTION_NAME);
2944         std::ostringstream os(std::ios_base::binary);
2945
2946         writeU16(os, TOCLIENT_MOVEMENT);
2947         writeF1000(os, g_settings->getFloat("movement_acceleration_default"));
2948         writeF1000(os, g_settings->getFloat("movement_acceleration_air"));
2949         writeF1000(os, g_settings->getFloat("movement_acceleration_fast"));
2950         writeF1000(os, g_settings->getFloat("movement_speed_walk"));
2951         writeF1000(os, g_settings->getFloat("movement_speed_crouch"));
2952         writeF1000(os, g_settings->getFloat("movement_speed_fast"));
2953         writeF1000(os, g_settings->getFloat("movement_speed_climb"));
2954         writeF1000(os, g_settings->getFloat("movement_speed_jump"));
2955         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity"));
2956         writeF1000(os, g_settings->getFloat("movement_liquid_fluidity_smooth"));
2957         writeF1000(os, g_settings->getFloat("movement_liquid_sink"));
2958         writeF1000(os, g_settings->getFloat("movement_gravity"));
2959
2960         // Make data buffer
2961         std::string s = os.str();
2962         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2963         // Send as reliable
2964         m_clients.send(peer_id, 0, data, true);
2965 }
2966
2967 void Server::SendHP(u16 peer_id, u8 hp)
2968 {
2969         DSTACK(__FUNCTION_NAME);
2970         std::ostringstream os(std::ios_base::binary);
2971
2972         writeU16(os, TOCLIENT_HP);
2973         writeU8(os, hp);
2974
2975         // Make data buffer
2976         std::string s = os.str();
2977         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2978         // Send as reliable
2979         m_clients.send(peer_id, 0, data, true);
2980 }
2981
2982 void Server::SendBreath(u16 peer_id, u16 breath)
2983 {
2984         DSTACK(__FUNCTION_NAME);
2985         std::ostringstream os(std::ios_base::binary);
2986
2987         writeU16(os, TOCLIENT_BREATH);
2988         writeU16(os, breath);
2989
2990         // Make data buffer
2991         std::string s = os.str();
2992         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
2993         // Send as reliable
2994         m_clients.send(peer_id, 0, data, true);
2995 }
2996
2997 void Server::SendAccessDenied(u16 peer_id,const std::wstring &reason)
2998 {
2999         DSTACK(__FUNCTION_NAME);
3000         std::ostringstream os(std::ios_base::binary);
3001
3002         writeU16(os, TOCLIENT_ACCESS_DENIED);
3003         os<<serializeWideString(reason);
3004
3005         // Make data buffer
3006         std::string s = os.str();
3007         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3008         // Send as reliable
3009         m_clients.send(peer_id, 0, data, true);
3010 }
3011
3012 void Server::SendDeathscreen(u16 peer_id,bool set_camera_point_target,
3013                 v3f camera_point_target)
3014 {
3015         DSTACK(__FUNCTION_NAME);
3016         std::ostringstream os(std::ios_base::binary);
3017
3018         writeU16(os, TOCLIENT_DEATHSCREEN);
3019         writeU8(os, set_camera_point_target);
3020         writeV3F1000(os, camera_point_target);
3021
3022         // Make data buffer
3023         std::string s = os.str();
3024         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3025         // Send as reliable
3026         m_clients.send(peer_id, 0, data, true);
3027 }
3028
3029 void Server::SendItemDef(u16 peer_id,
3030                 IItemDefManager *itemdef, u16 protocol_version)
3031 {
3032         DSTACK(__FUNCTION_NAME);
3033         std::ostringstream os(std::ios_base::binary);
3034
3035         /*
3036                 u16 command
3037                 u32 length of the next item
3038                 zlib-compressed serialized ItemDefManager
3039         */
3040         writeU16(os, TOCLIENT_ITEMDEF);
3041         std::ostringstream tmp_os(std::ios::binary);
3042         itemdef->serialize(tmp_os, protocol_version);
3043         std::ostringstream tmp_os2(std::ios::binary);
3044         compressZlib(tmp_os.str(), tmp_os2);
3045         os<<serializeLongString(tmp_os2.str());
3046
3047         // Make data buffer
3048         std::string s = os.str();
3049         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3050                         <<"): size="<<s.size()<<std::endl;
3051         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3052         // Send as reliable
3053         m_clients.send(peer_id, 0, data, true);
3054 }
3055
3056 void Server::SendNodeDef(u16 peer_id,
3057                 INodeDefManager *nodedef, u16 protocol_version)
3058 {
3059         DSTACK(__FUNCTION_NAME);
3060         std::ostringstream os(std::ios_base::binary);
3061
3062         /*
3063                 u16 command
3064                 u32 length of the next item
3065                 zlib-compressed serialized NodeDefManager
3066         */
3067         writeU16(os, TOCLIENT_NODEDEF);
3068         std::ostringstream tmp_os(std::ios::binary);
3069         nodedef->serialize(tmp_os, protocol_version);
3070         std::ostringstream tmp_os2(std::ios::binary);
3071         compressZlib(tmp_os.str(), tmp_os2);
3072         os<<serializeLongString(tmp_os2.str());
3073
3074         // Make data buffer
3075         std::string s = os.str();
3076         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3077                         <<"): size="<<s.size()<<std::endl;
3078         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3079         // Send as reliable
3080         m_clients.send(peer_id, 0, data, true);
3081 }
3082
3083 /*
3084         Non-static send methods
3085 */
3086
3087 void Server::SendInventory(u16 peer_id)
3088 {
3089         DSTACK(__FUNCTION_NAME);
3090
3091         PlayerSAO *playersao = getPlayerSAO(peer_id);
3092         assert(playersao);
3093
3094         playersao->m_inventory_not_sent = false;
3095
3096         /*
3097                 Serialize it
3098         */
3099
3100         std::ostringstream os;
3101         playersao->getInventory()->serialize(os);
3102
3103         std::string s = os.str();
3104
3105         SharedBuffer<u8> data(s.size()+2);
3106         writeU16(&data[0], TOCLIENT_INVENTORY);
3107         memcpy(&data[2], s.c_str(), s.size());
3108
3109         // Send as reliable
3110         m_clients.send(peer_id, 0, data, true);
3111 }
3112
3113 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3114 {
3115         DSTACK(__FUNCTION_NAME);
3116
3117         std::ostringstream os(std::ios_base::binary);
3118         u8 buf[12];
3119
3120         // Write command
3121         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3122         os.write((char*)buf, 2);
3123
3124         // Write length
3125         writeU16(buf, message.size());
3126         os.write((char*)buf, 2);
3127
3128         // Write string
3129         for(u32 i=0; i<message.size(); i++)
3130         {
3131                 u16 w = message[i];
3132                 writeU16(buf, w);
3133                 os.write((char*)buf, 2);
3134         }
3135
3136         // Make data buffer
3137         std::string s = os.str();
3138         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3139
3140         if (peer_id != PEER_ID_INEXISTENT)
3141         {
3142                 // Send as reliable
3143                 m_clients.send(peer_id, 0, data, true);
3144         }
3145         else
3146         {
3147                 m_clients.sendToAll(0,data,true);
3148         }
3149 }
3150
3151 void Server::SendShowFormspecMessage(u16 peer_id, const std::string &formspec,
3152                                      const std::string &formname)
3153 {
3154         DSTACK(__FUNCTION_NAME);
3155
3156         std::ostringstream os(std::ios_base::binary);
3157         u8 buf[12];
3158
3159         // Write command
3160         writeU16(buf, TOCLIENT_SHOW_FORMSPEC);
3161         os.write((char*)buf, 2);
3162         os<<serializeLongString(formspec);
3163         os<<serializeString(formname);
3164
3165         // Make data buffer
3166         std::string s = os.str();
3167         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3168         // Send as reliable
3169         m_clients.send(peer_id, 0, data, true);
3170 }
3171
3172 // Spawns a particle on peer with peer_id
3173 void Server::SendSpawnParticle(u16 peer_id, v3f pos, v3f velocity, v3f acceleration,
3174                                 float expirationtime, float size, bool collisiondetection,
3175                                 bool vertical, std::string texture)
3176 {
3177         DSTACK(__FUNCTION_NAME);
3178
3179         std::ostringstream os(std::ios_base::binary);
3180         writeU16(os, TOCLIENT_SPAWN_PARTICLE);
3181         writeV3F1000(os, pos);
3182         writeV3F1000(os, velocity);
3183         writeV3F1000(os, acceleration);
3184         writeF1000(os, expirationtime);
3185         writeF1000(os, size);
3186         writeU8(os,  collisiondetection);
3187         os<<serializeLongString(texture);
3188         writeU8(os, vertical);
3189
3190         // Make data buffer
3191         std::string s = os.str();
3192         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3193
3194         if (peer_id != PEER_ID_INEXISTENT)
3195         {
3196         // Send as reliable
3197                 m_clients.send(peer_id, 0, data, true);
3198         }
3199         else
3200         {
3201                 m_clients.sendToAll(0,data,true);
3202         }
3203 }
3204
3205 // Adds a ParticleSpawner on peer with peer_id
3206 void Server::SendAddParticleSpawner(u16 peer_id, u16 amount, float spawntime, v3f minpos, v3f maxpos,
3207         v3f minvel, v3f maxvel, v3f minacc, v3f maxacc, float minexptime, float maxexptime,
3208         float minsize, float maxsize, bool collisiondetection, bool vertical, std::string texture, u32 id)
3209 {
3210         DSTACK(__FUNCTION_NAME);
3211
3212         std::ostringstream os(std::ios_base::binary);
3213         writeU16(os, TOCLIENT_ADD_PARTICLESPAWNER);
3214
3215         writeU16(os, amount);
3216         writeF1000(os, spawntime);
3217         writeV3F1000(os, minpos);
3218         writeV3F1000(os, maxpos);
3219         writeV3F1000(os, minvel);
3220         writeV3F1000(os, maxvel);
3221         writeV3F1000(os, minacc);
3222         writeV3F1000(os, maxacc);
3223         writeF1000(os, minexptime);
3224         writeF1000(os, maxexptime);
3225         writeF1000(os, minsize);
3226         writeF1000(os, maxsize);
3227         writeU8(os,  collisiondetection);
3228         os<<serializeLongString(texture);
3229         writeU32(os, id);
3230         writeU8(os, vertical);
3231
3232         // Make data buffer
3233         std::string s = os.str();
3234         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3235
3236         if (peer_id != PEER_ID_INEXISTENT)
3237         {
3238                 // Send as reliable
3239                 m_clients.send(peer_id, 0, data, true);
3240         }
3241         else {
3242                 m_clients.sendToAll(0,data,true);
3243         }
3244 }
3245
3246 void Server::SendDeleteParticleSpawner(u16 peer_id, u32 id)
3247 {
3248         DSTACK(__FUNCTION_NAME);
3249
3250         std::ostringstream os(std::ios_base::binary);
3251         writeU16(os, TOCLIENT_DELETE_PARTICLESPAWNER);
3252
3253         writeU16(os, id);
3254
3255         // Make data buffer
3256         std::string s = os.str();
3257         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3258
3259         if (peer_id != PEER_ID_INEXISTENT) {
3260                 // Send as reliable
3261                 m_clients.send(peer_id, 0, data, true);
3262         }
3263         else {
3264                 m_clients.sendToAll(0,data,true);
3265         }
3266
3267 }
3268
3269 void Server::SendHUDAdd(u16 peer_id, u32 id, HudElement *form)
3270 {
3271         std::ostringstream os(std::ios_base::binary);
3272
3273         // Write command
3274         writeU16(os, TOCLIENT_HUDADD);
3275         writeU32(os, id);
3276         writeU8(os, (u8)form->type);
3277         writeV2F1000(os, form->pos);
3278         os << serializeString(form->name);
3279         writeV2F1000(os, form->scale);
3280         os << serializeString(form->text);
3281         writeU32(os, form->number);
3282         writeU32(os, form->item);
3283         writeU32(os, form->dir);
3284         writeV2F1000(os, form->align);
3285         writeV2F1000(os, form->offset);
3286         writeV3F1000(os, form->world_pos);
3287         writeV2S32(os,form->size);
3288
3289         // Make data buffer
3290         std::string s = os.str();
3291         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3292         // Send as reliable
3293         m_clients.send(peer_id, 1, data, true);
3294 }
3295
3296 void Server::SendHUDRemove(u16 peer_id, u32 id)
3297 {
3298         std::ostringstream os(std::ios_base::binary);
3299
3300         // Write command
3301         writeU16(os, TOCLIENT_HUDRM);
3302         writeU32(os, id);
3303
3304         // Make data buffer
3305         std::string s = os.str();
3306         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3307         // Send as reliable
3308
3309         m_clients.send(peer_id, 1, data, true);
3310 }
3311
3312 void Server::SendHUDChange(u16 peer_id, u32 id, HudElementStat stat, void *value)
3313 {
3314         std::ostringstream os(std::ios_base::binary);
3315
3316         // Write command
3317         writeU16(os, TOCLIENT_HUDCHANGE);
3318         writeU32(os, id);
3319         writeU8(os, (u8)stat);
3320         switch (stat) {
3321                 case HUD_STAT_POS:
3322                 case HUD_STAT_SCALE:
3323                 case HUD_STAT_ALIGN:
3324                 case HUD_STAT_OFFSET:
3325                         writeV2F1000(os, *(v2f *)value);
3326                         break;
3327                 case HUD_STAT_NAME:
3328                 case HUD_STAT_TEXT:
3329                         os << serializeString(*(std::string *)value);
3330                         break;
3331                 case HUD_STAT_WORLD_POS:
3332                         writeV3F1000(os, *(v3f *)value);
3333                         break;
3334                 case HUD_STAT_SIZE:
3335                         writeV2S32(os,*(v2s32 *)value);
3336                         break;
3337                 case HUD_STAT_NUMBER:
3338                 case HUD_STAT_ITEM:
3339                 case HUD_STAT_DIR:
3340                 default:
3341                         writeU32(os, *(u32 *)value);
3342                         break;
3343         }
3344
3345         // Make data buffer
3346         std::string s = os.str();
3347         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3348         // Send as reliable
3349         m_clients.send(peer_id, 0, data, true);
3350 }
3351
3352 void Server::SendHUDSetFlags(u16 peer_id, u32 flags, u32 mask)
3353 {
3354         std::ostringstream os(std::ios_base::binary);
3355
3356         // Write command
3357         writeU16(os, TOCLIENT_HUD_SET_FLAGS);
3358         writeU32(os, flags);
3359         writeU32(os, mask);
3360
3361         // Make data buffer
3362         std::string s = os.str();
3363         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3364         // Send as reliable
3365         m_clients.send(peer_id, 0, data, true);
3366 }
3367
3368 void Server::SendHUDSetParam(u16 peer_id, u16 param, const std::string &value)
3369 {
3370         std::ostringstream os(std::ios_base::binary);
3371
3372         // Write command
3373         writeU16(os, TOCLIENT_HUD_SET_PARAM);
3374         writeU16(os, param);
3375         os<<serializeString(value);
3376
3377         // Make data buffer
3378         std::string s = os.str();
3379         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3380         // Send as reliable
3381         m_clients.send(peer_id, 0, data, true);
3382 }
3383
3384 void Server::SendSetSky(u16 peer_id, const video::SColor &bgcolor,
3385                 const std::string &type, const std::vector<std::string> &params)
3386 {
3387         std::ostringstream os(std::ios_base::binary);
3388
3389         // Write command
3390         writeU16(os, TOCLIENT_SET_SKY);
3391         writeARGB8(os, bgcolor);
3392         os<<serializeString(type);
3393         writeU16(os, params.size());
3394         for(size_t i=0; i<params.size(); i++)
3395                 os<<serializeString(params[i]);
3396
3397         // Make data buffer
3398         std::string s = os.str();
3399         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3400         // Send as reliable
3401         m_clients.send(peer_id, 0, data, true);
3402 }
3403
3404 void Server::SendOverrideDayNightRatio(u16 peer_id, bool do_override,
3405                 float ratio)
3406 {
3407         std::ostringstream os(std::ios_base::binary);
3408
3409         // Write command
3410         writeU16(os, TOCLIENT_OVERRIDE_DAY_NIGHT_RATIO);
3411         writeU8(os, do_override);
3412         writeU16(os, ratio*65535);
3413
3414         // Make data buffer
3415         std::string s = os.str();
3416         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3417         // Send as reliable
3418         m_clients.send(peer_id, 0, data, true);
3419 }
3420
3421 void Server::SendTimeOfDay(u16 peer_id, u16 time, f32 time_speed)
3422 {
3423         DSTACK(__FUNCTION_NAME);
3424
3425         // Make packet
3426         SharedBuffer<u8> data(2+2+4);
3427         writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
3428         writeU16(&data[2], time);
3429         writeF1000(&data[4], time_speed);
3430
3431         if (peer_id == PEER_ID_INEXISTENT) {
3432                 m_clients.sendToAll(0,data,true);
3433         }
3434         else {
3435                 // Send as reliable
3436                 m_clients.send(peer_id, 0, data, true);
3437         }
3438 }
3439
3440 void Server::SendPlayerHP(u16 peer_id)
3441 {
3442         DSTACK(__FUNCTION_NAME);
3443         PlayerSAO *playersao = getPlayerSAO(peer_id);
3444         assert(playersao);
3445         playersao->m_hp_not_sent = false;
3446         SendHP(peer_id, playersao->getHP());
3447         m_script->player_event(playersao,"health_changed");
3448
3449         // Send to other clients
3450         std::string str = gob_cmd_punched(playersao->readDamage(), playersao->getHP());
3451         ActiveObjectMessage aom(playersao->getId(), true, str);
3452         playersao->m_messages_out.push_back(aom);
3453 }
3454
3455 void Server::SendPlayerBreath(u16 peer_id)
3456 {
3457         DSTACK(__FUNCTION_NAME);
3458         PlayerSAO *playersao = getPlayerSAO(peer_id);
3459         assert(playersao);
3460         playersao->m_breath_not_sent = false;
3461         m_script->player_event(playersao,"breath_changed");
3462         SendBreath(peer_id, playersao->getBreath());
3463 }
3464
3465 void Server::SendMovePlayer(u16 peer_id)
3466 {
3467         DSTACK(__FUNCTION_NAME);
3468         Player *player = m_env->getPlayer(peer_id);
3469         assert(player);
3470
3471         std::ostringstream os(std::ios_base::binary);
3472         writeU16(os, TOCLIENT_MOVE_PLAYER);
3473         writeV3F1000(os, player->getPosition());
3474         writeF1000(os, player->getPitch());
3475         writeF1000(os, player->getYaw());
3476
3477         {
3478                 v3f pos = player->getPosition();
3479                 f32 pitch = player->getPitch();
3480                 f32 yaw = player->getYaw();
3481                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3482                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3483                                 <<" pitch="<<pitch
3484                                 <<" yaw="<<yaw
3485                                 <<std::endl;
3486         }
3487
3488         // Make data buffer
3489         std::string s = os.str();
3490         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3491         // Send as reliable
3492         m_clients.send(peer_id, 0, data, true);
3493 }
3494
3495 void Server::SendLocalPlayerAnimations(u16 peer_id, v2s32 animation_frames[4], f32 animation_speed)
3496 {
3497         std::ostringstream os(std::ios_base::binary);
3498
3499         writeU16(os, TOCLIENT_LOCAL_PLAYER_ANIMATIONS);
3500         writeV2S32(os, animation_frames[0]);
3501         writeV2S32(os, animation_frames[1]);
3502         writeV2S32(os, animation_frames[2]);
3503         writeV2S32(os, animation_frames[3]);
3504         writeF1000(os, animation_speed);
3505
3506         // Make data buffer
3507         std::string s = os.str();
3508         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3509         // Send as reliable
3510         m_clients.send(peer_id, 0, data, true);
3511 }
3512
3513 void Server::SendEyeOffset(u16 peer_id, v3f first, v3f third)
3514 {
3515         std::ostringstream os(std::ios_base::binary);
3516
3517         writeU16(os, TOCLIENT_EYE_OFFSET);
3518         writeV3F1000(os, first);
3519         writeV3F1000(os, third);
3520
3521         // Make data buffer
3522         std::string s = os.str();
3523         SharedBuffer<u8> data((u8 *)s.c_str(), s.size());
3524         // Send as reliable
3525         m_clients.send(peer_id, 0, data, true);
3526 }
3527 void Server::SendPlayerPrivileges(u16 peer_id)
3528 {
3529         Player *player = m_env->getPlayer(peer_id);
3530         assert(player);
3531         if(player->peer_id == PEER_ID_INEXISTENT)
3532                 return;
3533
3534         std::set<std::string> privs;
3535         m_script->getAuth(player->getName(), NULL, &privs);
3536
3537         std::ostringstream os(std::ios_base::binary);
3538         writeU16(os, TOCLIENT_PRIVILEGES);
3539         writeU16(os, privs.size());
3540         for(std::set<std::string>::const_iterator i = privs.begin();
3541                         i != privs.end(); i++){
3542                 os<<serializeString(*i);
3543         }
3544
3545         // Make data buffer
3546         std::string s = os.str();
3547         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3548         // Send as reliable
3549         m_clients.send(peer_id, 0, data, true);
3550 }
3551
3552 void Server::SendPlayerInventoryFormspec(u16 peer_id)
3553 {
3554         Player *player = m_env->getPlayer(peer_id);
3555         assert(player);
3556         if(player->peer_id == PEER_ID_INEXISTENT)
3557                 return;
3558
3559         std::ostringstream os(std::ios_base::binary);
3560         writeU16(os, TOCLIENT_INVENTORY_FORMSPEC);
3561         os<<serializeLongString(player->inventory_formspec);
3562
3563         // Make data buffer
3564         std::string s = os.str();
3565         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3566         // Send as reliable
3567         m_clients.send(peer_id, 0, data, true);
3568 }
3569
3570 s32 Server::playSound(const SimpleSoundSpec &spec,
3571                 const ServerSoundParams &params)
3572 {
3573         // Find out initial position of sound
3574         bool pos_exists = false;
3575         v3f pos = params.getPos(m_env, &pos_exists);
3576         // If position is not found while it should be, cancel sound
3577         if(pos_exists != (params.type != ServerSoundParams::SSP_LOCAL))
3578                 return -1;
3579
3580         // Filter destination clients
3581         std::list<u16> dst_clients;
3582         if(params.to_player != "")
3583         {
3584                 Player *player = m_env->getPlayer(params.to_player.c_str());
3585                 if(!player){
3586                         infostream<<"Server::playSound: Player \""<<params.to_player
3587                                         <<"\" not found"<<std::endl;
3588                         return -1;
3589                 }
3590                 if(player->peer_id == PEER_ID_INEXISTENT){
3591                         infostream<<"Server::playSound: Player \""<<params.to_player
3592                                         <<"\" not connected"<<std::endl;
3593                         return -1;
3594                 }
3595                 dst_clients.push_back(player->peer_id);
3596         }
3597         else
3598         {
3599                 std::list<u16> clients = m_clients.getClientIDs();
3600
3601                 for(std::list<u16>::iterator
3602                                 i = clients.begin(); i != clients.end(); ++i)
3603                 {
3604                         Player *player = m_env->getPlayer(*i);
3605                         if(!player)
3606                                 continue;
3607                         if(pos_exists){
3608                                 if(player->getPosition().getDistanceFrom(pos) >
3609                                                 params.max_hear_distance)
3610                                         continue;
3611                         }
3612                         dst_clients.push_back(*i);
3613                 }
3614         }
3615         if(dst_clients.size() == 0)
3616                 return -1;
3617
3618         // Create the sound
3619         s32 id = m_next_sound_id++;
3620         // The sound will exist as a reference in m_playing_sounds
3621         m_playing_sounds[id] = ServerPlayingSound();
3622         ServerPlayingSound &psound = m_playing_sounds[id];
3623         psound.params = params;
3624         for(std::list<u16>::iterator i = dst_clients.begin();
3625                         i != dst_clients.end(); i++)
3626                 psound.clients.insert(*i);
3627         // Create packet
3628         std::ostringstream os(std::ios_base::binary);
3629         writeU16(os, TOCLIENT_PLAY_SOUND);
3630         writeS32(os, id);
3631         os<<serializeString(spec.name);
3632         writeF1000(os, spec.gain * params.gain);
3633         writeU8(os, params.type);
3634         writeV3F1000(os, pos);
3635         writeU16(os, params.object);
3636         writeU8(os, params.loop);
3637         // Make data buffer
3638         std::string s = os.str();
3639         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3640         // Send
3641         for(std::list<u16>::iterator i = dst_clients.begin();
3642                         i != dst_clients.end(); i++){
3643                 // Send as reliable
3644                 m_clients.send(*i, 0, data, true);
3645         }
3646         return id;
3647 }
3648 void Server::stopSound(s32 handle)
3649 {
3650         // Get sound reference
3651         std::map<s32, ServerPlayingSound>::iterator i =
3652                         m_playing_sounds.find(handle);
3653         if(i == m_playing_sounds.end())
3654                 return;
3655         ServerPlayingSound &psound = i->second;
3656         // Create packet
3657         std::ostringstream os(std::ios_base::binary);
3658         writeU16(os, TOCLIENT_STOP_SOUND);
3659         writeS32(os, handle);
3660         // Make data buffer
3661         std::string s = os.str();
3662         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3663         // Send
3664         for(std::set<u16>::iterator i = psound.clients.begin();
3665                         i != psound.clients.end(); i++){
3666                 // Send as reliable
3667                 m_clients.send(*i, 0, data, true);
3668         }
3669         // Remove sound reference
3670         m_playing_sounds.erase(i);
3671 }
3672
3673 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3674         std::list<u16> *far_players, float far_d_nodes)
3675 {
3676         float maxd = far_d_nodes*BS;
3677         v3f p_f = intToFloat(p, BS);
3678
3679         // Create packet
3680         u32 replysize = 8;
3681         SharedBuffer<u8> reply(replysize);
3682         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3683         writeS16(&reply[2], p.X);
3684         writeS16(&reply[4], p.Y);
3685         writeS16(&reply[6], p.Z);
3686
3687         std::list<u16> clients = m_clients.getClientIDs();
3688         for(std::list<u16>::iterator
3689                 i = clients.begin();
3690                 i != clients.end(); ++i)
3691         {
3692                 if(far_players)
3693                 {
3694                         // Get player
3695                         Player *player = m_env->getPlayer(*i);
3696                         if(player)
3697                         {
3698                                 // If player is far away, only set modified blocks not sent
3699                                 v3f player_pos = player->getPosition();
3700                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3701                                 {
3702                                         far_players->push_back(*i);
3703                                         continue;
3704                                 }
3705                         }
3706                 }
3707
3708                 // Send as reliable
3709                 m_clients.send(*i, 0, reply, true);
3710         }
3711 }
3712
3713 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3714                 std::list<u16> *far_players, float far_d_nodes,
3715                 bool remove_metadata)
3716 {
3717         float maxd = far_d_nodes*BS;
3718         v3f p_f = intToFloat(p, BS);
3719
3720         std::list<u16> clients = m_clients.getClientIDs();
3721                 for(std::list<u16>::iterator
3722                         i = clients.begin();
3723                         i != clients.end(); ++i)
3724                 {
3725
3726                 if(far_players)
3727                 {
3728                         // Get player
3729                         Player *player = m_env->getPlayer(*i);
3730                         if(player)
3731                         {
3732                                 // If player is far away, only set modified blocks not sent
3733                                 v3f player_pos = player->getPosition();
3734                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3735                                 {
3736                                         far_players->push_back(*i);
3737                                         continue;
3738                                 }
3739                         }
3740                 }
3741                 SharedBuffer<u8> reply(0);
3742                 m_clients.Lock();
3743                 RemoteClient* client = m_clients.lockedGetClientNoEx(*i);
3744                 if (client != 0)
3745                 {
3746                         // Create packet
3747                         u32 replysize = 9 + MapNode::serializedLength(client->serialization_version);
3748                         reply = SharedBuffer<u8>(replysize);
3749                         writeU16(&reply[0], TOCLIENT_ADDNODE);
3750                         writeS16(&reply[2], p.X);
3751                         writeS16(&reply[4], p.Y);
3752                         writeS16(&reply[6], p.Z);
3753                         n.serialize(&reply[8], client->serialization_version);
3754                         u32 index = 8 + MapNode::serializedLength(client->serialization_version);
3755                         writeU8(&reply[index], remove_metadata ? 0 : 1);
3756
3757                         if (!remove_metadata) {
3758                                 if (client->net_proto_version <= 21) {
3759                                         // Old clients always clear metadata; fix it
3760                                         // by sending the full block again.
3761                                         client->SetBlockNotSent(p);
3762                                 }
3763                         }
3764                 }
3765                 m_clients.Unlock();
3766
3767                 // Send as reliable
3768                 if (reply.getSize() > 0)
3769                         m_clients.send(*i, 0, reply, true);
3770         }
3771 }
3772
3773 void Server::setBlockNotSent(v3s16 p)
3774 {
3775         std::list<u16> clients = m_clients.getClientIDs();
3776         m_clients.Lock();
3777         for(std::list<u16>::iterator
3778                 i = clients.begin();
3779                 i != clients.end(); ++i)
3780         {
3781                 RemoteClient *client = m_clients.lockedGetClientNoEx(*i);
3782                 client->SetBlockNotSent(p);
3783         }
3784         m_clients.Unlock();
3785 }
3786
3787 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver, u16 net_proto_version)
3788 {
3789         DSTACK(__FUNCTION_NAME);
3790
3791         v3s16 p = block->getPos();
3792
3793 #if 0
3794         // Analyze it a bit
3795         bool completely_air = true;
3796         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3797         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3798         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3799         {
3800                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3801                 {
3802                         completely_air = false;
3803                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3804                 }
3805         }
3806
3807         // Print result
3808         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3809         if(completely_air)
3810                 infostream<<"[completely air] ";
3811         infostream<<std::endl;
3812 #endif
3813
3814         /*
3815                 Create a packet with the block in the right format
3816         */
3817
3818         std::ostringstream os(std::ios_base::binary);
3819         block->serialize(os, ver, false);
3820         block->serializeNetworkSpecific(os, net_proto_version);
3821         std::string s = os.str();
3822         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3823
3824         u32 replysize = 8 + blockdata.getSize();
3825         SharedBuffer<u8> reply(replysize);
3826         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3827         writeS16(&reply[2], p.X);
3828         writeS16(&reply[4], p.Y);
3829         writeS16(&reply[6], p.Z);
3830         memcpy(&reply[8], *blockdata, blockdata.getSize());
3831
3832         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3833                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3834
3835         /*
3836                 Send packet
3837         */
3838         m_clients.send(peer_id, 2, reply, true);
3839 }
3840
3841 void Server::SendBlocks(float dtime)
3842 {
3843         DSTACK(__FUNCTION_NAME);
3844
3845         JMutexAutoLock envlock(m_env_mutex);
3846         //TODO check if one big lock could be faster then multiple small ones
3847
3848         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
3849
3850         std::vector<PrioritySortedBlockTransfer> queue;
3851
3852         s32 total_sending = 0;
3853
3854         {
3855                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3856
3857                 std::list<u16> clients = m_clients.getClientIDs();
3858
3859                 m_clients.Lock();
3860                 for(std::list<u16>::iterator
3861                         i = clients.begin();
3862                         i != clients.end(); ++i)
3863                 {
3864                         RemoteClient *client = m_clients.lockedGetClientNoEx(*i,Active);
3865
3866                         if (client == NULL)
3867                                 return;
3868
3869                         total_sending += client->SendingCount();
3870                         client->GetNextBlocks(m_env,m_emerge, dtime, queue);
3871                 }
3872                 m_clients.Unlock();
3873         }
3874
3875         // Sort.
3876         // Lowest priority number comes first.
3877         // Lowest is most important.
3878         std::sort(queue.begin(), queue.end());
3879
3880         m_clients.Lock();
3881         for(u32 i=0; i<queue.size(); i++)
3882         {
3883                 //TODO: Calculate limit dynamically
3884                 if(total_sending >= g_settings->getS32
3885                                 ("max_simultaneous_block_sends_server_total"))
3886                         break;
3887
3888                 PrioritySortedBlockTransfer q = queue[i];
3889
3890                 MapBlock *block = NULL;
3891                 try
3892                 {
3893                         block = m_env->getMap().getBlockNoCreate(q.pos);
3894                 }
3895                 catch(InvalidPositionException &e)
3896                 {
3897                         continue;
3898                 }
3899
3900                 RemoteClient *client = m_clients.lockedGetClientNoEx(q.peer_id,Active);
3901
3902                 if(!client)
3903                         continue;
3904
3905                 SendBlockNoLock(q.peer_id, block, client->serialization_version, client->net_proto_version);
3906
3907                 client->SentBlock(q.pos);
3908                 total_sending++;
3909         }
3910         m_clients.Unlock();
3911 }
3912
3913 void Server::fillMediaCache()
3914 {
3915         DSTACK(__FUNCTION_NAME);
3916
3917         infostream<<"Server: Calculating media file checksums"<<std::endl;
3918
3919         // Collect all media file paths
3920         std::list<std::string> paths;
3921         for(std::vector<ModSpec>::iterator i = m_mods.begin();
3922                         i != m_mods.end(); i++){
3923                 const ModSpec &mod = *i;
3924                 paths.push_back(mod.path + DIR_DELIM + "textures");
3925                 paths.push_back(mod.path + DIR_DELIM + "sounds");
3926                 paths.push_back(mod.path + DIR_DELIM + "media");
3927                 paths.push_back(mod.path + DIR_DELIM + "models");
3928         }
3929         paths.push_back(porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
3930
3931         // Collect media file information from paths into cache
3932         for(std::list<std::string>::iterator i = paths.begin();
3933                         i != paths.end(); i++)
3934         {
3935                 std::string mediapath = *i;
3936                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(mediapath);
3937                 for(u32 j=0; j<dirlist.size(); j++){
3938                         if(dirlist[j].dir) // Ignode dirs
3939                                 continue;
3940                         std::string filename = dirlist[j].name;
3941                         // If name contains illegal characters, ignore the file
3942                         if(!string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)){
3943                                 infostream<<"Server: ignoring illegal file name: \""
3944                                                 <<filename<<"\""<<std::endl;
3945                                 continue;
3946                         }
3947                         // If name is not in a supported format, ignore it
3948                         const char *supported_ext[] = {
3949                                 ".png", ".jpg", ".bmp", ".tga",
3950                                 ".pcx", ".ppm", ".psd", ".wal", ".rgb",
3951                                 ".ogg",
3952                                 ".x", ".b3d", ".md2", ".obj",
3953                                 NULL
3954                         };
3955                         if(removeStringEnd(filename, supported_ext) == ""){
3956                                 infostream<<"Server: ignoring unsupported file extension: \""
3957                                                 <<filename<<"\""<<std::endl;
3958                                 continue;
3959                         }
3960                         // Ok, attempt to load the file and add to cache
3961                         std::string filepath = mediapath + DIR_DELIM + filename;
3962                         // Read data
3963                         std::ifstream fis(filepath.c_str(), std::ios_base::binary);
3964                         if(fis.good() == false){
3965                                 errorstream<<"Server::fillMediaCache(): Could not open \""
3966                                                 <<filename<<"\" for reading"<<std::endl;
3967                                 continue;
3968                         }
3969                         std::ostringstream tmp_os(std::ios_base::binary);
3970                         bool bad = false;
3971                         for(;;){
3972                                 char buf[1024];
3973                                 fis.read(buf, 1024);
3974                                 std::streamsize len = fis.gcount();
3975                                 tmp_os.write(buf, len);
3976                                 if(fis.eof())
3977                                         break;
3978                                 if(!fis.good()){
3979                                         bad = true;
3980                                         break;
3981                                 }
3982                         }
3983                         if(bad){
3984                                 errorstream<<"Server::fillMediaCache(): Failed to read \""
3985                                                 <<filename<<"\""<<std::endl;
3986                                 continue;
3987                         }
3988                         if(tmp_os.str().length() == 0){
3989                                 errorstream<<"Server::fillMediaCache(): Empty file \""
3990                                                 <<filepath<<"\""<<std::endl;
3991                                 continue;
3992                         }
3993
3994                         SHA1 sha1;
3995                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
3996
3997                         unsigned char *digest = sha1.getDigest();
3998                         std::string sha1_base64 = base64_encode(digest, 20);
3999                         std::string sha1_hex = hex_encode((char*)digest, 20);
4000                         free(digest);
4001
4002                         // Put in list
4003                         this->m_media[filename] = MediaInfo(filepath, sha1_base64);
4004                         verbosestream<<"Server: "<<sha1_hex<<" is "<<filename<<std::endl;
4005                 }
4006         }
4007 }
4008
4009 struct SendableMediaAnnouncement
4010 {
4011         std::string name;
4012         std::string sha1_digest;
4013
4014         SendableMediaAnnouncement(const std::string &name_="",
4015                                   const std::string &sha1_digest_=""):
4016                 name(name_),
4017                 sha1_digest(sha1_digest_)
4018         {}
4019 };
4020
4021 void Server::sendMediaAnnouncement(u16 peer_id)
4022 {
4023         DSTACK(__FUNCTION_NAME);
4024
4025         verbosestream<<"Server: Announcing files to id("<<peer_id<<")"
4026                         <<std::endl;
4027
4028         std::list<SendableMediaAnnouncement> file_announcements;
4029
4030         for(std::map<std::string, MediaInfo>::iterator i = m_media.begin();
4031                         i != m_media.end(); i++){
4032                 // Put in list
4033                 file_announcements.push_back(
4034                                 SendableMediaAnnouncement(i->first, i->second.sha1_digest));
4035         }
4036
4037         // Make packet
4038         std::ostringstream os(std::ios_base::binary);
4039
4040         /*
4041                 u16 command
4042                 u32 number of files
4043                 for each texture {
4044                         u16 length of name
4045                         string name
4046                         u16 length of sha1_digest
4047                         string sha1_digest
4048                 }
4049         */
4050
4051         writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
4052         writeU16(os, file_announcements.size());
4053
4054         for(std::list<SendableMediaAnnouncement>::iterator
4055                         j = file_announcements.begin();
4056                         j != file_announcements.end(); ++j){
4057                 os<<serializeString(j->name);
4058                 os<<serializeString(j->sha1_digest);
4059         }
4060         os<<serializeString(g_settings->get("remote_media"));
4061
4062         // Make data buffer
4063         std::string s = os.str();
4064         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4065
4066         // Send as reliable
4067         m_clients.send(peer_id, 0, data, true);
4068 }
4069
4070 struct SendableMedia
4071 {
4072         std::string name;
4073         std::string path;
4074         std::string data;
4075
4076         SendableMedia(const std::string &name_="", const std::string &path_="",
4077                       const std::string &data_=""):
4078                 name(name_),
4079                 path(path_),
4080                 data(data_)
4081         {}
4082 };
4083
4084 void Server::sendRequestedMedia(u16 peer_id,
4085                 const std::list<std::string> &tosend)
4086 {
4087         DSTACK(__FUNCTION_NAME);
4088
4089         verbosestream<<"Server::sendRequestedMedia(): "
4090                         <<"Sending files to client"<<std::endl;
4091
4092         /* Read files */
4093
4094         // Put 5kB in one bunch (this is not accurate)
4095         u32 bytes_per_bunch = 5000;
4096
4097         std::vector< std::list<SendableMedia> > file_bunches;
4098         file_bunches.push_back(std::list<SendableMedia>());
4099
4100         u32 file_size_bunch_total = 0;
4101
4102         for(std::list<std::string>::const_iterator i = tosend.begin();
4103                         i != tosend.end(); ++i)
4104         {
4105                 const std::string &name = *i;
4106
4107                 if(m_media.find(name) == m_media.end()){
4108                         errorstream<<"Server::sendRequestedMedia(): Client asked for "
4109                                         <<"unknown file \""<<(name)<<"\""<<std::endl;
4110                         continue;
4111                 }
4112
4113                 //TODO get path + name
4114                 std::string tpath = m_media[name].path;
4115
4116                 // Read data
4117                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
4118                 if(fis.good() == false){
4119                         errorstream<<"Server::sendRequestedMedia(): Could not open \""
4120                                         <<tpath<<"\" for reading"<<std::endl;
4121                         continue;
4122                 }
4123                 std::ostringstream tmp_os(std::ios_base::binary);
4124                 bool bad = false;
4125                 for(;;){
4126                         char buf[1024];
4127                         fis.read(buf, 1024);
4128                         std::streamsize len = fis.gcount();
4129                         tmp_os.write(buf, len);
4130                         file_size_bunch_total += len;
4131                         if(fis.eof())
4132                                 break;
4133                         if(!fis.good()){
4134                                 bad = true;
4135                                 break;
4136                         }
4137                 }
4138                 if(bad){
4139                         errorstream<<"Server::sendRequestedMedia(): Failed to read \""
4140                                         <<name<<"\""<<std::endl;
4141                         continue;
4142                 }
4143                 /*infostream<<"Server::sendRequestedMedia(): Loaded \""
4144                                 <<tname<<"\""<<std::endl;*/
4145                 // Put in list
4146                 file_bunches[file_bunches.size()-1].push_back(
4147                                 SendableMedia(name, tpath, tmp_os.str()));
4148
4149                 // Start next bunch if got enough data
4150                 if(file_size_bunch_total >= bytes_per_bunch){
4151                         file_bunches.push_back(std::list<SendableMedia>());
4152                         file_size_bunch_total = 0;
4153                 }
4154
4155         }
4156
4157         /* Create and send packets */
4158
4159         u32 num_bunches = file_bunches.size();
4160         for(u32 i=0; i<num_bunches; i++)
4161         {
4162                 std::ostringstream os(std::ios_base::binary);
4163
4164                 /*
4165                         u16 command
4166                         u16 total number of texture bunches
4167                         u16 index of this bunch
4168                         u32 number of files in this bunch
4169                         for each file {
4170                                 u16 length of name
4171                                 string name
4172                                 u32 length of data
4173                                 data
4174                         }
4175                 */
4176
4177                 writeU16(os, TOCLIENT_MEDIA);
4178                 writeU16(os, num_bunches);
4179                 writeU16(os, i);
4180                 writeU32(os, file_bunches[i].size());
4181
4182                 for(std::list<SendableMedia>::iterator
4183                                 j = file_bunches[i].begin();
4184                                 j != file_bunches[i].end(); ++j){
4185                         os<<serializeString(j->name);
4186                         os<<serializeLongString(j->data);
4187                 }
4188
4189                 // Make data buffer
4190                 std::string s = os.str();
4191                 verbosestream<<"Server::sendRequestedMedia(): bunch "
4192                                 <<i<<"/"<<num_bunches
4193                                 <<" files="<<file_bunches[i].size()
4194                                 <<" size=" <<s.size()<<std::endl;
4195                 SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4196                 // Send as reliable
4197                 m_clients.send(peer_id, 2, data, true);
4198         }
4199 }
4200
4201 void Server::sendDetachedInventory(const std::string &name, u16 peer_id)
4202 {
4203         if(m_detached_inventories.count(name) == 0){
4204                 errorstream<<__FUNCTION_NAME<<": \""<<name<<"\" not found"<<std::endl;
4205                 return;
4206         }
4207         Inventory *inv = m_detached_inventories[name];
4208
4209         std::ostringstream os(std::ios_base::binary);
4210         writeU16(os, TOCLIENT_DETACHED_INVENTORY);
4211         os<<serializeString(name);
4212         inv->serialize(os);
4213
4214         // Make data buffer
4215         std::string s = os.str();
4216         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4217
4218         if (peer_id != PEER_ID_INEXISTENT)
4219         {
4220                 // Send as reliable
4221                 m_clients.send(peer_id, 0, data, true);
4222         }
4223         else
4224         {
4225                 m_clients.sendToAll(0,data,true);
4226         }
4227 }
4228
4229 void Server::sendDetachedInventories(u16 peer_id)
4230 {
4231         DSTACK(__FUNCTION_NAME);
4232
4233         for(std::map<std::string, Inventory*>::iterator
4234                         i = m_detached_inventories.begin();
4235                         i != m_detached_inventories.end(); i++){
4236                 const std::string &name = i->first;
4237                 //Inventory *inv = i->second;
4238                 sendDetachedInventory(name, peer_id);
4239         }
4240 }
4241
4242 /*
4243         Something random
4244 */
4245
4246 void Server::DiePlayer(u16 peer_id)
4247 {
4248         DSTACK(__FUNCTION_NAME);
4249
4250         PlayerSAO *playersao = getPlayerSAO(peer_id);
4251         assert(playersao);
4252
4253         infostream<<"Server::DiePlayer(): Player "
4254                         <<playersao->getPlayer()->getName()
4255                         <<" dies"<<std::endl;
4256
4257         playersao->setHP(0);
4258
4259         // Trigger scripted stuff
4260         m_script->on_dieplayer(playersao);
4261
4262         SendPlayerHP(peer_id);
4263         SendDeathscreen(peer_id, false, v3f(0,0,0));
4264 }
4265
4266 void Server::RespawnPlayer(u16 peer_id)
4267 {
4268         DSTACK(__FUNCTION_NAME);
4269
4270         PlayerSAO *playersao = getPlayerSAO(peer_id);
4271         assert(playersao);
4272
4273         infostream<<"Server::RespawnPlayer(): Player "
4274                         <<playersao->getPlayer()->getName()
4275                         <<" respawns"<<std::endl;
4276
4277         playersao->setHP(PLAYER_MAX_HP);
4278
4279         bool repositioned = m_script->on_respawnplayer(playersao);
4280         if(!repositioned){
4281                 v3f pos = findSpawnPos(m_env->getServerMap());
4282                 playersao->setPos(pos);
4283         }
4284 }
4285
4286 void Server::DenyAccess(u16 peer_id, const std::wstring &reason)
4287 {
4288         DSTACK(__FUNCTION_NAME);
4289
4290         SendAccessDenied(peer_id, reason);
4291         m_clients.event(peer_id,SetDenied);
4292         m_con.DisconnectPeer(peer_id);
4293 }
4294
4295 void Server::DeleteClient(u16 peer_id, ClientDeletionReason reason)
4296 {
4297         DSTACK(__FUNCTION_NAME);
4298         std::wstring message;
4299         {
4300                 /*
4301                         Clear references to playing sounds
4302                 */
4303                 for(std::map<s32, ServerPlayingSound>::iterator
4304                                 i = m_playing_sounds.begin();
4305                                 i != m_playing_sounds.end();)
4306                 {
4307                         ServerPlayingSound &psound = i->second;
4308                         psound.clients.erase(peer_id);
4309                         if(psound.clients.size() == 0)
4310                                 m_playing_sounds.erase(i++);
4311                         else
4312                                 i++;
4313                 }
4314
4315                 Player *player = m_env->getPlayer(peer_id);
4316
4317                 // Collect information about leaving in chat
4318                 {
4319                         if(player != NULL && reason != CDR_DENY)
4320                         {
4321                                 std::wstring name = narrow_to_wide(player->getName());
4322                                 message += L"*** ";
4323                                 message += name;
4324                                 message += L" left the game.";
4325                                 if(reason == CDR_TIMEOUT)
4326                                         message += L" (timed out)";
4327                         }
4328                 }
4329
4330                 /* Run scripts and remove from environment */
4331                 {
4332                         if(player != NULL)
4333                         {
4334                                 PlayerSAO *playersao = player->getPlayerSAO();
4335                                 assert(playersao);
4336
4337                                 m_script->on_leaveplayer(playersao);
4338
4339                                 playersao->disconnected();
4340                         }
4341                 }
4342
4343                 /*
4344                         Print out action
4345                 */
4346                 {
4347                         if(player != NULL && reason != CDR_DENY)
4348                         {
4349                                 std::ostringstream os(std::ios_base::binary);
4350                                 std::list<u16> clients = m_clients.getClientIDs();
4351
4352                                 for(std::list<u16>::iterator
4353                                         i = clients.begin();
4354                                         i != clients.end(); ++i)
4355                                 {
4356                                         // Get player
4357                                         Player *player = m_env->getPlayer(*i);
4358                                         if(!player)
4359                                                 continue;
4360                                         // Get name of player
4361                                         os<<player->getName()<<" ";
4362                                 }
4363
4364                                 actionstream<<player->getName()<<" "
4365                                                 <<(reason==CDR_TIMEOUT?"times out.":"leaves game.")
4366                                                 <<" List of players: "<<os.str()<<std::endl;
4367                         }
4368                 }
4369                 {
4370                         JMutexAutoLock env_lock(m_env_mutex);
4371                         m_clients.DeleteClient(peer_id);
4372                 }
4373         }
4374
4375         // Send leave chat message to all remaining clients
4376         if(message.length() != 0)
4377                 SendChatMessage(PEER_ID_INEXISTENT,message);
4378 }
4379
4380 void Server::UpdateCrafting(u16 peer_id)
4381 {
4382         DSTACK(__FUNCTION_NAME);
4383
4384         Player* player = m_env->getPlayer(peer_id);
4385         assert(player);
4386
4387         // Get a preview for crafting
4388         ItemStack preview;
4389         InventoryLocation loc;
4390         loc.setPlayer(player->getName());
4391         getCraftingResult(&player->inventory, preview, false, this);
4392         m_env->getScriptIface()->item_CraftPredict(preview, player->getPlayerSAO(), (&player->inventory)->getList("craft"), loc);
4393
4394         // Put the new preview in
4395         InventoryList *plist = player->inventory.getList("craftpreview");
4396         assert(plist);
4397         assert(plist->getSize() >= 1);
4398         plist->changeItem(0, preview);
4399 }
4400
4401 RemoteClient* Server::getClient(u16 peer_id, ClientState state_min)
4402 {
4403         RemoteClient *client = getClientNoEx(peer_id,state_min);
4404         if(!client)
4405                 throw ClientNotFoundException("Client not found");
4406
4407         return client;
4408 }
4409 RemoteClient* Server::getClientNoEx(u16 peer_id, ClientState state_min)
4410 {
4411         return m_clients.getClientNoEx(peer_id, state_min);
4412 }
4413
4414 std::string Server::getPlayerName(u16 peer_id)
4415 {
4416         Player *player = m_env->getPlayer(peer_id);
4417         if(player == NULL)
4418                 return "[id="+itos(peer_id)+"]";
4419         return player->getName();
4420 }
4421
4422 PlayerSAO* Server::getPlayerSAO(u16 peer_id)
4423 {
4424         Player *player = m_env->getPlayer(peer_id);
4425         if(player == NULL)
4426                 return NULL;
4427         return player->getPlayerSAO();
4428 }
4429
4430 std::wstring Server::getStatusString()
4431 {
4432         std::wostringstream os(std::ios_base::binary);
4433         os<<L"# Server: ";
4434         // Version
4435         os<<L"version="<<narrow_to_wide(minetest_version_simple);
4436         // Uptime
4437         os<<L", uptime="<<m_uptime.get();
4438         // Max lag estimate
4439         os<<L", max_lag="<<m_env->getMaxLagEstimate();
4440         // Information about clients
4441         bool first = true;
4442         os<<L", clients={";
4443         std::list<u16> clients = m_clients.getClientIDs();
4444         for(std::list<u16>::iterator i = clients.begin();
4445                 i != clients.end(); ++i)
4446         {
4447                 // Get player
4448                 Player *player = m_env->getPlayer(*i);
4449                 // Get name of player
4450                 std::wstring name = L"unknown";
4451                 if(player != NULL)
4452                         name = narrow_to_wide(player->getName());
4453                 // Add name to information string
4454                 if(!first)
4455                         os<<L",";
4456                 else
4457                         first = false;
4458                 os<<name;
4459         }
4460         os<<L"}";
4461         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4462                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4463         if(g_settings->get("motd") != "")
4464                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4465         return os.str();
4466 }
4467
4468 std::set<std::string> Server::getPlayerEffectivePrivs(const std::string &name)
4469 {
4470         std::set<std::string> privs;
4471         m_script->getAuth(name, NULL, &privs);
4472         return privs;
4473 }
4474
4475 bool Server::checkPriv(const std::string &name, const std::string &priv)
4476 {
4477         std::set<std::string> privs = getPlayerEffectivePrivs(name);
4478         return (privs.count(priv) != 0);
4479 }
4480
4481 void Server::reportPrivsModified(const std::string &name)
4482 {
4483         if(name == ""){
4484                 std::list<u16> clients = m_clients.getClientIDs();
4485                 for(std::list<u16>::iterator
4486                                 i = clients.begin();
4487                                 i != clients.end(); ++i){
4488                         Player *player = m_env->getPlayer(*i);
4489                         reportPrivsModified(player->getName());
4490                 }
4491         } else {
4492                 Player *player = m_env->getPlayer(name.c_str());
4493                 if(!player)
4494                         return;
4495                 SendPlayerPrivileges(player->peer_id);
4496                 PlayerSAO *sao = player->getPlayerSAO();
4497                 if(!sao)
4498                         return;
4499                 sao->updatePrivileges(
4500                                 getPlayerEffectivePrivs(name),
4501                                 isSingleplayer());
4502         }
4503 }
4504
4505 void Server::reportInventoryFormspecModified(const std::string &name)
4506 {
4507         Player *player = m_env->getPlayer(name.c_str());
4508         if(!player)
4509                 return;
4510         SendPlayerInventoryFormspec(player->peer_id);
4511 }
4512
4513 void Server::setIpBanned(const std::string &ip, const std::string &name)
4514 {
4515         m_banmanager->add(ip, name);
4516 }
4517
4518 void Server::unsetIpBanned(const std::string &ip_or_name)
4519 {
4520         m_banmanager->remove(ip_or_name);
4521 }
4522
4523 std::string Server::getBanDescription(const std::string &ip_or_name)
4524 {
4525         return m_banmanager->getBanDescription(ip_or_name);
4526 }
4527
4528 void Server::notifyPlayer(const char *name, const std::wstring &msg)
4529 {
4530         Player *player = m_env->getPlayer(name);
4531         if(!player)
4532                 return;
4533
4534         if (player->peer_id == PEER_ID_INEXISTENT)
4535                 return;
4536
4537         SendChatMessage(player->peer_id, msg);
4538 }
4539
4540 bool Server::showFormspec(const char *playername, const std::string &formspec, const std::string &formname)
4541 {
4542         Player *player = m_env->getPlayer(playername);
4543
4544         if(!player)
4545         {
4546                 infostream<<"showFormspec: couldn't find player:"<<playername<<std::endl;
4547                 return false;
4548         }
4549
4550         SendShowFormspecMessage(player->peer_id, formspec, formname);
4551         return true;
4552 }
4553
4554 u32 Server::hudAdd(Player *player, HudElement *form) {
4555         if (!player)
4556                 return -1;
4557
4558         u32 id = player->getFreeHudID();
4559         if (id < player->hud.size())
4560                 player->hud[id] = form;
4561         else
4562                 player->hud.push_back(form);
4563         
4564         SendHUDAdd(player->peer_id, id, form);
4565         return id;
4566 }
4567
4568 bool Server::hudRemove(Player *player, u32 id) {
4569         if (!player || id >= player->hud.size() || !player->hud[id])
4570                 return false;
4571
4572         delete player->hud[id];
4573         player->hud[id] = NULL;
4574         
4575         SendHUDRemove(player->peer_id, id);
4576         return true;
4577 }
4578
4579 bool Server::hudChange(Player *player, u32 id, HudElementStat stat, void *data) {
4580         if (!player)
4581                 return false;
4582
4583         SendHUDChange(player->peer_id, id, stat, data);
4584         return true;
4585 }
4586
4587 bool Server::hudSetFlags(Player *player, u32 flags, u32 mask) {
4588         if (!player)
4589                 return false;
4590
4591         SendHUDSetFlags(player->peer_id, flags, mask);
4592
4593         m_script->player_event(player->getPlayerSAO(),"hud_changed");
4594         return true;
4595 }
4596
4597 bool Server::hudSetHotbarItemcount(Player *player, s32 hotbar_itemcount) {
4598         if (!player)
4599                 return false;
4600         if (hotbar_itemcount <= 0 || hotbar_itemcount > HUD_HOTBAR_ITEMCOUNT_MAX)
4601                 return false;
4602
4603         std::ostringstream os(std::ios::binary);
4604         writeS32(os, hotbar_itemcount);
4605         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_ITEMCOUNT, os.str());
4606         return true;
4607 }
4608
4609 void Server::hudSetHotbarImage(Player *player, std::string name) {
4610         if (!player)
4611                 return;
4612
4613         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_IMAGE, name);
4614 }
4615
4616 void Server::hudSetHotbarSelectedImage(Player *player, std::string name) {
4617         if (!player)
4618                 return;
4619
4620         SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name);
4621 }
4622
4623 bool Server::setLocalPlayerAnimations(Player *player, v2s32 animation_frames[4], f32 frame_speed)
4624 {
4625         if (!player)
4626                 return false;
4627
4628         SendLocalPlayerAnimations(player->peer_id, animation_frames, frame_speed);
4629         return true;
4630 }
4631
4632 bool Server::setPlayerEyeOffset(Player *player, v3f first, v3f third)
4633 {
4634         if (!player)
4635                 return false;
4636
4637         SendEyeOffset(player->peer_id, first, third);
4638         return true;
4639 }
4640
4641 bool Server::setSky(Player *player, const video::SColor &bgcolor,
4642                 const std::string &type, const std::vector<std::string> &params)
4643 {
4644         if (!player)
4645                 return false;
4646
4647         SendSetSky(player->peer_id, bgcolor, type, params);
4648         return true;
4649 }
4650
4651 bool Server::overrideDayNightRatio(Player *player, bool do_override,
4652                 float ratio)
4653 {
4654         if (!player)
4655                 return false;
4656
4657         SendOverrideDayNightRatio(player->peer_id, do_override, ratio);
4658         return true;
4659 }
4660
4661 void Server::notifyPlayers(const std::wstring &msg)
4662 {
4663         SendChatMessage(PEER_ID_INEXISTENT,msg);
4664 }
4665
4666 void Server::spawnParticle(const char *playername, v3f pos,
4667                 v3f velocity, v3f acceleration,
4668                 float expirationtime, float size, bool
4669                 collisiondetection, bool vertical, std::string texture)
4670 {
4671         Player *player = m_env->getPlayer(playername);
4672         if(!player)
4673                 return;
4674         SendSpawnParticle(player->peer_id, pos, velocity, acceleration,
4675                         expirationtime, size, collisiondetection, vertical, texture);
4676 }
4677
4678 void Server::spawnParticleAll(v3f pos, v3f velocity, v3f acceleration,
4679                 float expirationtime, float size,
4680                 bool collisiondetection, bool vertical, std::string texture)
4681 {
4682         SendSpawnParticle(PEER_ID_INEXISTENT,pos, velocity, acceleration,
4683                         expirationtime, size, collisiondetection, vertical, texture);
4684 }
4685
4686 u32 Server::addParticleSpawner(const char *playername,
4687                 u16 amount, float spawntime,
4688                 v3f minpos, v3f maxpos,
4689                 v3f minvel, v3f maxvel,
4690                 v3f minacc, v3f maxacc,
4691                 float minexptime, float maxexptime,
4692                 float minsize, float maxsize,
4693                 bool collisiondetection, bool vertical, std::string texture)
4694 {
4695         Player *player = m_env->getPlayer(playername);
4696         if(!player)
4697                 return -1;
4698
4699         u32 id = 0;
4700         for(;;) // look for unused particlespawner id
4701         {
4702                 id++;
4703                 if (std::find(m_particlespawner_ids.begin(),
4704                                 m_particlespawner_ids.end(), id)
4705                                 == m_particlespawner_ids.end())
4706                 {
4707                         m_particlespawner_ids.push_back(id);
4708                         break;
4709                 }
4710         }
4711
4712         SendAddParticleSpawner(player->peer_id, amount, spawntime,
4713                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4714                 minexptime, maxexptime, minsize, maxsize,
4715                 collisiondetection, vertical, texture, id);
4716
4717         return id;
4718 }
4719
4720 u32 Server::addParticleSpawnerAll(u16 amount, float spawntime,
4721                 v3f minpos, v3f maxpos,
4722                 v3f minvel, v3f maxvel,
4723                 v3f minacc, v3f maxacc,
4724                 float minexptime, float maxexptime,
4725                 float minsize, float maxsize,
4726                 bool collisiondetection, bool vertical, std::string texture)
4727 {
4728         u32 id = 0;
4729         for(;;) // look for unused particlespawner id
4730         {
4731                 id++;
4732                 if (std::find(m_particlespawner_ids.begin(),
4733                                 m_particlespawner_ids.end(), id)
4734                                 == m_particlespawner_ids.end())
4735                 {
4736                         m_particlespawner_ids.push_back(id);
4737                         break;
4738                 }
4739         }
4740
4741         SendAddParticleSpawner(PEER_ID_INEXISTENT, amount, spawntime,
4742                 minpos, maxpos, minvel, maxvel, minacc, maxacc,
4743                 minexptime, maxexptime, minsize, maxsize,
4744                 collisiondetection, vertical, texture, id);
4745
4746         return id;
4747 }
4748
4749 void Server::deleteParticleSpawner(const char *playername, u32 id)
4750 {
4751         Player *player = m_env->getPlayer(playername);
4752         if(!player)
4753                 return;
4754
4755         m_particlespawner_ids.erase(
4756                         std::remove(m_particlespawner_ids.begin(),
4757                         m_particlespawner_ids.end(), id),
4758                         m_particlespawner_ids.end());
4759         SendDeleteParticleSpawner(player->peer_id, id);
4760 }
4761
4762 void Server::deleteParticleSpawnerAll(u32 id)
4763 {
4764         m_particlespawner_ids.erase(
4765                         std::remove(m_particlespawner_ids.begin(),
4766                         m_particlespawner_ids.end(), id),
4767                         m_particlespawner_ids.end());
4768         SendDeleteParticleSpawner(PEER_ID_INEXISTENT, id);
4769 }
4770
4771 Inventory* Server::createDetachedInventory(const std::string &name)
4772 {
4773         if(m_detached_inventories.count(name) > 0){
4774                 infostream<<"Server clearing detached inventory \""<<name<<"\""<<std::endl;
4775                 delete m_detached_inventories[name];
4776         } else {
4777                 infostream<<"Server creating detached inventory \""<<name<<"\""<<std::endl;
4778         }
4779         Inventory *inv = new Inventory(m_itemdef);
4780         assert(inv);
4781         m_detached_inventories[name] = inv;
4782         //TODO find a better way to do this
4783         sendDetachedInventory(name,PEER_ID_INEXISTENT);
4784         return inv;
4785 }
4786
4787 class BoolScopeSet
4788 {
4789 public:
4790         BoolScopeSet(bool *dst, bool val):
4791                 m_dst(dst)
4792         {
4793                 m_orig_state = *m_dst;
4794                 *m_dst = val;
4795         }
4796         ~BoolScopeSet()
4797         {
4798                 *m_dst = m_orig_state;
4799         }
4800 private:
4801         bool *m_dst;
4802         bool m_orig_state;
4803 };
4804
4805 // actions: time-reversed list
4806 // Return value: success/failure
4807 bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
4808                 std::list<std::string> *log)
4809 {
4810         infostream<<"Server::rollbackRevertActions(len="<<actions.size()<<")"<<std::endl;
4811         ServerMap *map = (ServerMap*)(&m_env->getMap());
4812         // Disable rollback report sink while reverting
4813         BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
4814
4815         // Fail if no actions to handle
4816         if(actions.empty()){
4817                 log->push_back("Nothing to do.");
4818                 return false;
4819         }
4820
4821         int num_tried = 0;
4822         int num_failed = 0;
4823
4824         for(std::list<RollbackAction>::const_iterator
4825                         i = actions.begin();
4826                         i != actions.end(); i++)
4827         {
4828                 const RollbackAction &action = *i;
4829                 num_tried++;
4830                 bool success = action.applyRevert(map, this, this);
4831                 if(!success){
4832                         num_failed++;
4833                         std::ostringstream os;
4834                         os<<"Revert of step ("<<num_tried<<") "<<action.toString()<<" failed";
4835                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4836                         if(log)
4837                                 log->push_back(os.str());
4838                 }else{
4839                         std::ostringstream os;
4840                         os<<"Successfully reverted step ("<<num_tried<<") "<<action.toString();
4841                         infostream<<"Map::rollbackRevertActions(): "<<os.str()<<std::endl;
4842                         if(log)
4843                                 log->push_back(os.str());
4844                 }
4845         }
4846
4847         infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
4848                         <<" failed"<<std::endl;
4849
4850         // Call it done if less than half failed
4851         return num_failed <= num_tried/2;
4852 }
4853
4854 // IGameDef interface
4855 // Under envlock
4856 IItemDefManager* Server::getItemDefManager()
4857 {
4858         return m_itemdef;
4859 }
4860 INodeDefManager* Server::getNodeDefManager()
4861 {
4862         return m_nodedef;
4863 }
4864 ICraftDefManager* Server::getCraftDefManager()
4865 {
4866         return m_craftdef;
4867 }
4868 ITextureSource* Server::getTextureSource()
4869 {
4870         return NULL;
4871 }
4872 IShaderSource* Server::getShaderSource()
4873 {
4874         return NULL;
4875 }
4876 u16 Server::allocateUnknownNodeId(const std::string &name)
4877 {
4878         return m_nodedef->allocateDummy(name);
4879 }
4880 ISoundManager* Server::getSoundManager()
4881 {
4882         return &dummySoundManager;
4883 }
4884 MtEventManager* Server::getEventManager()
4885 {
4886         return m_event;
4887 }
4888 IRollbackReportSink* Server::getRollbackReportSink()
4889 {
4890         if(!m_enable_rollback_recording)
4891                 return NULL;
4892         if(!m_rollback_sink_enabled)
4893                 return NULL;
4894         return m_rollback;
4895 }
4896
4897 IWritableItemDefManager* Server::getWritableItemDefManager()
4898 {
4899         return m_itemdef;
4900 }
4901 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4902 {
4903         return m_nodedef;
4904 }
4905 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4906 {
4907         return m_craftdef;
4908 }
4909
4910 const ModSpec* Server::getModSpec(const std::string &modname)
4911 {
4912         for(std::vector<ModSpec>::iterator i = m_mods.begin();
4913                         i != m_mods.end(); i++){
4914                 const ModSpec &mod = *i;
4915                 if(mod.name == modname)
4916                         return &mod;
4917         }
4918         return NULL;
4919 }
4920 void Server::getModNames(std::list<std::string> &modlist)
4921 {
4922         for(std::vector<ModSpec>::iterator i = m_mods.begin(); i != m_mods.end(); i++)
4923         {
4924                 modlist.push_back(i->name);
4925         }
4926 }
4927 std::string Server::getBuiltinLuaPath()
4928 {
4929         return porting::path_share + DIR_DELIM + "builtin";
4930 }
4931
4932 v3f findSpawnPos(ServerMap &map)
4933 {
4934         //return v3f(50,50,50)*BS;
4935
4936         v3s16 nodepos;
4937
4938 #if 0
4939         nodepos = v2s16(0,0);
4940         groundheight = 20;
4941 #endif
4942
4943 #if 1
4944         s16 water_level = map.getWaterLevel();
4945
4946         // Try to find a good place a few times
4947         for(s32 i=0; i<1000; i++)
4948         {
4949                 s32 range = 1 + i;
4950                 // We're going to try to throw the player to this position
4951                 v2s16 nodepos2d = v2s16(
4952                                 -range + (myrand() % (range * 2)),
4953                                 -range + (myrand() % (range * 2)));
4954
4955                 // Get ground height at point
4956                 s16 groundheight = map.findGroundLevel(nodepos2d);
4957                 if (groundheight <= water_level) // Don't go underwater
4958                         continue;
4959                 if (groundheight > water_level + 6) // Don't go to high places
4960                         continue;
4961
4962                 nodepos = v3s16(nodepos2d.X, groundheight, nodepos2d.Y);
4963                 bool is_good = false;
4964                 s32 air_count = 0;
4965                 for (s32 i = 0; i < 10; i++) {
4966                         v3s16 blockpos = getNodeBlockPos(nodepos);
4967                         map.emergeBlock(blockpos, true);
4968                         content_t c = map.getNodeNoEx(nodepos).getContent();
4969                         if (c == CONTENT_AIR || c == CONTENT_IGNORE) {
4970                                 air_count++;
4971                                 if (air_count >= 2){
4972                                         is_good = true;
4973                                         break;
4974                                 }
4975                         }
4976                         nodepos.Y++;
4977                 }
4978                 if(is_good){
4979                         // Found a good place
4980                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4981                         break;
4982                 }
4983         }
4984 #endif
4985
4986         return intToFloat(nodepos, BS);
4987 }
4988
4989 PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
4990 {
4991         RemotePlayer *player = NULL;
4992         bool newplayer = false;
4993
4994         /*
4995                 Try to get an existing player
4996         */
4997         player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
4998
4999         // If player is already connected, cancel
5000         if(player != NULL && player->peer_id != 0)
5001         {
5002                 infostream<<"emergePlayer(): Player already connected"<<std::endl;
5003                 return NULL;
5004         }
5005
5006         /*
5007                 If player with the wanted peer_id already exists, cancel.
5008         */
5009         if(m_env->getPlayer(peer_id) != NULL)
5010         {
5011                 infostream<<"emergePlayer(): Player with wrong name but same"
5012                                 " peer_id already exists"<<std::endl;
5013                 return NULL;
5014         }
5015
5016         /*
5017                 Create a new player if it doesn't exist yet
5018         */
5019         if(player == NULL)
5020         {
5021                 newplayer = true;
5022                 player = new RemotePlayer(this);
5023                 player->updateName(name);
5024
5025                 /* Set player position */
5026                 infostream<<"Server: Finding spawn place for player \""
5027                                 <<name<<"\""<<std::endl;
5028                 v3f pos = findSpawnPos(m_env->getServerMap());
5029                 player->setPosition(pos);
5030
5031                 /* Add player to environment */
5032                 m_env->addPlayer(player);
5033         }
5034
5035         /*
5036                 Create a new player active object
5037         */
5038         PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id,
5039                         getPlayerEffectivePrivs(player->getName()),
5040                         isSingleplayer());
5041
5042         /* Clean up old HUD elements from previous sessions */
5043         player->hud.clear();
5044
5045         /* Add object to environment */
5046         m_env->addActiveObject(playersao);
5047
5048         /* Run scripts */
5049         if(newplayer)
5050                 m_script->on_newplayer(playersao);
5051
5052         return playersao;
5053 }
5054
5055 void dedicated_server_loop(Server &server, bool &kill)
5056 {
5057         DSTACK(__FUNCTION_NAME);
5058
5059         verbosestream<<"dedicated_server_loop()"<<std::endl;
5060
5061         IntervalLimiter m_profiler_interval;
5062
5063         for(;;)
5064         {
5065                 float steplen = g_settings->getFloat("dedicated_server_step");
5066                 // This is kind of a hack but can be done like this
5067                 // because server.step() is very light
5068                 {
5069                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
5070                         sleep_ms((int)(steplen*1000.0));
5071                 }
5072                 server.step(steplen);
5073
5074                 if(server.getShutdownRequested() || kill)
5075                 {
5076                         infostream<<"Dedicated server quitting"<<std::endl;
5077 #if USE_CURL
5078                         if(g_settings->getBool("server_announce") == true)
5079                                 ServerList::sendAnnounce("delete");
5080 #endif
5081                         break;
5082                 }
5083
5084                 /*
5085                         Profiler
5086                 */
5087                 float profiler_print_interval =
5088                                 g_settings->getFloat("profiler_print_interval");
5089                 if(profiler_print_interval != 0)
5090                 {
5091                         if(m_profiler_interval.step(steplen, profiler_print_interval))
5092                         {
5093                                 infostream<<"Profiler:"<<std::endl;
5094                                 g_profiler->print(infostream);
5095                                 g_profiler->clear();
5096                         }
5097                 }
5098         }
5099 }
5100
5101