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