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