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