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