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