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