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