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