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