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