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