Mention world location at server startup at action level
[oweals/minetest.git] / src / server.cpp
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 General Public License as published by
7 the Free Software Foundation; either version 2 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 General Public License for more details.
14
15 You should have received a copy of the GNU 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 "utility.h"
22 #include <iostream>
23 #include <queue>
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 "servercommand.h"
32 #include "filesys.h"
33 #include "content_mapnode.h"
34 #include "content_nodemeta.h"
35 #include "mapblock.h"
36 #include "serverobject.h"
37 #include "settings.h"
38 #include "profiler.h"
39 #include "log.h"
40 #include "script.h"
41 #include "scriptapi.h"
42 #include "nodedef.h"
43 #include "itemdef.h"
44 #include "craftdef.h"
45 #include "mapgen.h"
46 #include "content_abm.h"
47 #include "mods.h"
48 #include "sha1.h"
49 #include "base64.h"
50 #include "tool.h"
51 #include "utility_string.h"
52
53 #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
54
55 #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
56
57 class MapEditEventIgnorer
58 {
59 public:
60         MapEditEventIgnorer(bool *flag):
61                 m_flag(flag)
62         {
63                 if(*m_flag == false)
64                         *m_flag = true;
65                 else
66                         m_flag = NULL;
67         }
68
69         ~MapEditEventIgnorer()
70         {
71                 if(m_flag)
72                 {
73                         assert(*m_flag);
74                         *m_flag = false;
75                 }
76         }
77         
78 private:
79         bool *m_flag;
80 };
81
82 void * ServerThread::Thread()
83 {
84         ThreadStarted();
85
86         log_register_thread("ServerThread");
87
88         DSTACK(__FUNCTION_NAME);
89
90         BEGIN_DEBUG_EXCEPTION_HANDLER
91
92         while(getRun())
93         {
94                 try{
95                         //TimeTaker timer("AsyncRunStep() + Receive()");
96
97                         {
98                                 //TimeTaker timer("AsyncRunStep()");
99                                 m_server->AsyncRunStep();
100                         }
101                 
102                         //infostream<<"Running m_server->Receive()"<<std::endl;
103                         m_server->Receive();
104                 }
105                 catch(con::NoIncomingDataException &e)
106                 {
107                 }
108                 catch(con::PeerNotFoundException &e)
109                 {
110                         infostream<<"Server: PeerNotFoundException"<<std::endl;
111                 }
112         }
113         
114         END_DEBUG_EXCEPTION_HANDLER(errorstream)
115
116         return NULL;
117 }
118
119 void * EmergeThread::Thread()
120 {
121         ThreadStarted();
122
123         log_register_thread("EmergeThread");
124
125         DSTACK(__FUNCTION_NAME);
126
127         BEGIN_DEBUG_EXCEPTION_HANDLER
128
129         bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
130         
131         /*
132                 Get block info from queue, emerge them and send them
133                 to clients.
134
135                 After queue is empty, exit.
136         */
137         while(getRun())
138         {
139                 QueuedBlockEmerge *qptr = m_server->m_emerge_queue.pop();
140                 if(qptr == NULL)
141                         break;
142                 
143                 SharedPtr<QueuedBlockEmerge> q(qptr);
144
145                 v3s16 &p = q->pos;
146                 v2s16 p2d(p.X,p.Z);
147
148                 /*
149                         Do not generate over-limit
150                 */
151                 if(blockpos_over_limit(p))
152                         continue;
153                         
154                 //infostream<<"EmergeThread::Thread(): running"<<std::endl;
155
156                 //TimeTaker timer("block emerge");
157                 
158                 /*
159                         Try to emerge it from somewhere.
160
161                         If it is only wanted as optional, only loading from disk
162                         will be allowed.
163                 */
164                 
165                 /*
166                         Check if any peer wants it as non-optional. In that case it
167                         will be generated.
168
169                         Also decrement the emerge queue count in clients.
170                 */
171
172                 bool only_from_disk = true;
173
174                 {
175                         core::map<u16, u8>::Iterator i;
176                         for(i=q->peer_ids.getIterator(); i.atEnd()==false; i++)
177                         {
178                                 //u16 peer_id = i.getNode()->getKey();
179
180                                 // Check flags
181                                 u8 flags = i.getNode()->getValue();
182                                 if((flags & BLOCK_EMERGE_FLAG_FROMDISK) == false)
183                                         only_from_disk = false;
184                                 
185                         }
186                 }
187                 
188                 if(enable_mapgen_debug_info)
189                         infostream<<"EmergeThread: p="
190                                         <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
191                                         <<"only_from_disk="<<only_from_disk<<std::endl;
192                 
193                 ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
194                         
195                 MapBlock *block = NULL;
196                 bool got_block = true;
197                 core::map<v3s16, MapBlock*> modified_blocks;
198
199                 /*
200                         Try to fetch block from memory or disk.
201                         If not found and asked to generate, initialize generator.
202                 */
203                 
204                 bool started_generate = false;
205                 mapgen::BlockMakeData data;
206
207                 {
208                         JMutexAutoLock envlock(m_server->m_env_mutex);
209                         
210                         // Load sector if it isn't loaded
211                         if(map.getSectorNoGenerateNoEx(p2d) == NULL)
212                                 map.loadSectorMeta(p2d);
213                         
214                         // Attempt to load block
215                         block = map.getBlockNoCreateNoEx(p);
216                         if(!block || block->isDummy() || !block->isGenerated())
217                         {
218                                 if(enable_mapgen_debug_info)
219                                         infostream<<"EmergeThread: not in memory, "
220                                                         <<"attempting to load from disk"<<std::endl;
221
222                                 block = map.loadBlock(p);
223                         }
224                         
225                         // If could not load and allowed to generate, start generation
226                         // inside this same envlock
227                         if(only_from_disk == false &&
228                                         (block == NULL || block->isGenerated() == false)){
229                                 if(enable_mapgen_debug_info)
230                                         infostream<<"EmergeThread: generating"<<std::endl;
231                                 started_generate = true;
232
233                                 map.initBlockMake(&data, p);
234                         }
235                 }
236
237                 /*
238                         If generator was initialized, generate now when envlock is free.
239                 */
240                 if(started_generate)
241                 {
242                         {
243                                 ScopeProfiler sp(g_profiler, "EmergeThread: mapgen::make_block",
244                                                 SPT_AVG);
245                                 TimeTaker t("mapgen::make_block()");
246
247                                 mapgen::make_block(&data);
248
249                                 if(enable_mapgen_debug_info == false)
250                                         t.stop(true); // Hide output
251                         }
252                         
253                         do{ // enable break
254                                 // Lock environment again to access the map
255                                 JMutexAutoLock envlock(m_server->m_env_mutex);
256                                 
257                                 ScopeProfiler sp(g_profiler, "EmergeThread: after "
258                                                 "mapgen::make_block (envlock)", SPT_AVG);
259
260                                 // Blit data back on map, update lighting, add mobs and
261                                 // whatever this does
262                                 map.finishBlockMake(&data, modified_blocks);
263
264                                 // Get central block
265                                 block = map.getBlockNoCreateNoEx(p);
266                                 
267                                 // If block doesn't exist, don't try doing anything with it
268                                 // This happens if the block is not in generation boundaries
269                                 if(!block)
270                                         break;
271
272                                 /*
273                                         Do some post-generate stuff
274                                 */
275                                 
276                                 v3s16 minp = block->getPos()*MAP_BLOCKSIZE;
277                                 v3s16 maxp = minp + v3s16(1,1,1)*(MAP_BLOCKSIZE-1);
278                                 scriptapi_environment_on_generated(m_server->m_lua,
279                                                 minp, maxp);
280                                 
281                                 if(enable_mapgen_debug_info)
282                                         infostream<<"EmergeThread: ended up with: "
283                                                         <<analyze_block(block)<<std::endl;
284
285                                 /*
286                                         Ignore map edit events, they will not need to be
287                                         sent to anybody because the block hasn't been sent
288                                         to anybody
289                                 */
290                                 MapEditEventIgnorer ign(&m_server->m_ignore_map_edit_events);
291                                 
292                                 // Activate objects and stuff
293                                 m_server->m_env->activateBlock(block, 0);
294                         }while(false);
295                 }
296
297                 if(block == NULL)
298                         got_block = false;
299                         
300                 /*
301                         Set sent status of modified blocks on clients
302                 */
303         
304                 // NOTE: Server's clients are also behind the connection mutex
305                 JMutexAutoLock lock(m_server->m_con_mutex);
306
307                 /*
308                         Add the originally fetched block to the modified list
309                 */
310                 if(got_block)
311                 {
312                         modified_blocks.insert(p, block);
313                 }
314                 
315                 /*
316                         Set the modified blocks unsent for all the clients
317                 */
318                 
319                 for(core::map<u16, RemoteClient*>::Iterator
320                                 i = m_server->m_clients.getIterator();
321                                 i.atEnd() == false; i++)
322                 {
323                         RemoteClient *client = i.getNode()->getValue();
324                         
325                         if(modified_blocks.size() > 0)
326                         {
327                                 // Remove block from sent history
328                                 client->SetBlocksNotSent(modified_blocks);
329                         }
330                 }
331                 
332         }
333
334         END_DEBUG_EXCEPTION_HANDLER(errorstream)
335
336         log_deregister_thread();
337
338         return NULL;
339 }
340
341 void RemoteClient::GetNextBlocks(Server *server, float dtime,
342                 core::array<PrioritySortedBlockTransfer> &dest)
343 {
344         DSTACK(__FUNCTION_NAME);
345         
346         /*u32 timer_result;
347         TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/
348         
349         // Increment timers
350         m_nothing_to_send_pause_timer -= dtime;
351         m_nearest_unsent_reset_timer += dtime;
352         
353         if(m_nothing_to_send_pause_timer >= 0)
354         {
355                 return;
356         }
357
358         // Won't send anything if already sending
359         if(m_blocks_sending.size() >= g_settings->getU16
360                         ("max_simultaneous_block_sends_per_client"))
361         {
362                 //infostream<<"Not sending any blocks, Queue full."<<std::endl;
363                 return;
364         }
365
366         //TimeTaker timer("RemoteClient::GetNextBlocks");
367         
368         Player *player = server->m_env->getPlayer(peer_id);
369
370         assert(player != NULL);
371
372         v3f playerpos = player->getPosition();
373         v3f playerspeed = player->getSpeed();
374         v3f playerspeeddir(0,0,0);
375         if(playerspeed.getLength() > 1.0*BS)
376                 playerspeeddir = playerspeed / playerspeed.getLength();
377         // Predict to next block
378         v3f playerpos_predicted = playerpos + playerspeeddir*MAP_BLOCKSIZE*BS;
379
380         v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
381
382         v3s16 center = getNodeBlockPos(center_nodepos);
383         
384         // Camera position and direction
385         v3f camera_pos = player->getEyePosition();
386         v3f camera_dir = v3f(0,0,1);
387         camera_dir.rotateYZBy(player->getPitch());
388         camera_dir.rotateXZBy(player->getYaw());
389
390         /*infostream<<"camera_dir=("<<camera_dir.X<<","<<camera_dir.Y<<","
391                         <<camera_dir.Z<<")"<<std::endl;*/
392
393         /*
394                 Get the starting value of the block finder radius.
395         */
396                 
397         if(m_last_center != center)
398         {
399                 m_nearest_unsent_d = 0;
400                 m_last_center = center;
401         }
402
403         /*infostream<<"m_nearest_unsent_reset_timer="
404                         <<m_nearest_unsent_reset_timer<<std::endl;*/
405                         
406         // Reset periodically to workaround for some bugs or stuff
407         if(m_nearest_unsent_reset_timer > 20.0)
408         {
409                 m_nearest_unsent_reset_timer = 0;
410                 m_nearest_unsent_d = 0;
411                 //infostream<<"Resetting m_nearest_unsent_d for "
412                 //              <<server->getPlayerName(peer_id)<<std::endl;
413         }
414
415         //s16 last_nearest_unsent_d = m_nearest_unsent_d;
416         s16 d_start = m_nearest_unsent_d;
417
418         //infostream<<"d_start="<<d_start<<std::endl;
419
420         u16 max_simul_sends_setting = g_settings->getU16
421                         ("max_simultaneous_block_sends_per_client");
422         u16 max_simul_sends_usually = max_simul_sends_setting;
423
424         /*
425                 Check the time from last addNode/removeNode.
426                 
427                 Decrease send rate if player is building stuff.
428         */
429         m_time_from_building += dtime;
430         if(m_time_from_building < g_settings->getFloat(
431                                 "full_block_send_enable_min_time_from_building"))
432         {
433                 max_simul_sends_usually
434                         = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
435         }
436         
437         /*
438                 Number of blocks sending + number of blocks selected for sending
439         */
440         u32 num_blocks_selected = m_blocks_sending.size();
441         
442         /*
443                 next time d will be continued from the d from which the nearest
444                 unsent block was found this time.
445
446                 This is because not necessarily any of the blocks found this
447                 time are actually sent.
448         */
449         s32 new_nearest_unsent_d = -1;
450
451         s16 d_max = g_settings->getS16("max_block_send_distance");
452         s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
453         
454         // Don't loop very much at a time
455         s16 max_d_increment_at_time = 2;
456         if(d_max > d_start + max_d_increment_at_time)
457                 d_max = d_start + max_d_increment_at_time;
458         /*if(d_max_gen > d_start+2)
459                 d_max_gen = d_start+2;*/
460         
461         //infostream<<"Starting from "<<d_start<<std::endl;
462
463         s32 nearest_emerged_d = -1;
464         s32 nearest_emergefull_d = -1;
465         s32 nearest_sent_d = -1;
466         bool queue_is_full = false;
467         
468         s16 d;
469         for(d = d_start; d <= d_max; d++)
470         {
471                 /*errorstream<<"checking d="<<d<<" for "
472                                 <<server->getPlayerName(peer_id)<<std::endl;*/
473                 //infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
474                 
475                 /*
476                         If m_nearest_unsent_d was changed by the EmergeThread
477                         (it can change it to 0 through SetBlockNotSent),
478                         update our d to it.
479                         Else update m_nearest_unsent_d
480                 */
481                 /*if(m_nearest_unsent_d != last_nearest_unsent_d)
482                 {
483                         d = m_nearest_unsent_d;
484                         last_nearest_unsent_d = m_nearest_unsent_d;
485                 }*/
486
487                 /*
488                         Get the border/face dot coordinates of a "d-radiused"
489                         box
490                 */
491                 core::list<v3s16> list;
492                 getFacePositions(list, d);
493                 
494                 core::list<v3s16>::Iterator li;
495                 for(li=list.begin(); li!=list.end(); li++)
496                 {
497                         v3s16 p = *li + center;
498                         
499                         /*
500                                 Send throttling
501                                 - Don't allow too many simultaneous transfers
502                                 - EXCEPT when the blocks are very close
503
504                                 Also, don't send blocks that are already flying.
505                         */
506                         
507                         // Start with the usual maximum
508                         u16 max_simul_dynamic = max_simul_sends_usually;
509                         
510                         // If block is very close, allow full maximum
511                         if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
512                                 max_simul_dynamic = max_simul_sends_setting;
513
514                         // Don't select too many blocks for sending
515                         if(num_blocks_selected >= max_simul_dynamic)
516                         {
517                                 queue_is_full = true;
518                                 goto queue_full_break;
519                         }
520                         
521                         // Don't send blocks that are currently being transferred
522                         if(m_blocks_sending.find(p) != NULL)
523                                 continue;
524                 
525                         /*
526                                 Do not go over-limit
527                         */
528                         if(p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
529                         || p.X > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
530                         || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
531                         || p.Y > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
532                         || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
533                         || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
534                                 continue;
535                 
536                         // If this is true, inexistent block will be made from scratch
537                         bool generate = d <= d_max_gen;
538                         
539                         {
540                                 /*// Limit the generating area vertically to 2/3
541                                 if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
542                                         generate = false;*/
543
544                                 // Limit the send area vertically to 1/2
545                                 if(abs(p.Y - center.Y) > d_max / 2)
546                                         continue;
547                         }
548
549 #if 0
550                         /*
551                                 If block is far away, don't generate it unless it is
552                                 near ground level.
553                         */
554                         if(d >= 4)
555                         {
556         #if 1
557                                 // Block center y in nodes
558                                 f32 y = (f32)(p.Y * MAP_BLOCKSIZE + MAP_BLOCKSIZE/2);
559                                 // Don't generate if it's very high or very low
560                                 if(y < -64 || y > 64)
561                                         generate = false;
562         #endif
563         #if 0
564                                 v2s16 p2d_nodes_center(
565                                         MAP_BLOCKSIZE*p.X,
566                                         MAP_BLOCKSIZE*p.Z);
567                                 
568                                 // Get ground height in nodes
569                                 s16 gh = server->m_env->getServerMap().findGroundLevel(
570                                                 p2d_nodes_center);
571
572                                 // If differs a lot, don't generate
573                                 if(fabs(gh - y) > MAP_BLOCKSIZE*2)
574                                         generate = false;
575                                         // Actually, don't even send it
576                                         //continue;
577         #endif
578                         }
579 #endif
580
581                         //infostream<<"d="<<d<<std::endl;
582 #if 1
583                         /*
584                                 Don't generate or send if not in sight
585                                 FIXME This only works if the client uses a small enough
586                                 FOV setting. The default of 72 degrees is fine.
587                         */
588
589                         float camera_fov = (72.0*PI/180) * 4./3.;
590                         if(isBlockInSight(p, camera_pos, camera_dir, camera_fov, 10000*BS) == false)
591                         {
592                                 continue;
593                         }
594 #endif
595                         /*
596                                 Don't send already sent blocks
597                         */
598                         {
599                                 if(m_blocks_sent.find(p) != NULL)
600                                 {
601                                         continue;
602                                 }
603                         }
604
605                         /*
606                                 Check if map has this block
607                         */
608                         MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p);
609                         
610                         bool surely_not_found_on_disk = false;
611                         bool block_is_invalid = false;
612                         if(block != NULL)
613                         {
614                                 // Reset usage timer, this block will be of use in the future.
615                                 block->resetUsageTimer();
616
617                                 // Block is dummy if data doesn't exist.
618                                 // It means it has been not found from disk and not generated
619                                 if(block->isDummy())
620                                 {
621                                         surely_not_found_on_disk = true;
622                                 }
623                                 
624                                 // Block is valid if lighting is up-to-date and data exists
625                                 if(block->isValid() == false)
626                                 {
627                                         block_is_invalid = true;
628                                 }
629                                 
630                                 /*if(block->isFullyGenerated() == false)
631                                 {
632                                         block_is_invalid = true;
633                                 }*/
634
635 #if 0
636                                 v2s16 p2d(p.X, p.Z);
637                                 ServerMap *map = (ServerMap*)(&server->m_env->getMap());
638                                 v2s16 chunkpos = map->sector_to_chunk(p2d);
639                                 if(map->chunkNonVolatile(chunkpos) == false)
640                                         block_is_invalid = true;
641 #endif
642                                 if(block->isGenerated() == false)
643                                         block_is_invalid = true;
644 #if 1
645                                 /*
646                                         If block is not close, don't send it unless it is near
647                                         ground level.
648
649                                         Block is near ground level if night-time mesh
650                                         differs from day-time mesh.
651                                 */
652                                 if(d >= 4)
653                                 {
654                                         if(block->dayNightDiffed() == false)
655                                                 continue;
656                                 }
657 #endif
658                         }
659
660                         /*
661                                 If block has been marked to not exist on disk (dummy)
662                                 and generating new ones is not wanted, skip block.
663                         */
664                         if(generate == false && surely_not_found_on_disk == true)
665                         {
666                                 // get next one.
667                                 continue;
668                         }
669
670                         /*
671                                 Add inexistent block to emerge queue.
672                         */
673                         if(block == NULL || surely_not_found_on_disk || block_is_invalid)
674                         {
675                                 //TODO: Get value from somewhere
676                                 // Allow only one block in emerge queue
677                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
678                                 // Allow two blocks in queue per client
679                                 //if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
680                                 u32 max_emerge = 25;
681                                 // Make it more responsive when needing to generate stuff
682                                 if(surely_not_found_on_disk)
683                                         max_emerge = 5;
684                                 if(server->m_emerge_queue.peerItemCount(peer_id) < max_emerge)
685                                 {
686                                         //infostream<<"Adding block to emerge queue"<<std::endl;
687                                         
688                                         // Add it to the emerge queue and trigger the thread
689                                         
690                                         u8 flags = 0;
691                                         if(generate == false)
692                                                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
693                                         
694                                         server->m_emerge_queue.addBlock(peer_id, p, flags);
695                                         server->m_emergethread.trigger();
696
697                                         if(nearest_emerged_d == -1)
698                                                 nearest_emerged_d = d;
699                                 } else {
700                                         if(nearest_emergefull_d == -1)
701                                                 nearest_emergefull_d = d;
702                                 }
703                                 
704                                 // get next one.
705                                 continue;
706                         }
707
708                         if(nearest_sent_d == -1)
709                                 nearest_sent_d = d;
710
711                         /*
712                                 Add block to send queue
713                         */
714
715                         /*errorstream<<"sending from d="<<d<<" to "
716                                         <<server->getPlayerName(peer_id)<<std::endl;*/
717
718                         PrioritySortedBlockTransfer q((float)d, p, peer_id);
719
720                         dest.push_back(q);
721
722                         num_blocks_selected += 1;
723                 }
724         }
725 queue_full_break:
726
727         //infostream<<"Stopped at "<<d<<std::endl;
728         
729         // If nothing was found for sending and nothing was queued for
730         // emerging, continue next time browsing from here
731         if(nearest_emerged_d != -1){
732                 new_nearest_unsent_d = nearest_emerged_d;
733         } else if(nearest_emergefull_d != -1){
734                 new_nearest_unsent_d = nearest_emergefull_d;
735         } else {
736                 if(d > g_settings->getS16("max_block_send_distance")){
737                         new_nearest_unsent_d = 0;
738                         m_nothing_to_send_pause_timer = 2.0;
739                         /*infostream<<"GetNextBlocks(): d wrapped around for "
740                                         <<server->getPlayerName(peer_id)
741                                         <<"; setting to 0 and pausing"<<std::endl;*/
742                 } else {
743                         if(nearest_sent_d != -1)
744                                 new_nearest_unsent_d = nearest_sent_d;
745                         else
746                                 new_nearest_unsent_d = d;
747                 }
748         }
749
750         if(new_nearest_unsent_d != -1)
751                 m_nearest_unsent_d = new_nearest_unsent_d;
752
753         /*timer_result = timer.stop(true);
754         if(timer_result != 0)
755                 infostream<<"GetNextBlocks duration: "<<timer_result<<" (!=0)"<<std::endl;*/
756 }
757
758 void RemoteClient::GotBlock(v3s16 p)
759 {
760         if(m_blocks_sending.find(p) != NULL)
761                 m_blocks_sending.remove(p);
762         else
763         {
764                 /*infostream<<"RemoteClient::GotBlock(): Didn't find in"
765                                 " m_blocks_sending"<<std::endl;*/
766                 m_excess_gotblocks++;
767         }
768         m_blocks_sent.insert(p, true);
769 }
770
771 void RemoteClient::SentBlock(v3s16 p)
772 {
773         if(m_blocks_sending.find(p) == NULL)
774                 m_blocks_sending.insert(p, 0.0);
775         else
776                 infostream<<"RemoteClient::SentBlock(): Sent block"
777                                 " already in m_blocks_sending"<<std::endl;
778 }
779
780 void RemoteClient::SetBlockNotSent(v3s16 p)
781 {
782         m_nearest_unsent_d = 0;
783         
784         if(m_blocks_sending.find(p) != NULL)
785                 m_blocks_sending.remove(p);
786         if(m_blocks_sent.find(p) != NULL)
787                 m_blocks_sent.remove(p);
788 }
789
790 void RemoteClient::SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks)
791 {
792         m_nearest_unsent_d = 0;
793         
794         for(core::map<v3s16, MapBlock*>::Iterator
795                         i = blocks.getIterator();
796                         i.atEnd()==false; i++)
797         {
798                 v3s16 p = i.getNode()->getKey();
799
800                 if(m_blocks_sending.find(p) != NULL)
801                         m_blocks_sending.remove(p);
802                 if(m_blocks_sent.find(p) != NULL)
803                         m_blocks_sent.remove(p);
804         }
805 }
806
807 /*
808         PlayerInfo
809 */
810
811 PlayerInfo::PlayerInfo()
812 {
813         name[0] = 0;
814         avg_rtt = 0;
815 }
816
817 void PlayerInfo::PrintLine(std::ostream *s)
818 {
819         (*s)<<id<<": ";
820         (*s)<<"\""<<name<<"\" ("
821                         <<(position.X/10)<<","<<(position.Y/10)
822                         <<","<<(position.Z/10)<<") ";
823         address.print(s);
824         (*s)<<" avg_rtt="<<avg_rtt;
825         (*s)<<std::endl;
826 }
827
828 /*
829         Server
830 */
831
832 Server::Server(
833                 const std::string &path_world,
834                 const std::string &path_config,
835                 const SubgameSpec &gamespec
836         ):
837         m_path_world(path_world),
838         m_path_config(path_config),
839         m_gamespec(gamespec),
840         m_env(NULL),
841         m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
842         m_authmanager(path_world+DIR_DELIM+"auth.txt"),
843         m_banmanager(path_world+DIR_DELIM+"ipban.txt"),
844         m_lua(NULL),
845         m_itemdef(createItemDefManager()),
846         m_nodedef(createNodeDefManager()),
847         m_craftdef(createCraftDefManager()),
848         m_thread(this),
849         m_emergethread(this),
850         m_time_counter(0),
851         m_time_of_day_send_timer(0),
852         m_uptime(0),
853         m_shutdown_requested(false),
854         m_ignore_map_edit_events(false),
855         m_ignore_map_edit_events_peer_id(0)
856 {
857         m_liquid_transform_timer = 0.0;
858         m_print_info_timer = 0.0;
859         m_objectdata_timer = 0.0;
860         m_emergethread_trigger_timer = 0.0;
861         m_savemap_timer = 0.0;
862         
863         m_env_mutex.Init();
864         m_con_mutex.Init();
865         m_step_dtime_mutex.Init();
866         m_step_dtime = 0.0;
867
868         if(!gamespec.isValid())
869                 throw ServerError("Supplied invalid gamespec");
870         
871         // Figure out some paths
872         // share/server
873         m_path_share = porting::path_share + DIR_DELIM + "server";
874
875         infostream<<"Server created for gameid \""<<m_gamespec.id<<"\""<<std::endl;
876         infostream<<"- world:  "<<m_path_world<<std::endl;
877         infostream<<"- config: "<<m_path_config<<std::endl;
878         infostream<<"- game:   "<<m_gamespec.path<<std::endl;
879         for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin();
880                         i != m_gamespec.addon_paths.end(); i++)
881                 infostream<<"- addons: "<<(*i)<<std::endl;
882
883         // Path to builtin.lua
884         std::string builtinpath = m_path_share + DIR_DELIM + "builtin.lua";
885
886         // Add default global mod search path
887         m_modspaths.push_front(m_gamespec.path + DIR_DELIM "mods");
888         // Add world mod search path
889         m_modspaths.push_front(m_path_world + DIR_DELIM + "worldmods");
890         // Add addon mod search path
891         for(std::set<std::string>::const_iterator i = m_gamespec.addon_paths.begin();
892                         i != m_gamespec.addon_paths.end(); i++)
893                 m_modspaths.push_front((*i) + DIR_DELIM + "mods");
894
895         // Print out mod search paths
896         for(core::list<std::string>::Iterator i = m_modspaths.begin();
897                         i != m_modspaths.end(); i++){
898                 std::string modspath = *i;
899                 infostream<<"- mods:   "<<modspath<<std::endl;
900         }
901         
902         // Create world.mt if does not already exist
903         std::string worldmt_path = m_path_world + DIR_DELIM + "world.mt";
904         if(!fs::PathExists(worldmt_path)){
905                 infostream<<"Creating world.mt ("<<worldmt_path<<")"<<std::endl;
906                 fs::CreateAllDirs(m_path_world);
907                 std::ofstream of(worldmt_path.c_str(), std::ios::binary);
908                 of<<"gameid = "<<m_gamespec.id<<"\n";
909         }
910
911         // Lock environment
912         JMutexAutoLock envlock(m_env_mutex);
913         JMutexAutoLock conlock(m_con_mutex);
914
915         // Initialize scripting
916         
917         infostream<<"Server: Initializing Lua"<<std::endl;
918         m_lua = script_init();
919         assert(m_lua);
920         // Export API
921         scriptapi_export(m_lua, this);
922         // Load and run builtin.lua
923         infostream<<"Server: Loading builtin.lua [\""
924                         <<builtinpath<<"\"]"<<std::endl;
925         bool success = scriptapi_loadmod(m_lua, builtinpath, "__builtin");
926         if(!success){
927                 errorstream<<"Server: Failed to load and run "
928                                 <<builtinpath<<std::endl;
929                 throw ModError("Failed to load and run "+builtinpath);
930         }
931         // Find mods in mod search paths
932         m_mods = getMods(m_modspaths);
933         // Print 'em
934         infostream<<"Server: Loading mods: ";
935         for(core::list<ModSpec>::Iterator i = m_mods.begin();
936                         i != m_mods.end(); i++){
937                 const ModSpec &mod = *i;
938                 infostream<<mod.name<<" ";
939         }
940         infostream<<std::endl;
941         // Load and run "mod" scripts
942         for(core::list<ModSpec>::Iterator i = m_mods.begin();
943                         i != m_mods.end(); i++){
944                 const ModSpec &mod = *i;
945                 std::string scriptpath = mod.path + DIR_DELIM + "init.lua";
946                 infostream<<"  ["<<padStringRight(mod.name, 12)<<"] [\""
947                                 <<scriptpath<<"\"]"<<std::endl;
948                 bool success = scriptapi_loadmod(m_lua, scriptpath, mod.name);
949                 if(!success){
950                         errorstream<<"Server: Failed to load and run "
951                                         <<scriptpath<<std::endl;
952                         throw ModError("Failed to load and run "+scriptpath);
953                 }
954         }
955         
956         // Read Textures and calculate sha1 sums
957         PrepareTextures();
958
959         // Apply item aliases in the node definition manager
960         m_nodedef->updateAliases(m_itemdef);
961
962         // Initialize Environment
963         
964         m_env = new ServerEnvironment(new ServerMap(path_world, this), m_lua,
965                         this, this);
966
967         // Give environment reference to scripting api
968         scriptapi_add_environment(m_lua, m_env);
969         
970         // Register us to receive map edit events
971         m_env->getMap().addEventReceiver(this);
972
973         // If file exists, load environment metadata
974         if(fs::PathExists(m_path_world+DIR_DELIM+"env_meta.txt"))
975         {
976                 infostream<<"Server: Loading environment metadata"<<std::endl;
977                 m_env->loadMeta(m_path_world);
978         }
979
980         // Load players
981         infostream<<"Server: Loading players"<<std::endl;
982         m_env->deSerializePlayers(m_path_world);
983
984         /*
985                 Add some test ActiveBlockModifiers to environment
986         */
987         add_legacy_abms(m_env, m_nodedef);
988 }
989
990 Server::~Server()
991 {
992         infostream<<"Server destructing"<<std::endl;
993
994         /*
995                 Send shutdown message
996         */
997         {
998                 JMutexAutoLock conlock(m_con_mutex);
999                 
1000                 std::wstring line = L"*** Server shutting down";
1001
1002                 /*
1003                         Send the message to clients
1004                 */
1005                 for(core::map<u16, RemoteClient*>::Iterator
1006                         i = m_clients.getIterator();
1007                         i.atEnd() == false; i++)
1008                 {
1009                         // Get client and check that it is valid
1010                         RemoteClient *client = i.getNode()->getValue();
1011                         assert(client->peer_id == i.getNode()->getKey());
1012                         if(client->serialization_version == SER_FMT_VER_INVALID)
1013                                 continue;
1014
1015                         try{
1016                                 SendChatMessage(client->peer_id, line);
1017                         }
1018                         catch(con::PeerNotFoundException &e)
1019                         {}
1020                 }
1021         }
1022         
1023         {
1024                 JMutexAutoLock envlock(m_env_mutex);
1025
1026                 /*
1027                         Save players
1028                 */
1029                 infostream<<"Server: Saving players"<<std::endl;
1030                 m_env->serializePlayers(m_path_world);
1031
1032                 /*
1033                         Save environment metadata
1034                 */
1035                 infostream<<"Server: Saving environment metadata"<<std::endl;
1036                 m_env->saveMeta(m_path_world);
1037         }
1038                 
1039         /*
1040                 Stop threads
1041         */
1042         stop();
1043         
1044         /*
1045                 Delete clients
1046         */
1047         {
1048                 JMutexAutoLock clientslock(m_con_mutex);
1049
1050                 for(core::map<u16, RemoteClient*>::Iterator
1051                         i = m_clients.getIterator();
1052                         i.atEnd() == false; i++)
1053                 {
1054                         /*// Delete player
1055                         // NOTE: These are removed by env destructor
1056                         {
1057                                 u16 peer_id = i.getNode()->getKey();
1058                                 JMutexAutoLock envlock(m_env_mutex);
1059                                 m_env->removePlayer(peer_id);
1060                         }*/
1061                         
1062                         // Delete client
1063                         delete i.getNode()->getValue();
1064                 }
1065         }
1066
1067         // Delete Environment
1068         delete m_env;
1069
1070         delete m_itemdef;
1071         delete m_nodedef;
1072         delete m_craftdef;
1073         
1074         // Deinitialize scripting
1075         infostream<<"Server: Deinitializing scripting"<<std::endl;
1076         script_deinit(m_lua);
1077 }
1078
1079 void Server::start(unsigned short port)
1080 {
1081         DSTACK(__FUNCTION_NAME);
1082         // Stop thread if already running
1083         m_thread.stop();
1084         
1085         // Initialize connection
1086         m_con.SetTimeoutMs(30);
1087         m_con.Serve(port);
1088
1089         // Start thread
1090         m_thread.setRun(true);
1091         m_thread.Start();
1092         
1093         // ASCII art for the win!
1094         actionstream
1095         <<"        .__               __                   __   "<<std::endl
1096         <<"  _____ |__| ____   _____/  |_  ____   _______/  |_ "<<std::endl
1097         <<" /     \\|  |/    \\_/ __ \\   __\\/ __ \\ /  ___/\\   __\\"<<std::endl
1098         <<"|  Y Y  \\  |   |  \\  ___/|  | \\  ___/ \\___ \\  |  |  "<<std::endl
1099         <<"|__|_|  /__|___|  /\\___  >__|  \\___  >____  > |__|  "<<std::endl
1100         <<"      \\/        \\/     \\/          \\/     \\/        "<<std::endl;
1101         actionstream<<"World at ["<<m_path_world<<"]"<<std::endl;
1102         actionstream<<"Server for gameid=\""<<m_gamespec.id
1103                         <<"\" listening on port "<<port<<"."<<std::endl;
1104 }
1105
1106 void Server::stop()
1107 {
1108         DSTACK(__FUNCTION_NAME);
1109         
1110         infostream<<"Server: Stopping and waiting threads"<<std::endl;
1111
1112         // Stop threads (set run=false first so both start stopping)
1113         m_thread.setRun(false);
1114         m_emergethread.setRun(false);
1115         m_thread.stop();
1116         m_emergethread.stop();
1117         
1118         infostream<<"Server: Threads stopped"<<std::endl;
1119 }
1120
1121 void Server::step(float dtime)
1122 {
1123         DSTACK(__FUNCTION_NAME);
1124         // Limit a bit
1125         if(dtime > 2.0)
1126                 dtime = 2.0;
1127         {
1128                 JMutexAutoLock lock(m_step_dtime_mutex);
1129                 m_step_dtime += dtime;
1130         }
1131 }
1132
1133 void Server::AsyncRunStep()
1134 {
1135         DSTACK(__FUNCTION_NAME);
1136         
1137         g_profiler->add("Server::AsyncRunStep (num)", 1);
1138         
1139         float dtime;
1140         {
1141                 JMutexAutoLock lock1(m_step_dtime_mutex);
1142                 dtime = m_step_dtime;
1143         }
1144         
1145         {
1146                 // Send blocks to clients
1147                 SendBlocks(dtime);
1148         }
1149         
1150         if(dtime < 0.001)
1151                 return;
1152         
1153         g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
1154
1155         //infostream<<"Server steps "<<dtime<<std::endl;
1156         //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
1157         
1158         {
1159                 JMutexAutoLock lock1(m_step_dtime_mutex);
1160                 m_step_dtime -= dtime;
1161         }
1162
1163         /*
1164                 Update uptime
1165         */
1166         {
1167                 m_uptime.set(m_uptime.get() + dtime);
1168         }
1169         
1170         {
1171                 // Process connection's timeouts
1172                 JMutexAutoLock lock2(m_con_mutex);
1173                 ScopeProfiler sp(g_profiler, "Server: connection timeout processing");
1174                 m_con.RunTimeouts(dtime);
1175         }
1176         
1177         {
1178                 // This has to be called so that the client list gets synced
1179                 // with the peer list of the connection
1180                 handlePeerChanges();
1181         }
1182
1183         /*
1184                 Update m_time_of_day and overall game time
1185         */
1186         {
1187                 JMutexAutoLock envlock(m_env_mutex);
1188
1189                 m_time_counter += dtime;
1190                 f32 speed = g_settings->getFloat("time_speed") * 24000./(24.*3600);
1191                 u32 units = (u32)(m_time_counter*speed);
1192                 m_time_counter -= (f32)units / speed;
1193                 
1194                 m_env->setTimeOfDay((m_env->getTimeOfDay() + units) % 24000);
1195                 
1196                 //infostream<<"Server: m_time_of_day = "<<m_time_of_day.get()<<std::endl;
1197
1198                 /*
1199                         Send to clients at constant intervals
1200                 */
1201
1202                 m_time_of_day_send_timer -= dtime;
1203                 if(m_time_of_day_send_timer < 0.0)
1204                 {
1205                         m_time_of_day_send_timer = g_settings->getFloat("time_send_interval");
1206
1207                         //JMutexAutoLock envlock(m_env_mutex);
1208                         JMutexAutoLock conlock(m_con_mutex);
1209
1210                         for(core::map<u16, RemoteClient*>::Iterator
1211                                 i = m_clients.getIterator();
1212                                 i.atEnd() == false; i++)
1213                         {
1214                                 RemoteClient *client = i.getNode()->getValue();
1215                                 //Player *player = m_env->getPlayer(client->peer_id);
1216                                 
1217                                 SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
1218                                                 m_env->getTimeOfDay());
1219                                 // Send as reliable
1220                                 m_con.Send(client->peer_id, 0, data, true);
1221                         }
1222                 }
1223         }
1224
1225         {
1226                 JMutexAutoLock lock(m_env_mutex);
1227                 // Step environment
1228                 ScopeProfiler sp(g_profiler, "SEnv step");
1229                 ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
1230                 m_env->step(dtime);
1231         }
1232                 
1233         const float map_timer_and_unload_dtime = 2.92;
1234         if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
1235         {
1236                 JMutexAutoLock lock(m_env_mutex);
1237                 // Run Map's timers and unload unused data
1238                 ScopeProfiler sp(g_profiler, "Server: map timer and unload");
1239                 m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
1240                                 g_settings->getFloat("server_unload_unused_data_timeout"));
1241         }
1242         
1243         /*
1244                 Do background stuff
1245         */
1246
1247         /*
1248                 Handle players
1249         */
1250         {
1251                 JMutexAutoLock lock(m_env_mutex);
1252                 JMutexAutoLock lock2(m_con_mutex);
1253
1254                 ScopeProfiler sp(g_profiler, "Server: handle players");
1255
1256                 //float player_max_speed = BS * 4.0; // Normal speed
1257                 float player_max_speed = BS * 20; // Fast speed
1258                 float player_max_speed_up = BS * 20;
1259                 
1260                 player_max_speed *= 2.5; // Tolerance
1261                 player_max_speed_up *= 2.5;
1262
1263                 for(core::map<u16, RemoteClient*>::Iterator
1264                         i = m_clients.getIterator();
1265                         i.atEnd() == false; i++)
1266                 {
1267                         RemoteClient *client = i.getNode()->getValue();
1268                         ServerRemotePlayer *player =
1269                                         static_cast<ServerRemotePlayer*>
1270                                         (m_env->getPlayer(client->peer_id));
1271                         if(player==NULL)
1272                                 continue;
1273                         
1274                         /*
1275                                 Check player movements
1276
1277                                 NOTE: Actually the server should handle player physics like the
1278                                 client does and compare player's position to what is calculated
1279                                 on our side. This is required when eg. players fly due to an
1280                                 explosion.
1281                         */
1282                         player->m_last_good_position_age += dtime;
1283                         if(player->m_last_good_position_age >= 1.0){
1284                                 float age = player->m_last_good_position_age;
1285                                 v3f diff = (player->getPosition() - player->m_last_good_position);
1286                                 float d_vert = diff.Y;
1287                                 diff.Y = 0;
1288                                 float d_horiz = diff.getLength();
1289                                 /*infostream<<player->getName()<<"'s horizontal speed is "
1290                                                 <<(d_horiz/age)<<std::endl;*/
1291                                 if(d_horiz <= age * player_max_speed &&
1292                                                 (d_vert < 0 || d_vert < age * player_max_speed_up)){
1293                                         player->m_last_good_position = player->getPosition();
1294                                 } else {
1295                                         actionstream<<"Player "<<player->getName()
1296                                                         <<" moved too fast; resetting position"
1297                                                         <<std::endl;
1298                                         player->setPosition(player->m_last_good_position);
1299                                         SendMovePlayer(player);
1300                                 }
1301                                 player->m_last_good_position_age = 0;
1302                         }
1303
1304                         /*
1305                                 Handle player HPs (die if hp=0)
1306                         */
1307                         if(player->hp == 0 && player->m_hp_not_sent)
1308                                 DiePlayer(player);
1309
1310                         /*
1311                                 Send player inventories and HPs if necessary
1312                         */
1313                         if(player->m_inventory_not_sent){
1314                                 UpdateCrafting(player->peer_id);
1315                                 SendInventory(player->peer_id);
1316                         }
1317                         if(player->m_hp_not_sent){
1318                                 SendPlayerHP(player);
1319                         }
1320
1321                         /*
1322                                 Add to environment
1323                         */
1324                         if(!player->m_is_in_environment){
1325                                 player->m_removed = false;
1326                                 player->setId(0);
1327                                 m_env->addActiveObject(player);
1328                         }
1329                 }
1330         }
1331         
1332         /* Transform liquids */
1333         m_liquid_transform_timer += dtime;
1334         if(m_liquid_transform_timer >= 1.00)
1335         {
1336                 m_liquid_transform_timer -= 1.00;
1337                 
1338                 JMutexAutoLock lock(m_env_mutex);
1339
1340                 ScopeProfiler sp(g_profiler, "Server: liquid transform");
1341
1342                 core::map<v3s16, MapBlock*> modified_blocks;
1343                 m_env->getMap().transformLiquids(modified_blocks);
1344 #if 0           
1345                 /*
1346                         Update lighting
1347                 */
1348                 core::map<v3s16, MapBlock*> lighting_modified_blocks;
1349                 ServerMap &map = ((ServerMap&)m_env->getMap());
1350                 map.updateLighting(modified_blocks, lighting_modified_blocks);
1351                 
1352                 // Add blocks modified by lighting to modified_blocks
1353                 for(core::map<v3s16, MapBlock*>::Iterator
1354                                 i = lighting_modified_blocks.getIterator();
1355                                 i.atEnd() == false; i++)
1356                 {
1357                         MapBlock *block = i.getNode()->getValue();
1358                         modified_blocks.insert(block->getPos(), block);
1359                 }
1360 #endif
1361                 /*
1362                         Set the modified blocks unsent for all the clients
1363                 */
1364                 
1365                 JMutexAutoLock lock2(m_con_mutex);
1366
1367                 for(core::map<u16, RemoteClient*>::Iterator
1368                                 i = m_clients.getIterator();
1369                                 i.atEnd() == false; i++)
1370                 {
1371                         RemoteClient *client = i.getNode()->getValue();
1372                         
1373                         if(modified_blocks.size() > 0)
1374                         {
1375                                 // Remove block from sent history
1376                                 client->SetBlocksNotSent(modified_blocks);
1377                         }
1378                 }
1379         }
1380
1381         // Periodically print some info
1382         {
1383                 float &counter = m_print_info_timer;
1384                 counter += dtime;
1385                 if(counter >= 30.0)
1386                 {
1387                         counter = 0.0;
1388
1389                         JMutexAutoLock lock2(m_con_mutex);
1390                         
1391                         if(m_clients.size() != 0)
1392                                 infostream<<"Players:"<<std::endl;
1393                         for(core::map<u16, RemoteClient*>::Iterator
1394                                 i = m_clients.getIterator();
1395                                 i.atEnd() == false; i++)
1396                         {
1397                                 //u16 peer_id = i.getNode()->getKey();
1398                                 RemoteClient *client = i.getNode()->getValue();
1399                                 Player *player = m_env->getPlayer(client->peer_id);
1400                                 if(player==NULL)
1401                                         continue;
1402                                 infostream<<"* "<<player->getName()<<"\t";
1403                                 client->PrintInfo(infostream);
1404                         }
1405                 }
1406         }
1407
1408         //if(g_settings->getBool("enable_experimental"))
1409         {
1410
1411         /*
1412                 Check added and deleted active objects
1413         */
1414         {
1415                 //infostream<<"Server: Checking added and deleted active objects"<<std::endl;
1416                 JMutexAutoLock envlock(m_env_mutex);
1417                 JMutexAutoLock conlock(m_con_mutex);
1418
1419                 ScopeProfiler sp(g_profiler, "Server: checking added and deleted objs");
1420
1421                 // Radius inside which objects are active
1422                 s16 radius = g_settings->getS16("active_object_send_range_blocks");
1423                 radius *= MAP_BLOCKSIZE;
1424
1425                 for(core::map<u16, RemoteClient*>::Iterator
1426                         i = m_clients.getIterator();
1427                         i.atEnd() == false; i++)
1428                 {
1429                         RemoteClient *client = i.getNode()->getValue();
1430
1431                         // If definitions and textures have not been sent, don't
1432                         // send objects either
1433                         if(!client->definitions_sent)
1434                                 continue;
1435
1436                         Player *player = m_env->getPlayer(client->peer_id);
1437                         if(player==NULL)
1438                         {
1439                                 // This can happen if the client timeouts somehow
1440                                 /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client "
1441                                                 <<client->peer_id
1442                                                 <<" has no associated player"<<std::endl;*/
1443                                 continue;
1444                         }
1445                         v3s16 pos = floatToInt(player->getPosition(), BS);
1446
1447                         core::map<u16, bool> removed_objects;
1448                         core::map<u16, bool> added_objects;
1449                         m_env->getRemovedActiveObjects(pos, radius,
1450                                         client->m_known_objects, removed_objects);
1451                         m_env->getAddedActiveObjects(pos, radius,
1452                                         client->m_known_objects, added_objects);
1453                         
1454                         // Ignore if nothing happened
1455                         if(removed_objects.size() == 0 && added_objects.size() == 0)
1456                         {
1457                                 //infostream<<"active objects: none changed"<<std::endl;
1458                                 continue;
1459                         }
1460                         
1461                         std::string data_buffer;
1462
1463                         char buf[4];
1464                         
1465                         // Handle removed objects
1466                         writeU16((u8*)buf, removed_objects.size());
1467                         data_buffer.append(buf, 2);
1468                         for(core::map<u16, bool>::Iterator
1469                                         i = removed_objects.getIterator();
1470                                         i.atEnd()==false; i++)
1471                         {
1472                                 // Get object
1473                                 u16 id = i.getNode()->getKey();
1474                                 ServerActiveObject* obj = m_env->getActiveObject(id);
1475
1476                                 // Add to data buffer for sending
1477                                 writeU16((u8*)buf, i.getNode()->getKey());
1478                                 data_buffer.append(buf, 2);
1479                                 
1480                                 // Remove from known objects
1481                                 client->m_known_objects.remove(i.getNode()->getKey());
1482
1483                                 if(obj && obj->m_known_by_count > 0)
1484                                         obj->m_known_by_count--;
1485                         }
1486
1487                         // Handle added objects
1488                         writeU16((u8*)buf, added_objects.size());
1489                         data_buffer.append(buf, 2);
1490                         for(core::map<u16, bool>::Iterator
1491                                         i = added_objects.getIterator();
1492                                         i.atEnd()==false; i++)
1493                         {
1494                                 // Get object
1495                                 u16 id = i.getNode()->getKey();
1496                                 ServerActiveObject* obj = m_env->getActiveObject(id);
1497                                 
1498                                 // Get object type
1499                                 u8 type = ACTIVEOBJECT_TYPE_INVALID;
1500                                 if(obj == NULL)
1501                                         infostream<<"WARNING: "<<__FUNCTION_NAME
1502                                                         <<": NULL object"<<std::endl;
1503                                 else
1504                                         type = obj->getType();
1505
1506                                 // Add to data buffer for sending
1507                                 writeU16((u8*)buf, id);
1508                                 data_buffer.append(buf, 2);
1509                                 writeU8((u8*)buf, type);
1510                                 data_buffer.append(buf, 1);
1511                                 
1512                                 if(obj)
1513                                         data_buffer.append(serializeLongString(
1514                                                         obj->getClientInitializationData()));
1515                                 else
1516                                         data_buffer.append(serializeLongString(""));
1517
1518                                 // Add to known objects
1519                                 client->m_known_objects.insert(i.getNode()->getKey(), false);
1520
1521                                 if(obj)
1522                                         obj->m_known_by_count++;
1523                         }
1524
1525                         // Send packet
1526                         SharedBuffer<u8> reply(2 + data_buffer.size());
1527                         writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD);
1528                         memcpy((char*)&reply[2], data_buffer.c_str(),
1529                                         data_buffer.size());
1530                         // Send as reliable
1531                         m_con.Send(client->peer_id, 0, reply, true);
1532
1533                         verbosestream<<"Server: Sent object remove/add: "
1534                                         <<removed_objects.size()<<" removed, "
1535                                         <<added_objects.size()<<" added, "
1536                                         <<"packet size is "<<reply.getSize()<<std::endl;
1537                 }
1538
1539 #if 0
1540                 /*
1541                         Collect a list of all the objects known by the clients
1542                         and report it back to the environment.
1543                 */
1544
1545                 core::map<u16, bool> all_known_objects;
1546
1547                 for(core::map<u16, RemoteClient*>::Iterator
1548                         i = m_clients.getIterator();
1549                         i.atEnd() == false; i++)
1550                 {
1551                         RemoteClient *client = i.getNode()->getValue();
1552                         // Go through all known objects of client
1553                         for(core::map<u16, bool>::Iterator
1554                                         i = client->m_known_objects.getIterator();
1555                                         i.atEnd()==false; i++)
1556                         {
1557                                 u16 id = i.getNode()->getKey();
1558                                 all_known_objects[id] = true;
1559                         }
1560                 }
1561                 
1562                 m_env->setKnownActiveObjects(whatever);
1563 #endif
1564
1565         }
1566
1567         /*
1568                 Send object messages
1569         */
1570         {
1571                 JMutexAutoLock envlock(m_env_mutex);
1572                 JMutexAutoLock conlock(m_con_mutex);
1573
1574                 ScopeProfiler sp(g_profiler, "Server: sending object messages");
1575
1576                 // Key = object id
1577                 // Value = data sent by object
1578                 core::map<u16, core::list<ActiveObjectMessage>* > buffered_messages;
1579
1580                 // Get active object messages from environment
1581                 for(;;)
1582                 {
1583                         ActiveObjectMessage aom = m_env->getActiveObjectMessage();
1584                         if(aom.id == 0)
1585                                 break;
1586                         
1587                         core::list<ActiveObjectMessage>* message_list = NULL;
1588                         core::map<u16, core::list<ActiveObjectMessage>* >::Node *n;
1589                         n = buffered_messages.find(aom.id);
1590                         if(n == NULL)
1591                         {
1592                                 message_list = new core::list<ActiveObjectMessage>;
1593                                 buffered_messages.insert(aom.id, message_list);
1594                         }
1595                         else
1596                         {
1597                                 message_list = n->getValue();
1598                         }
1599                         message_list->push_back(aom);
1600                 }
1601                 
1602                 // Route data to every client
1603                 for(core::map<u16, RemoteClient*>::Iterator
1604                         i = m_clients.getIterator();
1605                         i.atEnd()==false; i++)
1606                 {
1607                         RemoteClient *client = i.getNode()->getValue();
1608                         std::string reliable_data;
1609                         std::string unreliable_data;
1610                         // Go through all objects in message buffer
1611                         for(core::map<u16, core::list<ActiveObjectMessage>* >::Iterator
1612                                         j = buffered_messages.getIterator();
1613                                         j.atEnd()==false; j++)
1614                         {
1615                                 // If object is not known by client, skip it
1616                                 u16 id = j.getNode()->getKey();
1617                                 if(client->m_known_objects.find(id) == NULL)
1618                                         continue;
1619                                 // Get message list of object
1620                                 core::list<ActiveObjectMessage>* list = j.getNode()->getValue();
1621                                 // Go through every message
1622                                 for(core::list<ActiveObjectMessage>::Iterator
1623                                                 k = list->begin(); k != list->end(); k++)
1624                                 {
1625                                         // Compose the full new data with header
1626                                         ActiveObjectMessage aom = *k;
1627                                         std::string new_data;
1628                                         // Add object id
1629                                         char buf[2];
1630                                         writeU16((u8*)&buf[0], aom.id);
1631                                         new_data.append(buf, 2);
1632                                         // Add data
1633                                         new_data += serializeString(aom.datastring);
1634                                         // Add data to buffer
1635                                         if(aom.reliable)
1636                                                 reliable_data += new_data;
1637                                         else
1638                                                 unreliable_data += new_data;
1639                                 }
1640                         }
1641                         /*
1642                                 reliable_data and unreliable_data are now ready.
1643                                 Send them.
1644                         */
1645                         if(reliable_data.size() > 0)
1646                         {
1647                                 SharedBuffer<u8> reply(2 + reliable_data.size());
1648                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
1649                                 memcpy((char*)&reply[2], reliable_data.c_str(),
1650                                                 reliable_data.size());
1651                                 // Send as reliable
1652                                 m_con.Send(client->peer_id, 0, reply, true);
1653                         }
1654                         if(unreliable_data.size() > 0)
1655                         {
1656                                 SharedBuffer<u8> reply(2 + unreliable_data.size());
1657                                 writeU16(&reply[0], TOCLIENT_ACTIVE_OBJECT_MESSAGES);
1658                                 memcpy((char*)&reply[2], unreliable_data.c_str(),
1659                                                 unreliable_data.size());
1660                                 // Send as unreliable
1661                                 m_con.Send(client->peer_id, 0, reply, false);
1662                         }
1663
1664                         /*if(reliable_data.size() > 0 || unreliable_data.size() > 0)
1665                         {
1666                                 infostream<<"Server: Size of object message data: "
1667                                                 <<"reliable: "<<reliable_data.size()
1668                                                 <<", unreliable: "<<unreliable_data.size()
1669                                                 <<std::endl;
1670                         }*/
1671                 }
1672
1673                 // Clear buffered_messages
1674                 for(core::map<u16, core::list<ActiveObjectMessage>* >::Iterator
1675                                 i = buffered_messages.getIterator();
1676                                 i.atEnd()==false; i++)
1677                 {
1678                         delete i.getNode()->getValue();
1679                 }
1680         }
1681
1682         } // enable_experimental
1683
1684         /*
1685                 Send queued-for-sending map edit events.
1686         */
1687         {
1688                 // Don't send too many at a time
1689                 //u32 count = 0;
1690
1691                 // Single change sending is disabled if queue size is not small
1692                 bool disable_single_change_sending = false;
1693                 if(m_unsent_map_edit_queue.size() >= 4)
1694                         disable_single_change_sending = true;
1695
1696                 int event_count = m_unsent_map_edit_queue.size();
1697
1698                 // We'll log the amount of each
1699                 Profiler prof;
1700
1701                 while(m_unsent_map_edit_queue.size() != 0)
1702                 {
1703                         MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
1704                         
1705                         // Players far away from the change are stored here.
1706                         // Instead of sending the changes, MapBlocks are set not sent
1707                         // for them.
1708                         core::list<u16> far_players;
1709
1710                         if(event->type == MEET_ADDNODE)
1711                         {
1712                                 //infostream<<"Server: MEET_ADDNODE"<<std::endl;
1713                                 prof.add("MEET_ADDNODE", 1);
1714                                 if(disable_single_change_sending)
1715                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1716                                                         &far_players, 5);
1717                                 else
1718                                         sendAddNode(event->p, event->n, event->already_known_by_peer,
1719                                                         &far_players, 30);
1720                         }
1721                         else if(event->type == MEET_REMOVENODE)
1722                         {
1723                                 //infostream<<"Server: MEET_REMOVENODE"<<std::endl;
1724                                 prof.add("MEET_REMOVENODE", 1);
1725                                 if(disable_single_change_sending)
1726                                         sendRemoveNode(event->p, event->already_known_by_peer,
1727                                                         &far_players, 5);
1728                                 else
1729                                         sendRemoveNode(event->p, event->already_known_by_peer,
1730                                                         &far_players, 30);
1731                         }
1732                         else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
1733                         {
1734                                 infostream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<<std::endl;
1735                                 prof.add("MEET_BLOCK_NODE_METADATA_CHANGED", 1);
1736                                 setBlockNotSent(event->p);
1737                         }
1738                         else if(event->type == MEET_OTHER)
1739                         {
1740                                 infostream<<"Server: MEET_OTHER"<<std::endl;
1741                                 prof.add("MEET_OTHER", 1);
1742                                 for(core::map<v3s16, bool>::Iterator
1743                                                 i = event->modified_blocks.getIterator();
1744                                                 i.atEnd()==false; i++)
1745                                 {
1746                                         v3s16 p = i.getNode()->getKey();
1747                                         setBlockNotSent(p);
1748                                 }
1749                         }
1750                         else
1751                         {
1752                                 prof.add("unknown", 1);
1753                                 infostream<<"WARNING: Server: Unknown MapEditEvent "
1754                                                 <<((u32)event->type)<<std::endl;
1755                         }
1756                         
1757                         /*
1758                                 Set blocks not sent to far players
1759                         */
1760                         if(far_players.size() > 0)
1761                         {
1762                                 // Convert list format to that wanted by SetBlocksNotSent
1763                                 core::map<v3s16, MapBlock*> modified_blocks2;
1764                                 for(core::map<v3s16, bool>::Iterator
1765                                                 i = event->modified_blocks.getIterator();
1766                                                 i.atEnd()==false; i++)
1767                                 {
1768                                         v3s16 p = i.getNode()->getKey();
1769                                         modified_blocks2.insert(p,
1770                                                         m_env->getMap().getBlockNoCreateNoEx(p));
1771                                 }
1772                                 // Set blocks not sent
1773                                 for(core::list<u16>::Iterator
1774                                                 i = far_players.begin();
1775                                                 i != far_players.end(); i++)
1776                                 {
1777                                         u16 peer_id = *i;
1778                                         RemoteClient *client = getClient(peer_id);
1779                                         if(client==NULL)
1780                                                 continue;
1781                                         client->SetBlocksNotSent(modified_blocks2);
1782                                 }
1783                         }
1784
1785                         delete event;
1786
1787                         /*// Don't send too many at a time
1788                         count++;
1789                         if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
1790                                 break;*/
1791                 }
1792
1793                 if(event_count >= 5){
1794                         infostream<<"Server: MapEditEvents:"<<std::endl;
1795                         prof.print(infostream);
1796                 } else if(event_count != 0){
1797                         verbosestream<<"Server: MapEditEvents:"<<std::endl;
1798                         prof.print(verbosestream);
1799                 }
1800                 
1801         }
1802
1803         /*
1804                 Trigger emergethread (it somehow gets to a non-triggered but
1805                 bysy state sometimes)
1806         */
1807         {
1808                 float &counter = m_emergethread_trigger_timer;
1809                 counter += dtime;
1810                 if(counter >= 2.0)
1811                 {
1812                         counter = 0.0;
1813                         
1814                         m_emergethread.trigger();
1815                 }
1816         }
1817
1818         // Save map, players and auth stuff
1819         {
1820                 float &counter = m_savemap_timer;
1821                 counter += dtime;
1822                 if(counter >= g_settings->getFloat("server_map_save_interval"))
1823                 {
1824                         counter = 0.0;
1825                         JMutexAutoLock lock(m_env_mutex);
1826
1827                         ScopeProfiler sp(g_profiler, "Server: saving stuff");
1828
1829                         // Auth stuff
1830                         if(m_authmanager.isModified())
1831                                 m_authmanager.save();
1832
1833                         //Ban stuff
1834                         if(m_banmanager.isModified())
1835                                 m_banmanager.save();
1836                         
1837                         // Save changed parts of map
1838                         m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
1839
1840                         // Save players
1841                         m_env->serializePlayers(m_path_world);
1842                         
1843                         // Save environment metadata
1844                         m_env->saveMeta(m_path_world);
1845                 }
1846         }
1847 }
1848
1849 void Server::Receive()
1850 {
1851         DSTACK(__FUNCTION_NAME);
1852         SharedBuffer<u8> data;
1853         u16 peer_id;
1854         u32 datasize;
1855         try{
1856                 {
1857                         JMutexAutoLock conlock(m_con_mutex);
1858                         datasize = m_con.Receive(peer_id, data);
1859                 }
1860
1861                 // This has to be called so that the client list gets synced
1862                 // with the peer list of the connection
1863                 handlePeerChanges();
1864
1865                 ProcessData(*data, datasize, peer_id);
1866         }
1867         catch(con::InvalidIncomingDataException &e)
1868         {
1869                 infostream<<"Server::Receive(): "
1870                                 "InvalidIncomingDataException: what()="
1871                                 <<e.what()<<std::endl;
1872         }
1873         catch(con::PeerNotFoundException &e)
1874         {
1875                 //NOTE: This is not needed anymore
1876                 
1877                 // The peer has been disconnected.
1878                 // Find the associated player and remove it.
1879
1880                 /*JMutexAutoLock envlock(m_env_mutex);
1881
1882                 infostream<<"ServerThread: peer_id="<<peer_id
1883                                 <<" has apparently closed connection. "
1884                                 <<"Removing player."<<std::endl;
1885
1886                 m_env->removePlayer(peer_id);*/
1887         }
1888 }
1889
1890 void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
1891 {
1892         DSTACK(__FUNCTION_NAME);
1893         // Environment is locked first.
1894         JMutexAutoLock envlock(m_env_mutex);
1895         JMutexAutoLock conlock(m_con_mutex);
1896         
1897         ScopeProfiler sp(g_profiler, "Server::ProcessData");
1898         
1899         try{
1900                 Address address = m_con.GetPeerAddress(peer_id);
1901
1902                 // drop player if is ip is banned
1903                 if(m_banmanager.isIpBanned(address.serializeString())){
1904                         SendAccessDenied(m_con, peer_id,
1905                                         L"Your ip is banned. Banned name was "
1906                                         +narrow_to_wide(m_banmanager.getBanName(
1907                                                 address.serializeString())));
1908                         m_con.DeletePeer(peer_id);
1909                         return;
1910                 }
1911         }
1912         catch(con::PeerNotFoundException &e)
1913         {
1914                 infostream<<"Server::ProcessData(): Cancelling: peer "
1915                                 <<peer_id<<" not found"<<std::endl;
1916                 return;
1917         }
1918         
1919         std::string addr_s = m_con.GetPeerAddress(peer_id).serializeString();
1920
1921         u8 peer_ser_ver = getClient(peer_id)->serialization_version;
1922
1923         try
1924         {
1925
1926         if(datasize < 2)
1927                 return;
1928
1929         ToServerCommand command = (ToServerCommand)readU16(&data[0]);
1930         
1931         if(command == TOSERVER_INIT)
1932         {
1933                 // [0] u16 TOSERVER_INIT
1934                 // [2] u8 SER_FMT_VER_HIGHEST
1935                 // [3] u8[20] player_name
1936                 // [23] u8[28] password <--- can be sent without this, from old versions
1937
1938                 if(datasize < 2+1+PLAYERNAME_SIZE)
1939                         return;
1940
1941                 verbosestream<<"Server: Got TOSERVER_INIT from "
1942                                 <<peer_id<<std::endl;
1943
1944                 // First byte after command is maximum supported
1945                 // serialization version
1946                 u8 client_max = data[2];
1947                 u8 our_max = SER_FMT_VER_HIGHEST;
1948                 // Use the highest version supported by both
1949                 u8 deployed = core::min_(client_max, our_max);
1950                 // If it's lower than the lowest supported, give up.
1951                 if(deployed < SER_FMT_VER_LOWEST)
1952                         deployed = SER_FMT_VER_INVALID;
1953
1954                 //peer->serialization_version = deployed;
1955                 getClient(peer_id)->pending_serialization_version = deployed;
1956                 
1957                 if(deployed == SER_FMT_VER_INVALID)
1958                 {
1959                         actionstream<<"Server: A mismatched client tried to connect from "
1960                                         <<addr_s<<std::endl;
1961                         infostream<<"Server: Cannot negotiate "
1962                                         "serialization version with peer "
1963                                         <<peer_id<<std::endl;
1964                         SendAccessDenied(m_con, peer_id, std::wstring(
1965                                         L"Your client's version is not supported.\n"
1966                                         L"Server version is ")
1967                                         + narrow_to_wide(VERSION_STRING) + L"."
1968                         );
1969                         return;
1970                 }
1971                 
1972                 /*
1973                         Read and check network protocol version
1974                 */
1975
1976                 u16 net_proto_version = 0;
1977                 if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
1978                 {
1979                         net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
1980                 }
1981
1982                 getClient(peer_id)->net_proto_version = net_proto_version;
1983
1984                 if(net_proto_version == 0)
1985                 {
1986                         actionstream<<"Server: An old tried to connect from "<<addr_s
1987                                         <<std::endl;
1988                         SendAccessDenied(m_con, peer_id, std::wstring(
1989                                         L"Your client's version is not supported.\n"
1990                                         L"Server version is ")
1991                                         + narrow_to_wide(VERSION_STRING) + L"."
1992                         );
1993                         return;
1994                 }
1995                 
1996                 if(g_settings->getBool("strict_protocol_version_checking"))
1997                 {
1998                         if(net_proto_version != PROTOCOL_VERSION)
1999                         {
2000                                 actionstream<<"Server: A mismatched client tried to connect"
2001                                                 <<" from "<<addr_s<<std::endl;
2002                                 SendAccessDenied(m_con, peer_id, std::wstring(
2003                                                 L"Your client's version is not supported.\n"
2004                                                 L"Server version is ")
2005                                                 + narrow_to_wide(VERSION_STRING) + L",\n"
2006                                                 + L"server's PROTOCOL_VERSION is "
2007                                                 + narrow_to_wide(itos(PROTOCOL_VERSION))
2008                                                 + L", client's PROTOCOL_VERSION is "
2009                                                 + narrow_to_wide(itos(net_proto_version))
2010                                 );
2011                                 return;
2012                         }
2013                 }
2014
2015                 /*
2016                         Set up player
2017                 */
2018                 
2019                 // Get player name
2020                 char playername[PLAYERNAME_SIZE];
2021                 for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
2022                 {
2023                         playername[i] = data[3+i];
2024                 }
2025                 playername[PLAYERNAME_SIZE-1] = 0;
2026                 
2027                 if(playername[0]=='\0')
2028                 {
2029                         actionstream<<"Server: Player with an empty name "
2030                                         <<"tried to connect from "<<addr_s<<std::endl;
2031                         SendAccessDenied(m_con, peer_id,
2032                                         L"Empty name");
2033                         return;
2034                 }
2035
2036                 if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false)
2037                 {
2038                         actionstream<<"Server: Player with an invalid name "
2039                                         <<"tried to connect from "<<addr_s<<std::endl;
2040                         SendAccessDenied(m_con, peer_id,
2041                                         L"Name contains unallowed characters");
2042                         return;
2043                 }
2044
2045                 infostream<<"Server: New connection: \""<<playername<<"\" from "
2046                                 <<m_con.GetPeerAddress(peer_id).serializeString()<<std::endl;
2047
2048                 // Get password
2049                 char password[PASSWORD_SIZE];
2050                 if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
2051                 {
2052                         // old version - assume blank password
2053                         password[0] = 0;
2054                 }
2055                 else
2056                 {
2057                         for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2058                         {
2059                                 password[i] = data[23+i];
2060                         }
2061                         password[PASSWORD_SIZE-1] = 0;
2062                 }
2063                 
2064                 // Add player to auth manager
2065                 if(m_authmanager.exists(playername) == false)
2066                 {
2067                         std::wstring default_password =
2068                                 narrow_to_wide(g_settings->get("default_password"));
2069                         std::string translated_default_password =
2070                                 translatePassword(playername, default_password);
2071
2072                         // If default_password is empty, allow any initial password
2073                         if (default_password.length() == 0)
2074                                 translated_default_password = password;
2075
2076                         infostream<<"Server: adding player "<<playername
2077                                         <<" to auth manager"<<std::endl;
2078                         m_authmanager.add(playername);
2079                         m_authmanager.setPassword(playername, translated_default_password);
2080                         m_authmanager.setPrivs(playername,
2081                                         stringToPrivs(g_settings->get("default_privs")));
2082                         m_authmanager.save();
2083                 }
2084
2085                 std::string checkpwd = m_authmanager.getPassword(playername);
2086
2087                 /*infostream<<"Server: Client gave password '"<<password
2088                                 <<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/
2089
2090                 if(password != checkpwd)
2091                 {
2092                         infostream<<"Server: peer_id="<<peer_id
2093                                         <<": supplied invalid password for "
2094                                         <<playername<<std::endl;
2095                         SendAccessDenied(m_con, peer_id, L"Invalid password");
2096                         return;
2097                 }
2098                 
2099                 // Enforce user limit.
2100                 // Don't enforce for users that have some admin right
2101                 if(m_clients.size() >= g_settings->getU16("max_users") &&
2102                                 (m_authmanager.getPrivs(playername)
2103                                         & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS|PRIV_PASSWORD)) == 0 &&
2104                                 playername != g_settings->get("name"))
2105                 {
2106                         actionstream<<"Server: "<<playername<<" tried to join, but there"
2107                                         <<" are already max_users="
2108                                         <<g_settings->getU16("max_users")<<" players."<<std::endl;
2109                         SendAccessDenied(m_con, peer_id, L"Too many users.");
2110                         return;
2111                 }
2112
2113                 // Get player
2114                 ServerRemotePlayer *player = emergePlayer(playername, peer_id);
2115
2116                 // If failed, cancel
2117                 if(player == NULL)
2118                 {
2119                         errorstream<<"Server: peer_id="<<peer_id
2120                                         <<": failed to emerge player"<<std::endl;
2121                         return;
2122                 }
2123
2124                 /*
2125                         Answer with a TOCLIENT_INIT
2126                 */
2127                 {
2128                         SharedBuffer<u8> reply(2+1+6+8);
2129                         writeU16(&reply[0], TOCLIENT_INIT);
2130                         writeU8(&reply[2], deployed);
2131                         writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
2132                         writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
2133                         
2134                         // Send as reliable
2135                         m_con.Send(peer_id, 0, reply, true);
2136                 }
2137
2138                 /*
2139                         Send complete position information
2140                 */
2141                 SendMovePlayer(player);
2142
2143                 return;
2144         }
2145
2146         if(command == TOSERVER_INIT2)
2147         {
2148                 verbosestream<<"Server: Got TOSERVER_INIT2 from "
2149                                 <<peer_id<<std::endl;
2150
2151
2152                 getClient(peer_id)->serialization_version
2153                                 = getClient(peer_id)->pending_serialization_version;
2154
2155                 /*
2156                         Send some initialization data
2157                 */
2158
2159                 infostream<<"Server: Sending content to "
2160                                 <<getPlayerName(peer_id)<<std::endl;
2161
2162                 // Send item definitions
2163                 SendItemDef(m_con, peer_id, m_itemdef);
2164                 
2165                 // Send node definitions
2166                 SendNodeDef(m_con, peer_id, m_nodedef);
2167                 
2168                 // Send texture announcement
2169                 SendTextureAnnouncement(peer_id);
2170                 
2171                 // Send player info to all players
2172                 //SendPlayerInfos();
2173
2174                 // Send inventory to player
2175                 UpdateCrafting(peer_id);
2176                 SendInventory(peer_id);
2177                 
2178                 // Send player items to all players
2179                 SendPlayerItems();
2180
2181                 Player *player = m_env->getPlayer(peer_id);
2182
2183                 // Send HP
2184                 SendPlayerHP(player);
2185                 
2186                 // Show death screen if necessary
2187                 if(player->hp == 0)
2188                         SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
2189
2190                 // Send time of day
2191                 {
2192                         SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
2193                                         m_env->getTimeOfDay());
2194                         m_con.Send(peer_id, 0, data, true);
2195                 }
2196                 
2197                 // Send information about server to player in chat
2198                 SendChatMessage(peer_id, getStatusString());
2199                 
2200                 // Send information about joining in chat
2201                 {
2202                         std::wstring name = L"unknown";
2203                         Player *player = m_env->getPlayer(peer_id);
2204                         if(player != NULL)
2205                                 name = narrow_to_wide(player->getName());
2206                         
2207                         std::wstring message;
2208                         message += L"*** ";
2209                         message += name;
2210                         message += L" joined game";
2211                         BroadcastChatMessage(message);
2212                 }
2213                 
2214                 // Warnings about protocol version can be issued here
2215                 if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION)
2216                 {
2217                         SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER");
2218                 }
2219
2220                 /*
2221                         Print out action
2222                 */
2223                 {
2224                         std::ostringstream os(std::ios_base::binary);
2225                         for(core::map<u16, RemoteClient*>::Iterator
2226                                 i = m_clients.getIterator();
2227                                 i.atEnd() == false; i++)
2228                         {
2229                                 RemoteClient *client = i.getNode()->getValue();
2230                                 assert(client->peer_id == i.getNode()->getKey());
2231                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2232                                         continue;
2233                                 // Get player
2234                                 Player *player = m_env->getPlayer(client->peer_id);
2235                                 if(!player)
2236                                         continue;
2237                                 // Get name of player
2238                                 os<<player->getName()<<" ";
2239                         }
2240
2241                         actionstream<<player->getName()<<" joins game. List of players: "
2242                                         <<os.str()<<std::endl;
2243                 }
2244
2245                 return;
2246         }
2247
2248         if(peer_ser_ver == SER_FMT_VER_INVALID)
2249         {
2250                 infostream<<"Server::ProcessData(): Cancelling: Peer"
2251                                 " serialization format invalid or not initialized."
2252                                 " Skipping incoming command="<<command<<std::endl;
2253                 return;
2254         }
2255         
2256         Player *player = m_env->getPlayer(peer_id);
2257         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
2258
2259         if(player == NULL){
2260                 infostream<<"Server::ProcessData(): Cancelling: "
2261                                 "No player for peer_id="<<peer_id
2262                                 <<std::endl;
2263                 return;
2264         }
2265         if(command == TOSERVER_PLAYERPOS)
2266         {
2267                 if(datasize < 2+12+12+4+4)
2268                         return;
2269         
2270                 u32 start = 0;
2271                 v3s32 ps = readV3S32(&data[start+2]);
2272                 v3s32 ss = readV3S32(&data[start+2+12]);
2273                 f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
2274                 f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
2275                 v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
2276                 v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
2277                 pitch = wrapDegrees(pitch);
2278                 yaw = wrapDegrees(yaw);
2279
2280                 player->setPosition(position);
2281                 player->setSpeed(speed);
2282                 player->setPitch(pitch);
2283                 player->setYaw(yaw);
2284                 
2285                 /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
2286                                 <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
2287                                 <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
2288         }
2289         else if(command == TOSERVER_GOTBLOCKS)
2290         {
2291                 if(datasize < 2+1)
2292                         return;
2293                 
2294                 /*
2295                         [0] u16 command
2296                         [2] u8 count
2297                         [3] v3s16 pos_0
2298                         [3+6] v3s16 pos_1
2299                         ...
2300                 */
2301
2302                 u16 count = data[2];
2303                 for(u16 i=0; i<count; i++)
2304                 {
2305                         if((s16)datasize < 2+1+(i+1)*6)
2306                                 throw con::InvalidIncomingDataException
2307                                         ("GOTBLOCKS length is too short");
2308                         v3s16 p = readV3S16(&data[2+1+i*6]);
2309                         /*infostream<<"Server: GOTBLOCKS ("
2310                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2311                         RemoteClient *client = getClient(peer_id);
2312                         client->GotBlock(p);
2313                 }
2314         }
2315         else if(command == TOSERVER_DELETEDBLOCKS)
2316         {
2317                 if(datasize < 2+1)
2318                         return;
2319                 
2320                 /*
2321                         [0] u16 command
2322                         [2] u8 count
2323                         [3] v3s16 pos_0
2324                         [3+6] v3s16 pos_1
2325                         ...
2326                 */
2327
2328                 u16 count = data[2];
2329                 for(u16 i=0; i<count; i++)
2330                 {
2331                         if((s16)datasize < 2+1+(i+1)*6)
2332                                 throw con::InvalidIncomingDataException
2333                                         ("DELETEDBLOCKS length is too short");
2334                         v3s16 p = readV3S16(&data[2+1+i*6]);
2335                         /*infostream<<"Server: DELETEDBLOCKS ("
2336                                         <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
2337                         RemoteClient *client = getClient(peer_id);
2338                         client->SetBlockNotSent(p);
2339                 }
2340         }
2341         else if(command == TOSERVER_CLICK_OBJECT)
2342         {
2343                 infostream<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
2344                 return;
2345         }
2346         else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
2347         {
2348                 infostream<<"Server: CLICK_ACTIVEOBJECT not supported anymore"<<std::endl;
2349                 return;
2350         }
2351         else if(command == TOSERVER_GROUND_ACTION)
2352         {
2353                 infostream<<"Server: GROUND_ACTION not supported anymore"<<std::endl;
2354                 return;
2355
2356         }
2357         else if(command == TOSERVER_RELEASE)
2358         {
2359                 infostream<<"Server: RELEASE not supported anymore"<<std::endl;
2360                 return;
2361         }
2362         else if(command == TOSERVER_SIGNTEXT)
2363         {
2364                 infostream<<"Server: SIGNTEXT not supported anymore"
2365                                 <<std::endl;
2366                 return;
2367         }
2368         else if(command == TOSERVER_SIGNNODETEXT)
2369         {
2370                 if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2371                         return;
2372                 /*
2373                         u16 command
2374                         v3s16 p
2375                         u16 textlen
2376                         textdata
2377                 */
2378                 std::string datastring((char*)&data[2], datasize-2);
2379                 std::istringstream is(datastring, std::ios_base::binary);
2380                 u8 buf[6];
2381                 // Read stuff
2382                 is.read((char*)buf, 6);
2383                 v3s16 p = readV3S16(buf);
2384                 is.read((char*)buf, 2);
2385                 u16 textlen = readU16(buf);
2386                 std::string text;
2387                 for(u16 i=0; i<textlen; i++)
2388                 {
2389                         is.read((char*)buf, 1);
2390                         text += (char)buf[0];
2391                 }
2392
2393                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(p);
2394                 if(!meta)
2395                         return;
2396
2397                 meta->setText(text);
2398                 
2399                 actionstream<<player->getName()<<" writes \""<<text<<"\" to sign"
2400                                 <<" at "<<PP(p)<<std::endl;
2401                                 
2402                 v3s16 blockpos = getNodeBlockPos(p);
2403                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
2404                 if(block)
2405                 {
2406                         block->raiseModified(MOD_STATE_WRITE_NEEDED,
2407                                         "sign node text");
2408                 }
2409
2410                 setBlockNotSent(blockpos);
2411         }
2412         else if(command == TOSERVER_INVENTORY_ACTION)
2413         {
2414                 // Strip command and create a stream
2415                 std::string datastring((char*)&data[2], datasize-2);
2416                 verbosestream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl;
2417                 std::istringstream is(datastring, std::ios_base::binary);
2418                 // Create an action
2419                 InventoryAction *a = InventoryAction::deSerialize(is);
2420                 if(a == NULL)
2421                 {
2422                         infostream<<"TOSERVER_INVENTORY_ACTION: "
2423                                         <<"InventoryAction::deSerialize() returned NULL"
2424                                         <<std::endl;
2425                         return;
2426                 }
2427
2428                 /*
2429                         Note: Always set inventory not sent, to repair cases
2430                         where the client made a bad prediction.
2431                 */
2432
2433                 /*
2434                         Handle restrictions and special cases of the move action
2435                 */
2436                 if(a->getType() == IACTION_MOVE)
2437                 {
2438                         IMoveAction *ma = (IMoveAction*)a;
2439
2440                         ma->from_inv.applyCurrentPlayer(player->getName());
2441                         ma->to_inv.applyCurrentPlayer(player->getName());
2442
2443                         setInventoryModified(ma->from_inv);
2444                         setInventoryModified(ma->to_inv);
2445
2446                         bool from_inv_is_current_player =
2447                                 (ma->from_inv.type == InventoryLocation::PLAYER) &&
2448                                 (ma->from_inv.name == player->getName());
2449
2450                         bool to_inv_is_current_player =
2451                                 (ma->to_inv.type == InventoryLocation::PLAYER) &&
2452                                 (ma->to_inv.name == player->getName());
2453
2454                         /*
2455                                 Disable moving items out of craftpreview
2456                         */
2457                         if(ma->from_list == "craftpreview")
2458                         {
2459                                 infostream<<"Ignoring IMoveAction from "
2460                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2461                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2462                                                 <<" because src is "<<ma->from_list<<std::endl;
2463                                 delete a;
2464                                 return;
2465                         }
2466
2467                         /*
2468                                 Disable moving items into craftresult and craftpreview
2469                         */
2470                         if(ma->to_list == "craftpreview" || ma->to_list == "craftresult")
2471                         {
2472                                 infostream<<"Ignoring IMoveAction from "
2473                                                 <<(ma->from_inv.dump())<<":"<<ma->from_list
2474                                                 <<" to "<<(ma->to_inv.dump())<<":"<<ma->to_list
2475                                                 <<" because dst is "<<ma->to_list<<std::endl;
2476                                 delete a;
2477                                 return;
2478                         }
2479
2480                         // Disallow moving items in elsewhere than player's inventory
2481                         // if not allowed to interact
2482                         if((getPlayerPrivs(player) & PRIV_INTERACT) == 0
2483                                         && (!from_inv_is_current_player
2484                                         || !to_inv_is_current_player))
2485                         {
2486                                 infostream<<"Cannot move outside of player's inventory: "
2487                                                 <<"No interact privilege"<<std::endl;
2488                                 delete a;
2489                                 return;
2490                         }
2491
2492                         // If player is not an admin, check for ownership of src and dst
2493                         if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
2494                         {
2495                                 std::string owner_from = getInventoryOwner(ma->from_inv);
2496                                 if(owner_from != "" && owner_from != player->getName())
2497                                 {
2498                                         infostream<<"WARNING: "<<player->getName()
2499                                                 <<" tried to access an inventory that"
2500                                                 <<" belongs to "<<owner_from<<std::endl;
2501                                         delete a;
2502                                         return;
2503                                 }
2504
2505                                 std::string owner_to = getInventoryOwner(ma->to_inv);
2506                                 if(owner_to != "" && owner_to != player->getName())
2507                                 {
2508                                         infostream<<"WARNING: "<<player->getName()
2509                                                 <<" tried to access an inventory that"
2510                                                 <<" belongs to "<<owner_to<<std::endl;
2511                                         delete a;
2512                                         return;
2513                                 }
2514                         }
2515                 }
2516                 /*
2517                         Handle restrictions and special cases of the drop action
2518                 */
2519                 else if(a->getType() == IACTION_DROP)
2520                 {
2521                         IDropAction *da = (IDropAction*)a;
2522
2523                         da->from_inv.applyCurrentPlayer(player->getName());
2524
2525                         setInventoryModified(da->from_inv);
2526
2527                         // Disallow dropping items if not allowed to interact
2528                         if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2529                         {
2530                                 delete a;
2531                                 return;
2532                         }
2533                         // If player is not an admin, check for ownership
2534                         else if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
2535                         {
2536                                 std::string owner_from = getInventoryOwner(da->from_inv);
2537                                 if(owner_from != "" && owner_from != player->getName())
2538                                 {
2539                                         infostream<<"WARNING: "<<player->getName()
2540                                                 <<" tried to access an inventory that"
2541                                                 <<" belongs to "<<owner_from<<std::endl;
2542                                         delete a;
2543                                         return;
2544                                 }
2545                         }
2546                 }
2547                 /*
2548                         Handle restrictions and special cases of the craft action
2549                 */
2550                 else if(a->getType() == IACTION_CRAFT)
2551                 {
2552                         ICraftAction *ca = (ICraftAction*)a;
2553
2554                         ca->craft_inv.applyCurrentPlayer(player->getName());
2555
2556                         setInventoryModified(ca->craft_inv);
2557
2558                         //bool craft_inv_is_current_player =
2559                         //      (ca->craft_inv.type == InventoryLocation::PLAYER) &&
2560                         //      (ca->craft_inv.name == player->getName());
2561
2562                         // Disallow crafting if not allowed to interact
2563                         if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2564                         {
2565                                 infostream<<"Cannot craft: "
2566                                                 <<"No interact privilege"<<std::endl;
2567                                 delete a;
2568                                 return;
2569                         }
2570
2571                         // If player is not an admin, check for ownership of inventory
2572                         if((getPlayerPrivs(player) & PRIV_SERVER) == 0)
2573                         {
2574                                 std::string owner_craft = getInventoryOwner(ca->craft_inv);
2575                                 if(owner_craft != "" && owner_craft != player->getName())
2576                                 {
2577                                         infostream<<"WARNING: "<<player->getName()
2578                                                 <<" tried to access an inventory that"
2579                                                 <<" belongs to "<<owner_craft<<std::endl;
2580                                         delete a;
2581                                         return;
2582                                 }
2583                         }
2584                 }
2585                 
2586                 // Do the action
2587                 a->apply(this, srp, this);
2588                 // Eat the action
2589                 delete a;
2590         }
2591         else if(command == TOSERVER_CHAT_MESSAGE)
2592         {
2593                 /*
2594                         u16 command
2595                         u16 length
2596                         wstring message
2597                 */
2598                 u8 buf[6];
2599                 std::string datastring((char*)&data[2], datasize-2);
2600                 std::istringstream is(datastring, std::ios_base::binary);
2601                 
2602                 // Read stuff
2603                 is.read((char*)buf, 2);
2604                 u16 len = readU16(buf);
2605                 
2606                 std::wstring message;
2607                 for(u16 i=0; i<len; i++)
2608                 {
2609                         is.read((char*)buf, 2);
2610                         message += (wchar_t)readU16(buf);
2611                 }
2612
2613                 // Get player name of this client
2614                 std::wstring name = narrow_to_wide(player->getName());
2615                 
2616                 // Run script hook
2617                 bool ate = scriptapi_on_chat_message(m_lua, player->getName(),
2618                                 wide_to_narrow(message));
2619                 // If script ate the message, don't proceed
2620                 if(ate)
2621                         return;
2622                 
2623                 // Line to send to players
2624                 std::wstring line;
2625                 // Whether to send to the player that sent the line
2626                 bool send_to_sender = false;
2627                 // Whether to send to other players
2628                 bool send_to_others = false;
2629                 
2630                 // Local player gets all privileges regardless of
2631                 // what's set on their account.
2632                 u64 privs = getPlayerPrivs(player);
2633
2634                 // Parse commands
2635                 if(message[0] == L'/')
2636                 {
2637                         size_t strip_size = 1;
2638                         if (message[1] == L'#') // support old-style commans
2639                                 ++strip_size;
2640                         message = message.substr(strip_size);
2641
2642                         WStrfnd f1(message);
2643                         f1.next(L" "); // Skip over /#whatever
2644                         std::wstring paramstring = f1.next(L"");
2645
2646                         ServerCommandContext *ctx = new ServerCommandContext(
2647                                 str_split(message, L' '),
2648                                 paramstring,
2649                                 this,
2650                                 m_env,
2651                                 player,
2652                                 privs);
2653
2654                         std::wstring reply(processServerCommand(ctx));
2655                         send_to_sender = ctx->flags & SEND_TO_SENDER;
2656                         send_to_others = ctx->flags & SEND_TO_OTHERS;
2657
2658                         if (ctx->flags & SEND_NO_PREFIX)
2659                                 line += reply;
2660                         else
2661                                 line += L"Server: " + reply;
2662
2663                         delete ctx;
2664
2665                 }
2666                 else
2667                 {
2668                         if(privs & PRIV_SHOUT)
2669                         {
2670                                 line += L"<";
2671                                 line += name;
2672                                 line += L"> ";
2673                                 line += message;
2674                                 send_to_others = true;
2675                         }
2676                         else
2677                         {
2678                                 line += L"Server: You are not allowed to shout";
2679                                 send_to_sender = true;
2680                         }
2681                 }
2682                 
2683                 if(line != L"")
2684                 {
2685                         if(send_to_others)
2686                                 actionstream<<"CHAT: "<<wide_to_narrow(line)<<std::endl;
2687
2688                         /*
2689                                 Send the message to clients
2690                         */
2691                         for(core::map<u16, RemoteClient*>::Iterator
2692                                 i = m_clients.getIterator();
2693                                 i.atEnd() == false; i++)
2694                         {
2695                                 // Get client and check that it is valid
2696                                 RemoteClient *client = i.getNode()->getValue();
2697                                 assert(client->peer_id == i.getNode()->getKey());
2698                                 if(client->serialization_version == SER_FMT_VER_INVALID)
2699                                         continue;
2700
2701                                 // Filter recipient
2702                                 bool sender_selected = (peer_id == client->peer_id);
2703                                 if(sender_selected == true && send_to_sender == false)
2704                                         continue;
2705                                 if(sender_selected == false && send_to_others == false)
2706                                         continue;
2707
2708                                 SendChatMessage(client->peer_id, line);
2709                         }
2710                 }
2711         }
2712         else if(command == TOSERVER_DAMAGE)
2713         {
2714                 std::string datastring((char*)&data[2], datasize-2);
2715                 std::istringstream is(datastring, std::ios_base::binary);
2716                 u8 damage = readU8(is);
2717
2718                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
2719
2720                 if(g_settings->getBool("enable_damage"))
2721                 {
2722                         actionstream<<player->getName()<<" damaged by "
2723                                         <<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
2724                                         <<std::endl;
2725
2726                         srp->setHP(srp->getHP() - damage);
2727
2728                         if(srp->getHP() == 0 && srp->m_hp_not_sent)
2729                                 DiePlayer(srp);
2730
2731                         if(srp->m_hp_not_sent)
2732                                 SendPlayerHP(player);
2733                 }
2734                 else
2735                 {
2736                         // Force send (to correct the client's predicted HP)
2737                         SendPlayerHP(player);
2738                 }
2739         }
2740         else if(command == TOSERVER_PASSWORD)
2741         {
2742                 /*
2743                         [0] u16 TOSERVER_PASSWORD
2744                         [2] u8[28] old password
2745                         [30] u8[28] new password
2746                 */
2747
2748                 if(datasize != 2+PASSWORD_SIZE*2)
2749                         return;
2750                 /*char password[PASSWORD_SIZE];
2751                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2752                         password[i] = data[2+i];
2753                 password[PASSWORD_SIZE-1] = 0;*/
2754                 std::string oldpwd;
2755                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2756                 {
2757                         char c = data[2+i];
2758                         if(c == 0)
2759                                 break;
2760                         oldpwd += c;
2761                 }
2762                 std::string newpwd;
2763                 for(u32 i=0; i<PASSWORD_SIZE-1; i++)
2764                 {
2765                         char c = data[2+PASSWORD_SIZE+i];
2766                         if(c == 0)
2767                                 break;
2768                         newpwd += c;
2769                 }
2770
2771                 infostream<<"Server: Client requests a password change from "
2772                                 <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
2773
2774                 std::string playername = player->getName();
2775
2776                 if(m_authmanager.exists(playername) == false)
2777                 {
2778                         infostream<<"Server: playername not found in authmanager"<<std::endl;
2779                         // Wrong old password supplied!!
2780                         SendChatMessage(peer_id, L"playername not found in authmanager");
2781                         return;
2782                 }
2783
2784                 std::string checkpwd = m_authmanager.getPassword(playername);
2785
2786                 if(oldpwd != checkpwd)
2787                 {
2788                         infostream<<"Server: invalid old password"<<std::endl;
2789                         // Wrong old password supplied!!
2790                         SendChatMessage(peer_id, L"Invalid old password supplied. Password NOT changed.");
2791                         return;
2792                 }
2793
2794                 actionstream<<player->getName()<<" changes password"<<std::endl;
2795
2796                 m_authmanager.setPassword(playername, newpwd);
2797                 
2798                 infostream<<"Server: password change successful for "<<playername
2799                                 <<std::endl;
2800                 SendChatMessage(peer_id, L"Password change successful");
2801         }
2802         else if(command == TOSERVER_PLAYERITEM)
2803         {
2804                 if (datasize < 2+2)
2805                         return;
2806
2807                 u16 item = readU16(&data[2]);
2808                 srp->setWieldIndex(item);
2809                 SendWieldedItem(srp);
2810         }
2811         else if(command == TOSERVER_RESPAWN)
2812         {
2813                 if(player->hp != 0)
2814                         return;
2815                 
2816                 RespawnPlayer(player);
2817                 
2818                 actionstream<<player->getName()<<" respawns at "
2819                                 <<PP(player->getPosition()/BS)<<std::endl;
2820
2821                 // ActiveObject is added to environment in AsyncRunStep after
2822                 // the previous addition has been succesfully removed
2823         }
2824         else if(command == TOSERVER_REQUEST_TEXTURES) {
2825                 std::string datastring((char*)&data[2], datasize-2);
2826                 std::istringstream is(datastring, std::ios_base::binary);
2827                 
2828                 
2829                 core::list<TextureRequest> tosend;
2830                 u16 numtextures = readU16(is);
2831
2832                 infostream<<"Sending "<<numtextures<<" textures to "
2833                                 <<getPlayerName(peer_id)<<std::endl;
2834                 verbosestream<<"TOSERVER_REQUEST_TEXTURES: "<<std::endl;
2835
2836                 for(int i = 0; i < numtextures; i++) {
2837                         std::string name = deSerializeString(is);
2838                         tosend.push_back(TextureRequest(name));
2839                         verbosestream<<"TOSERVER_REQUEST_TEXTURES: requested texture "
2840                                         <<name<<std::endl;
2841                 }
2842
2843                 SendTexturesRequested(peer_id, tosend);
2844
2845                 // Now the client should know about everything
2846                 // (definitions and textures)
2847                 getClient(peer_id)->definitions_sent = true;
2848         }
2849         else if(command == TOSERVER_INTERACT)
2850         {
2851                 std::string datastring((char*)&data[2], datasize-2);
2852                 std::istringstream is(datastring, std::ios_base::binary);
2853
2854                 /*
2855                         [0] u16 command
2856                         [2] u8 action
2857                         [3] u16 item
2858                         [5] u32 length of the next item
2859                         [9] serialized PointedThing
2860                         actions:
2861                         0: start digging (from undersurface) or use
2862                         1: stop digging (all parameters ignored)
2863                         2: digging completed
2864                         3: place block or item (to abovesurface)
2865                         4: use item
2866                 */
2867                 u8 action = readU8(is);
2868                 u16 item_i = readU16(is);
2869                 std::istringstream tmp_is(deSerializeLongString(is), std::ios::binary);
2870                 PointedThing pointed;
2871                 pointed.deSerialize(tmp_is);
2872
2873                 verbosestream<<"TOSERVER_INTERACT: action="<<(int)action<<", item="
2874                                 <<item_i<<", pointed="<<pointed.dump()<<std::endl;
2875
2876                 if(player->hp == 0)
2877                 {
2878                         verbosestream<<"TOSERVER_INTERACT: "<<srp->getName()
2879                                 <<" tried to interact, but is dead!"<<std::endl;
2880                         return;
2881                 }
2882
2883                 v3f player_pos = srp->m_last_good_position;
2884
2885                 // Update wielded item
2886                 if(srp->getWieldIndex() != item_i)
2887                 {
2888                         srp->setWieldIndex(item_i);
2889                         SendWieldedItem(srp);
2890                 }
2891
2892                 // Get pointed to node (undefined if not POINTEDTYPE_NODE)
2893                 v3s16 p_under = pointed.node_undersurface;
2894                 v3s16 p_above = pointed.node_abovesurface;
2895
2896                 // Get pointed to object (NULL if not POINTEDTYPE_OBJECT)
2897                 ServerActiveObject *pointed_object = NULL;
2898                 if(pointed.type == POINTEDTHING_OBJECT)
2899                 {
2900                         pointed_object = m_env->getActiveObject(pointed.object_id);
2901                         if(pointed_object == NULL)
2902                         {
2903                                 verbosestream<<"TOSERVER_INTERACT: "
2904                                         "pointed object is NULL"<<std::endl;
2905                                 return;
2906                         }
2907
2908                 }
2909
2910                 v3f pointed_pos_under = player_pos;
2911                 v3f pointed_pos_above = player_pos;
2912                 if(pointed.type == POINTEDTHING_NODE)
2913                 {
2914                         pointed_pos_under = intToFloat(p_under, BS);
2915                         pointed_pos_above = intToFloat(p_above, BS);
2916                 }
2917                 else if(pointed.type == POINTEDTHING_OBJECT)
2918                 {
2919                         pointed_pos_under = pointed_object->getBasePosition();
2920                         pointed_pos_above = pointed_pos_under;
2921                 }
2922
2923                 /*
2924                         Check that target is reasonably close
2925                         (only when digging or placing things)
2926                 */
2927                 if(action == 0 || action == 2 || action == 3)
2928                 {
2929                         float d = player_pos.getDistanceFrom(pointed_pos_under);
2930                         float max_d = BS * 14; // Just some large enough value
2931                         if(d > max_d){
2932                                 actionstream<<"Player "<<player->getName()
2933                                                 <<" tried to access "<<pointed.dump()
2934                                                 <<" from too far: "
2935                                                 <<"d="<<d<<", max_d="<<max_d
2936                                                 <<". ignoring."<<std::endl;
2937                                 // Re-send block to revert change on client-side
2938                                 RemoteClient *client = getClient(peer_id);
2939                                 v3s16 blockpos = getNodeBlockPos(floatToInt(pointed_pos_under, BS));
2940                                 client->SetBlockNotSent(blockpos);
2941                                 // Do nothing else
2942                                 return;
2943                         }
2944                 }
2945
2946                 /*
2947                         Make sure the player is allowed to do it
2948                 */
2949                 if((getPlayerPrivs(player) & PRIV_INTERACT) == 0)
2950                 {
2951                         infostream<<"Ignoring interaction from player "<<player->getName()
2952                                         <<" because privileges are "<<getPlayerPrivs(player)
2953                                         <<std::endl;
2954                         return;
2955                 }
2956
2957                 /*
2958                         0: start digging or punch object
2959                 */
2960                 if(action == 0)
2961                 {
2962                         if(pointed.type == POINTEDTHING_NODE)
2963                         {
2964                                 /*
2965                                         NOTE: This can be used in the future to check if
2966                                         somebody is cheating, by checking the timing.
2967                                 */
2968                                 MapNode n(CONTENT_IGNORE);
2969                                 try
2970                                 {
2971                                         n = m_env->getMap().getNode(p_under);
2972                                 }
2973                                 catch(InvalidPositionException &e)
2974                                 {
2975                                         infostream<<"Server: Not punching: Node not found."
2976                                                         <<" Adding block to emerge queue."
2977                                                         <<std::endl;
2978                                         m_emerge_queue.addBlock(peer_id,
2979                                                         getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
2980                                 }
2981                                 if(n.getContent() != CONTENT_IGNORE)
2982                                         scriptapi_node_on_punch(m_lua, p_under, n, srp);
2983                         }
2984                         else if(pointed.type == POINTEDTHING_OBJECT)
2985                         {
2986                                 // Skip if object has been removed
2987                                 if(pointed_object->m_removed)
2988                                         return;
2989
2990                                 actionstream<<player->getName()<<" punches object "
2991                                                 <<pointed.object_id<<": "
2992                                                 <<pointed_object->getDescription()<<std::endl;
2993
2994                                 ItemStack punchitem = srp->getWieldedItem();
2995                                 ToolCapabilities toolcap =
2996                                                 punchitem.getToolCapabilities(m_itemdef);
2997                                 v3f dir = (pointed_object->getBasePosition() -
2998                                                 (srp->getPosition() + srp->getEyeOffset())
2999                                                         ).normalize();
3000                                 pointed_object->punch(dir, &toolcap, srp,
3001                                                 srp->m_time_from_last_punch);
3002                                 srp->m_time_from_last_punch = 0;
3003                         }
3004
3005                 } // action == 0
3006
3007                 /*
3008                         1: stop digging
3009                 */
3010                 else if(action == 1)
3011                 {
3012                 } // action == 1
3013
3014                 /*
3015                         2: Digging completed
3016                 */
3017                 else if(action == 2)
3018                 {
3019                         // Only complete digging of nodes
3020                         if(pointed.type == POINTEDTHING_NODE)
3021                         {
3022                                 MapNode n(CONTENT_IGNORE);
3023                                 try
3024                                 {
3025                                         n = m_env->getMap().getNode(p_under);
3026                                 }
3027                                 catch(InvalidPositionException &e)
3028                                 {
3029                                         infostream<<"Server: Not finishing digging: Node not found."
3030                                                         <<" Adding block to emerge queue."
3031                                                         <<std::endl;
3032                                         m_emerge_queue.addBlock(peer_id,
3033                                                         getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
3034                                 }
3035                                 if(n.getContent() != CONTENT_IGNORE)
3036                                         scriptapi_node_on_dig(m_lua, p_under, n, srp);
3037                         }
3038                 } // action == 2
3039                 
3040                 /*
3041                         3: place block or right-click object
3042                 */
3043                 else if(action == 3)
3044                 {
3045                         ItemStack item = srp->getWieldedItem();
3046
3047                         // Reset build time counter
3048                         if(pointed.type == POINTEDTHING_NODE &&
3049                                         item.getDefinition(m_itemdef).type == ITEM_NODE)
3050                                 getClient(peer_id)->m_time_from_building = 0.0;
3051
3052                         if(pointed.type == POINTEDTHING_OBJECT)
3053                         {
3054                                 // Right click object
3055
3056                                 // Skip if object has been removed
3057                                 if(pointed_object->m_removed)
3058                                         return;
3059
3060                                 actionstream<<player->getName()<<" right-clicks object "
3061                                                 <<pointed.object_id<<": "
3062                                                 <<pointed_object->getDescription()<<std::endl;
3063
3064                                 // Do stuff
3065                                 pointed_object->rightClick(srp);
3066                         }
3067                         else if(scriptapi_item_on_place(m_lua,
3068                                         item, srp, pointed))
3069                         {
3070                                 // Placement was handled in lua
3071
3072                                 // Apply returned ItemStack
3073                                 if(g_settings->getBool("creative_mode") == false)
3074                                         srp->setWieldedItem(item);
3075                         }
3076
3077                 } // action == 3
3078
3079                 /*
3080                         4: use
3081                 */
3082                 else if(action == 4)
3083                 {
3084                         ItemStack item = srp->getWieldedItem();
3085
3086                         actionstream<<player->getName()<<" uses "<<item.name
3087                                         <<", pointing at "<<pointed.dump()<<std::endl;
3088
3089                         if(scriptapi_item_on_use(m_lua,
3090                                         item, srp, pointed))
3091                         {
3092                                 // Apply returned ItemStack
3093                                 if(g_settings->getBool("creative_mode") == false)
3094                                         srp->setWieldedItem(item);
3095                         }
3096
3097                 } // action == 4
3098
3099                 /*
3100                         Catch invalid actions
3101                 */
3102                 else
3103                 {
3104                         infostream<<"WARNING: Server: Invalid action "
3105                                         <<action<<std::endl;
3106                 }
3107         }
3108         else
3109         {
3110                 infostream<<"Server::ProcessData(): Ignoring "
3111                                 "unknown command "<<command<<std::endl;
3112         }
3113         
3114         } //try
3115         catch(SendFailedException &e)
3116         {
3117                 errorstream<<"Server::ProcessData(): SendFailedException: "
3118                                 <<"what="<<e.what()
3119                                 <<std::endl;
3120         }
3121 }
3122
3123 void Server::onMapEditEvent(MapEditEvent *event)
3124 {
3125         //infostream<<"Server::onMapEditEvent()"<<std::endl;
3126         if(m_ignore_map_edit_events)
3127                 return;
3128         MapEditEvent *e = event->clone();
3129         m_unsent_map_edit_queue.push_back(e);
3130 }
3131
3132 Inventory* Server::getInventory(const InventoryLocation &loc)
3133 {
3134         switch(loc.type){
3135         case InventoryLocation::UNDEFINED:
3136         {}
3137         break;
3138         case InventoryLocation::CURRENT_PLAYER:
3139         {}
3140         break;
3141         case InventoryLocation::PLAYER:
3142         {
3143                 Player *player = m_env->getPlayer(loc.name.c_str());
3144                 if(!player)
3145                         return NULL;
3146                 return &player->inventory;
3147         }
3148         break;
3149         case InventoryLocation::NODEMETA:
3150         {
3151                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3152                 if(!meta)
3153                         return NULL;
3154                 return meta->getInventory();
3155         }
3156         break;
3157         default:
3158                 assert(0);
3159         }
3160         return NULL;
3161 }
3162 std::string Server::getInventoryOwner(const InventoryLocation &loc)
3163 {
3164         switch(loc.type){
3165         case InventoryLocation::UNDEFINED:
3166         {}
3167         break;
3168         case InventoryLocation::CURRENT_PLAYER:
3169         {}
3170         break;
3171         case InventoryLocation::PLAYER:
3172         {
3173                 return loc.name;
3174         }
3175         break;
3176         case InventoryLocation::NODEMETA:
3177         {
3178                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3179                 if(!meta)
3180                         return "";
3181                 return meta->getOwner();
3182         }
3183         break;
3184         default:
3185                 assert(0);
3186         }
3187         return "";
3188 }
3189 void Server::setInventoryModified(const InventoryLocation &loc)
3190 {
3191         switch(loc.type){
3192         case InventoryLocation::UNDEFINED:
3193         {}
3194         break;
3195         case InventoryLocation::PLAYER:
3196         {
3197                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
3198                                 (m_env->getPlayer(loc.name.c_str()));
3199                 if(!srp)
3200                         return;
3201                 srp->m_inventory_not_sent = true;
3202         }
3203         break;
3204         case InventoryLocation::NODEMETA:
3205         {
3206                 v3s16 blockpos = getNodeBlockPos(loc.p);
3207
3208                 NodeMetadata *meta = m_env->getMap().getNodeMetadata(loc.p);
3209                 if(meta)
3210                         meta->inventoryModified();
3211                 
3212                 MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
3213                 if(block)
3214                         block->raiseModified(MOD_STATE_WRITE_NEEDED);
3215                 
3216                 setBlockNotSent(blockpos);
3217         }
3218         break;
3219         default:
3220                 assert(0);
3221         }
3222 }
3223
3224 core::list<PlayerInfo> Server::getPlayerInfo()
3225 {
3226         DSTACK(__FUNCTION_NAME);
3227         JMutexAutoLock envlock(m_env_mutex);
3228         JMutexAutoLock conlock(m_con_mutex);
3229         
3230         core::list<PlayerInfo> list;
3231
3232         core::list<Player*> players = m_env->getPlayers();
3233         
3234         core::list<Player*>::Iterator i;
3235         for(i = players.begin();
3236                         i != players.end(); i++)
3237         {
3238                 PlayerInfo info;
3239
3240                 Player *player = *i;
3241
3242                 try{
3243                         // Copy info from connection to info struct
3244                         info.id = player->peer_id;
3245                         info.address = m_con.GetPeerAddress(player->peer_id);
3246                         info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id);
3247                 }
3248                 catch(con::PeerNotFoundException &e)
3249                 {
3250                         // Set dummy peer info
3251                         info.id = 0;
3252                         info.address = Address(0,0,0,0,0);
3253                         info.avg_rtt = 0.0;
3254                 }
3255
3256                 snprintf(info.name, PLAYERNAME_SIZE, "%s", player->getName());
3257                 info.position = player->getPosition();
3258
3259                 list.push_back(info);
3260         }
3261
3262         return list;
3263 }
3264
3265
3266 void Server::peerAdded(con::Peer *peer)
3267 {
3268         DSTACK(__FUNCTION_NAME);
3269         verbosestream<<"Server::peerAdded(): peer->id="
3270                         <<peer->id<<std::endl;
3271         
3272         PeerChange c;
3273         c.type = PEER_ADDED;
3274         c.peer_id = peer->id;
3275         c.timeout = false;
3276         m_peer_change_queue.push_back(c);
3277 }
3278
3279 void Server::deletingPeer(con::Peer *peer, bool timeout)
3280 {
3281         DSTACK(__FUNCTION_NAME);
3282         verbosestream<<"Server::deletingPeer(): peer->id="
3283                         <<peer->id<<", timeout="<<timeout<<std::endl;
3284         
3285         PeerChange c;
3286         c.type = PEER_REMOVED;
3287         c.peer_id = peer->id;
3288         c.timeout = timeout;
3289         m_peer_change_queue.push_back(c);
3290 }
3291
3292 /*
3293         Static send methods
3294 */
3295
3296 void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
3297 {
3298         DSTACK(__FUNCTION_NAME);
3299         std::ostringstream os(std::ios_base::binary);
3300
3301         writeU16(os, TOCLIENT_HP);
3302         writeU8(os, hp);
3303
3304         // Make data buffer
3305         std::string s = os.str();
3306         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3307         // Send as reliable
3308         con.Send(peer_id, 0, data, true);
3309 }
3310
3311 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
3312                 const std::wstring &reason)
3313 {
3314         DSTACK(__FUNCTION_NAME);
3315         std::ostringstream os(std::ios_base::binary);
3316
3317         writeU16(os, TOCLIENT_ACCESS_DENIED);
3318         os<<serializeWideString(reason);
3319
3320         // Make data buffer
3321         std::string s = os.str();
3322         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3323         // Send as reliable
3324         con.Send(peer_id, 0, data, true);
3325 }
3326
3327 void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
3328                 bool set_camera_point_target, v3f camera_point_target)
3329 {
3330         DSTACK(__FUNCTION_NAME);
3331         std::ostringstream os(std::ios_base::binary);
3332
3333         writeU16(os, TOCLIENT_DEATHSCREEN);
3334         writeU8(os, set_camera_point_target);
3335         writeV3F1000(os, camera_point_target);
3336
3337         // Make data buffer
3338         std::string s = os.str();
3339         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3340         // Send as reliable
3341         con.Send(peer_id, 0, data, true);
3342 }
3343
3344 void Server::SendItemDef(con::Connection &con, u16 peer_id,
3345                 IItemDefManager *itemdef)
3346 {
3347         DSTACK(__FUNCTION_NAME);
3348         std::ostringstream os(std::ios_base::binary);
3349
3350         /*
3351                 u16 command
3352                 u32 length of the next item
3353                 zlib-compressed serialized ItemDefManager
3354         */
3355         writeU16(os, TOCLIENT_ITEMDEF);
3356         std::ostringstream tmp_os(std::ios::binary);
3357         itemdef->serialize(tmp_os);
3358         std::ostringstream tmp_os2(std::ios::binary);
3359         compressZlib(tmp_os.str(), tmp_os2);
3360         os<<serializeLongString(tmp_os2.str());
3361
3362         // Make data buffer
3363         std::string s = os.str();
3364         verbosestream<<"Server: Sending item definitions to id("<<peer_id
3365                         <<"): size="<<s.size()<<std::endl;
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::SendNodeDef(con::Connection &con, u16 peer_id,
3372                 INodeDefManager *nodedef)
3373 {
3374         DSTACK(__FUNCTION_NAME);
3375         std::ostringstream os(std::ios_base::binary);
3376
3377         /*
3378                 u16 command
3379                 u32 length of the next item
3380                 zlib-compressed serialized NodeDefManager
3381         */
3382         writeU16(os, TOCLIENT_NODEDEF);
3383         std::ostringstream tmp_os(std::ios::binary);
3384         nodedef->serialize(tmp_os);
3385         std::ostringstream tmp_os2(std::ios::binary);
3386         compressZlib(tmp_os.str(), tmp_os2);
3387         os<<serializeLongString(tmp_os2.str());
3388
3389         // Make data buffer
3390         std::string s = os.str();
3391         verbosestream<<"Server: Sending node definitions to id("<<peer_id
3392                         <<"): size="<<s.size()<<std::endl;
3393         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3394         // Send as reliable
3395         con.Send(peer_id, 0, data, true);
3396 }
3397
3398 /*
3399         Non-static send methods
3400 */
3401
3402 void Server::SendInventory(u16 peer_id)
3403 {
3404         DSTACK(__FUNCTION_NAME);
3405         
3406         ServerRemotePlayer* player =
3407                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(peer_id));
3408         assert(player);
3409
3410         player->m_inventory_not_sent = false;
3411
3412         /*
3413                 Serialize it
3414         */
3415
3416         std::ostringstream os;
3417         //os.imbue(std::locale("C"));
3418
3419         player->inventory.serialize(os);
3420
3421         std::string s = os.str();
3422         
3423         SharedBuffer<u8> data(s.size()+2);
3424         writeU16(&data[0], TOCLIENT_INVENTORY);
3425         memcpy(&data[2], s.c_str(), s.size());
3426         
3427         // Send as reliable
3428         m_con.Send(peer_id, 0, data, true);
3429 }
3430
3431 void Server::SendWieldedItem(const ServerRemotePlayer* srp)
3432 {
3433         DSTACK(__FUNCTION_NAME);
3434
3435         assert(srp);
3436
3437         std::ostringstream os(std::ios_base::binary);
3438
3439         writeU16(os, TOCLIENT_PLAYERITEM);
3440         writeU16(os, 1);
3441         writeU16(os, srp->peer_id);
3442         os<<serializeString(srp->getWieldedItem().getItemString());
3443
3444         // Make data buffer
3445         std::string s = os.str();
3446         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3447
3448         m_con.SendToAll(0, data, true);
3449 }
3450
3451 void Server::SendPlayerItems()
3452 {
3453         DSTACK(__FUNCTION_NAME);
3454
3455         std::ostringstream os(std::ios_base::binary);
3456         core::list<Player *> players = m_env->getPlayers(true);
3457
3458         writeU16(os, TOCLIENT_PLAYERITEM);
3459         writeU16(os, players.size());
3460         core::list<Player *>::Iterator i;
3461         for(i = players.begin(); i != players.end(); ++i)
3462         {
3463                 Player *p = *i;
3464                 ServerRemotePlayer *srp =
3465                         static_cast<ServerRemotePlayer*>(p);
3466                 writeU16(os, p->peer_id);
3467                 os<<serializeString(srp->getWieldedItem().getItemString());
3468         }
3469
3470         // Make data buffer
3471         std::string s = os.str();
3472         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3473
3474         m_con.SendToAll(0, data, true);
3475 }
3476
3477 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
3478 {
3479         DSTACK(__FUNCTION_NAME);
3480         
3481         std::ostringstream os(std::ios_base::binary);
3482         u8 buf[12];
3483         
3484         // Write command
3485         writeU16(buf, TOCLIENT_CHAT_MESSAGE);
3486         os.write((char*)buf, 2);
3487         
3488         // Write length
3489         writeU16(buf, message.size());
3490         os.write((char*)buf, 2);
3491         
3492         // Write string
3493         for(u32 i=0; i<message.size(); i++)
3494         {
3495                 u16 w = message[i];
3496                 writeU16(buf, w);
3497                 os.write((char*)buf, 2);
3498         }
3499         
3500         // Make data buffer
3501         std::string s = os.str();
3502         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3503         // Send as reliable
3504         m_con.Send(peer_id, 0, data, true);
3505 }
3506
3507 void Server::BroadcastChatMessage(const std::wstring &message)
3508 {
3509         for(core::map<u16, RemoteClient*>::Iterator
3510                 i = m_clients.getIterator();
3511                 i.atEnd() == false; i++)
3512         {
3513                 // Get client and check that it is valid
3514                 RemoteClient *client = i.getNode()->getValue();
3515                 assert(client->peer_id == i.getNode()->getKey());
3516                 if(client->serialization_version == SER_FMT_VER_INVALID)
3517                         continue;
3518
3519                 SendChatMessage(client->peer_id, message);
3520         }
3521 }
3522
3523 void Server::SendPlayerHP(Player *player)
3524 {
3525         SendHP(m_con, player->peer_id, player->hp);
3526         static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
3527 }
3528
3529 void Server::SendMovePlayer(Player *player)
3530 {
3531         DSTACK(__FUNCTION_NAME);
3532         std::ostringstream os(std::ios_base::binary);
3533
3534         writeU16(os, TOCLIENT_MOVE_PLAYER);
3535         writeV3F1000(os, player->getPosition());
3536         writeF1000(os, player->getPitch());
3537         writeF1000(os, player->getYaw());
3538         
3539         {
3540                 v3f pos = player->getPosition();
3541                 f32 pitch = player->getPitch();
3542                 f32 yaw = player->getYaw();
3543                 verbosestream<<"Server: Sending TOCLIENT_MOVE_PLAYER"
3544                                 <<" pos=("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
3545                                 <<" pitch="<<pitch
3546                                 <<" yaw="<<yaw
3547                                 <<std::endl;
3548         }
3549
3550         // Make data buffer
3551         std::string s = os.str();
3552         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3553         // Send as reliable
3554         m_con.Send(player->peer_id, 0, data, true);
3555 }
3556
3557 void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
3558         core::list<u16> *far_players, float far_d_nodes)
3559 {
3560         float maxd = far_d_nodes*BS;
3561         v3f p_f = intToFloat(p, BS);
3562
3563         // Create packet
3564         u32 replysize = 8;
3565         SharedBuffer<u8> reply(replysize);
3566         writeU16(&reply[0], TOCLIENT_REMOVENODE);
3567         writeS16(&reply[2], p.X);
3568         writeS16(&reply[4], p.Y);
3569         writeS16(&reply[6], p.Z);
3570
3571         for(core::map<u16, RemoteClient*>::Iterator
3572                 i = m_clients.getIterator();
3573                 i.atEnd() == false; i++)
3574         {
3575                 // Get client and check that it is valid
3576                 RemoteClient *client = i.getNode()->getValue();
3577                 assert(client->peer_id == i.getNode()->getKey());
3578                 if(client->serialization_version == SER_FMT_VER_INVALID)
3579                         continue;
3580
3581                 // Don't send if it's the same one
3582                 if(client->peer_id == ignore_id)
3583                         continue;
3584                 
3585                 if(far_players)
3586                 {
3587                         // Get player
3588                         Player *player = m_env->getPlayer(client->peer_id);
3589                         if(player)
3590                         {
3591                                 // If player is far away, only set modified blocks not sent
3592                                 v3f player_pos = player->getPosition();
3593                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3594                                 {
3595                                         far_players->push_back(client->peer_id);
3596                                         continue;
3597                                 }
3598                         }
3599                 }
3600
3601                 // Send as reliable
3602                 m_con.Send(client->peer_id, 0, reply, true);
3603         }
3604 }
3605
3606 void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
3607                 core::list<u16> *far_players, float far_d_nodes)
3608 {
3609         float maxd = far_d_nodes*BS;
3610         v3f p_f = intToFloat(p, BS);
3611
3612         for(core::map<u16, RemoteClient*>::Iterator
3613                 i = m_clients.getIterator();
3614                 i.atEnd() == false; i++)
3615         {
3616                 // Get client and check that it is valid
3617                 RemoteClient *client = i.getNode()->getValue();
3618                 assert(client->peer_id == i.getNode()->getKey());
3619                 if(client->serialization_version == SER_FMT_VER_INVALID)
3620                         continue;
3621
3622                 // Don't send if it's the same one
3623                 if(client->peer_id == ignore_id)
3624                         continue;
3625
3626                 if(far_players)
3627                 {
3628                         // Get player
3629                         Player *player = m_env->getPlayer(client->peer_id);
3630                         if(player)
3631                         {
3632                                 // If player is far away, only set modified blocks not sent
3633                                 v3f player_pos = player->getPosition();
3634                                 if(player_pos.getDistanceFrom(p_f) > maxd)
3635                                 {
3636                                         far_players->push_back(client->peer_id);
3637                                         continue;
3638                                 }
3639                         }
3640                 }
3641
3642                 // Create packet
3643                 u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
3644                 SharedBuffer<u8> reply(replysize);
3645                 writeU16(&reply[0], TOCLIENT_ADDNODE);
3646                 writeS16(&reply[2], p.X);
3647                 writeS16(&reply[4], p.Y);
3648                 writeS16(&reply[6], p.Z);
3649                 n.serialize(&reply[8], client->serialization_version);
3650
3651                 // Send as reliable
3652                 m_con.Send(client->peer_id, 0, reply, true);
3653         }
3654 }
3655
3656 void Server::setBlockNotSent(v3s16 p)
3657 {
3658         for(core::map<u16, RemoteClient*>::Iterator
3659                 i = m_clients.getIterator();
3660                 i.atEnd()==false; i++)
3661         {
3662                 RemoteClient *client = i.getNode()->getValue();
3663                 client->SetBlockNotSent(p);
3664         }
3665 }
3666
3667 void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
3668 {
3669         DSTACK(__FUNCTION_NAME);
3670
3671         v3s16 p = block->getPos();
3672         
3673 #if 0
3674         // Analyze it a bit
3675         bool completely_air = true;
3676         for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
3677         for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
3678         for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
3679         {
3680                 if(block->getNodeNoEx(v3s16(x0,y0,z0)).d != CONTENT_AIR)
3681                 {
3682                         completely_air = false;
3683                         x0 = y0 = z0 = MAP_BLOCKSIZE; // Break out
3684                 }
3685         }
3686
3687         // Print result
3688         infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<"): ";
3689         if(completely_air)
3690                 infostream<<"[completely air] ";
3691         infostream<<std::endl;
3692 #endif
3693
3694         /*
3695                 Create a packet with the block in the right format
3696         */
3697         
3698         std::ostringstream os(std::ios_base::binary);
3699         block->serialize(os, ver, false);
3700         std::string s = os.str();
3701         SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
3702
3703         u32 replysize = 8 + blockdata.getSize();
3704         SharedBuffer<u8> reply(replysize);
3705         writeU16(&reply[0], TOCLIENT_BLOCKDATA);
3706         writeS16(&reply[2], p.X);
3707         writeS16(&reply[4], p.Y);
3708         writeS16(&reply[6], p.Z);
3709         memcpy(&reply[8], *blockdata, blockdata.getSize());
3710
3711         /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
3712                         <<":  \tpacket size: "<<replysize<<std::endl;*/
3713         
3714         /*
3715                 Send packet
3716         */
3717         m_con.Send(peer_id, 1, reply, true);
3718 }
3719
3720 void Server::SendBlocks(float dtime)
3721 {
3722         DSTACK(__FUNCTION_NAME);
3723
3724         JMutexAutoLock envlock(m_env_mutex);
3725         JMutexAutoLock conlock(m_con_mutex);
3726
3727         ScopeProfiler sp(g_profiler, "Server: sel and send blocks to clients");
3728
3729         core::array<PrioritySortedBlockTransfer> queue;
3730
3731         s32 total_sending = 0;
3732         
3733         {
3734                 ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
3735
3736                 for(core::map<u16, RemoteClient*>::Iterator
3737                         i = m_clients.getIterator();
3738                         i.atEnd() == false; i++)
3739                 {
3740                         RemoteClient *client = i.getNode()->getValue();
3741                         assert(client->peer_id == i.getNode()->getKey());
3742
3743                         // If definitions and textures have not been sent, don't
3744                         // send MapBlocks either
3745                         if(!client->definitions_sent)
3746                                 continue;
3747
3748                         total_sending += client->SendingCount();
3749                         
3750                         if(client->serialization_version == SER_FMT_VER_INVALID)
3751                                 continue;
3752                         
3753                         client->GetNextBlocks(this, dtime, queue);
3754                 }
3755         }
3756
3757         // Sort.
3758         // Lowest priority number comes first.
3759         // Lowest is most important.
3760         queue.sort();
3761
3762         for(u32 i=0; i<queue.size(); i++)
3763         {
3764                 //TODO: Calculate limit dynamically
3765                 if(total_sending >= g_settings->getS32
3766                                 ("max_simultaneous_block_sends_server_total"))
3767                         break;
3768                 
3769                 PrioritySortedBlockTransfer q = queue[i];
3770
3771                 MapBlock *block = NULL;
3772                 try
3773                 {
3774                         block = m_env->getMap().getBlockNoCreate(q.pos);
3775                 }
3776                 catch(InvalidPositionException &e)
3777                 {
3778                         continue;
3779                 }
3780
3781                 RemoteClient *client = getClient(q.peer_id);
3782
3783                 SendBlockNoLock(q.peer_id, block, client->serialization_version);
3784
3785                 client->SentBlock(q.pos);
3786
3787                 total_sending++;
3788         }
3789 }
3790
3791 void Server::PrepareTextures()
3792 {
3793         DSTACK(__FUNCTION_NAME);
3794
3795         infostream<<"Server: Calculating texture checksums"<<std::endl;
3796
3797         for(core::list<ModSpec>::Iterator i = m_mods.begin();
3798                         i != m_mods.end(); i++){
3799                 const ModSpec &mod = *i;
3800                 std::string texturepath = mod.path + DIR_DELIM + "textures";
3801                 std::vector<fs::DirListNode> dirlist = fs::GetDirListing(texturepath);
3802                 for(u32 j=0; j<dirlist.size(); j++){
3803                         if(dirlist[j].dir) // Ignode dirs
3804                                 continue;
3805                         std::string tname = dirlist[j].name;
3806                         // if name contains illegal characters, ignore the texture
3807                         if(!string_allowed(tname, TEXTURENAME_ALLOWED_CHARS)){
3808                                 errorstream<<"Server: ignoring illegal texture name: \""
3809                                                 <<tname<<"\""<<std::endl;
3810                                 continue;
3811                         }
3812                         std::string tpath = texturepath + DIR_DELIM + tname;
3813                         // Read data
3814                         std::ifstream fis(tpath.c_str(), std::ios_base::binary);
3815                         if(fis.good() == false){
3816                                 errorstream<<"Server::PrepareTextures(): Could not open \""
3817                                                 <<tname<<"\" for reading"<<std::endl;
3818                                 continue;
3819                         }
3820                         std::ostringstream tmp_os(std::ios_base::binary);
3821                         bool bad = false;
3822                         for(;;){
3823                                 char buf[1024];
3824                                 fis.read(buf, 1024);
3825                                 std::streamsize len = fis.gcount();
3826                                 tmp_os.write(buf, len);
3827                                 if(fis.eof())
3828                                         break;
3829                                 if(!fis.good()){
3830                                         bad = true;
3831                                         break;
3832                                 }
3833                         }
3834                         if(bad){
3835                                 errorstream<<"Server::PrepareTextures(): Failed to read \""
3836                                                 <<tname<<"\""<<std::endl;
3837                                 continue;
3838                         }
3839                         if(tmp_os.str().length() == 0){
3840                                 errorstream<<"Server::PrepareTextures(): Empty file \""
3841                                                 <<tpath<<"\""<<std::endl;
3842                                 continue;
3843                         }
3844
3845                         SHA1 sha1;
3846                         sha1.addBytes(tmp_os.str().c_str(), tmp_os.str().length());
3847
3848                         unsigned char *digest = sha1.getDigest();
3849                         std::string digest_string = base64_encode(digest, 20);
3850
3851                         free(digest);
3852
3853                         // Put in list
3854                         this->m_Textures[tname] = TextureInformation(tpath,digest_string);
3855                         verbosestream<<"Server: sha1 for "<<tname<<"\tis "<<std::endl;
3856                 }
3857         }
3858 }
3859
3860 struct SendableTextureAnnouncement
3861         {
3862                 std::string name;
3863                 std::string sha1_digest;
3864
3865                 SendableTextureAnnouncement(const std::string name_="",
3866                                 const std::string sha1_digest_=""):
3867                         name(name_),
3868                         sha1_digest(sha1_digest_)
3869                 {
3870                 }
3871         };
3872
3873 void Server::SendTextureAnnouncement(u16 peer_id){
3874         DSTACK(__FUNCTION_NAME);
3875
3876         verbosestream<<"Server: Announcing textures to id("<<peer_id<<")"
3877                         <<std::endl;
3878
3879         core::list<SendableTextureAnnouncement> texture_announcements;
3880
3881         for (std::map<std::string,TextureInformation>::iterator i = m_Textures.begin();i != m_Textures.end(); i++ ) {
3882
3883                 // Put in list
3884                 texture_announcements.push_back(
3885                                 SendableTextureAnnouncement(i->first, i->second.sha1_digest));
3886         }
3887
3888         //send announcements
3889
3890         /*
3891                 u16 command
3892                 u32 number of textures
3893                 for each texture {
3894                         u16 length of name
3895                         string name
3896                         u16 length of digest string
3897                         string sha1_digest
3898                 }
3899         */
3900         std::ostringstream os(std::ios_base::binary);
3901
3902         writeU16(os,    TOCLIENT_ANNOUNCE_TEXTURES);
3903         writeU16(os, texture_announcements.size());
3904
3905         for(core::list<SendableTextureAnnouncement>::Iterator
3906                         j = texture_announcements.begin();
3907                         j != texture_announcements.end(); j++){
3908                 os<<serializeString(j->name);
3909                 os<<serializeString(j->sha1_digest);
3910         }
3911
3912         // Make data buffer
3913         std::string s = os.str();
3914         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
3915
3916         // Send as reliable
3917         m_con.Send(peer_id, 0, data, true);
3918
3919 }
3920
3921 struct SendableTexture
3922 {
3923         std::string name;
3924         std::string path;
3925         std::string data;
3926
3927         SendableTexture(const std::string &name_="", const std::string path_="",
3928                         const std::string &data_=""):
3929                 name(name_),
3930                 path(path_),
3931                 data(data_)
3932         {}
3933 };
3934
3935 void Server::SendTexturesRequested(u16 peer_id,core::list<TextureRequest> tosend) {
3936         DSTACK(__FUNCTION_NAME);
3937
3938         verbosestream<<"Server::SendTexturesRequested(): "
3939                         <<"Sending textures to client"<<std::endl;
3940
3941         /* Read textures */
3942
3943         // Put 5kB in one bunch (this is not accurate)
3944         u32 bytes_per_bunch = 5000;
3945
3946         core::array< core::list<SendableTexture> > texture_bunches;
3947         texture_bunches.push_back(core::list<SendableTexture>());
3948
3949         u32 texture_size_bunch_total = 0;
3950
3951         for(core::list<TextureRequest>::Iterator i = tosend.begin(); i != tosend.end(); i++) {
3952                 if(m_Textures.find(i->name) == m_Textures.end()){
3953                         errorstream<<"Server::SendTexturesRequested(): Client asked for "
3954                                         <<"unknown texture \""<<(i->name)<<"\""<<std::endl;
3955                         continue;
3956                 }
3957
3958                 //TODO get path + name
3959                 std::string tpath = m_Textures[(*i).name].path;
3960
3961                 // Read data
3962                 std::ifstream fis(tpath.c_str(), std::ios_base::binary);
3963                 if(fis.good() == false){
3964                         errorstream<<"Server::SendTexturesRequested(): Could not open \""
3965                                         <<tpath<<"\" for reading"<<std::endl;
3966                         continue;
3967                 }
3968                 std::ostringstream tmp_os(std::ios_base::binary);
3969                 bool bad = false;
3970                 for(;;){
3971                         char buf[1024];
3972                         fis.read(buf, 1024);
3973                         std::streamsize len = fis.gcount();
3974                         tmp_os.write(buf, len);
3975                         texture_size_bunch_total += len;
3976                         if(fis.eof())
3977                                 break;
3978                         if(!fis.good()){
3979                                 bad = true;
3980                                 break;
3981                         }
3982                 }
3983                 if(bad){
3984                         errorstream<<"Server::SendTexturesRequested(): Failed to read \""
3985                                         <<(*i).name<<"\""<<std::endl;
3986                         continue;
3987                 }
3988                 /*infostream<<"Server::SendTexturesRequested(): Loaded \""
3989                                 <<tname<<"\""<<std::endl;*/
3990                 // Put in list
3991                 texture_bunches[texture_bunches.size()-1].push_back(
3992                                 SendableTexture((*i).name, tpath, tmp_os.str()));
3993
3994                 // Start next bunch if got enough data
3995                 if(texture_size_bunch_total >= bytes_per_bunch){
3996                         texture_bunches.push_back(core::list<SendableTexture>());
3997                         texture_size_bunch_total = 0;
3998                 }
3999
4000         }
4001
4002         /* Create and send packets */
4003
4004                 u32 num_bunches = texture_bunches.size();
4005                 for(u32 i=0; i<num_bunches; i++)
4006                 {
4007                         /*
4008                                 u16 command
4009                                 u16 total number of texture bunches
4010                                 u16 index of this bunch
4011                                 u32 number of textures in this bunch
4012                                 for each texture {
4013                                         u16 length of name
4014                                         string name
4015                                         u32 length of data
4016                                         data
4017                                 }
4018                         */
4019                         std::ostringstream os(std::ios_base::binary);
4020
4021                         writeU16(os, TOCLIENT_TEXTURES);
4022                         writeU16(os, num_bunches);
4023                         writeU16(os, i);
4024                         writeU32(os, texture_bunches[i].size());
4025
4026                         for(core::list<SendableTexture>::Iterator
4027                                         j = texture_bunches[i].begin();
4028                                         j != texture_bunches[i].end(); j++){
4029                                 os<<serializeString(j->name);
4030                                 os<<serializeLongString(j->data);
4031                         }
4032
4033                         // Make data buffer
4034                         std::string s = os.str();
4035                         verbosestream<<"Server::SendTexturesRequested(): bunch "
4036                                         <<i<<"/"<<num_bunches
4037                                         <<" textures="<<texture_bunches[i].size()
4038                                         <<" size=" <<s.size()<<std::endl;
4039                         SharedBuffer<u8> data((u8*)s.c_str(), s.size());
4040                         // Send as reliable
4041                         m_con.Send(peer_id, 0, data, true);
4042                 }
4043
4044
4045 }
4046
4047 /*
4048         Something random
4049 */
4050
4051 void Server::DiePlayer(Player *player)
4052 {
4053         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4054
4055         infostream<<"Server::DiePlayer(): Player "
4056                         <<player->getName()<<" dies"<<std::endl;
4057         
4058         srp->setHP(0);
4059         
4060         // Trigger scripted stuff
4061         scriptapi_on_dieplayer(m_lua, srp);
4062         
4063         // Handle players that are not connected
4064         if(player->peer_id == PEER_ID_INEXISTENT){
4065                 RespawnPlayer(player);
4066                 return;
4067         }
4068
4069         SendPlayerHP(player);
4070         SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
4071 }
4072
4073 void Server::RespawnPlayer(Player *player)
4074 {
4075         ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4076         srp->setHP(20);
4077         bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
4078         if(!repositioned){
4079                 v3f pos = findSpawnPos(m_env->getServerMap());
4080                 player->setPosition(pos);
4081                 srp->m_last_good_position = pos;
4082                 srp->m_last_good_position_age = 0;
4083         }
4084         SendMovePlayer(player);
4085         SendPlayerHP(player);
4086 }
4087
4088 void Server::UpdateCrafting(u16 peer_id)
4089 {
4090         DSTACK(__FUNCTION_NAME);
4091         
4092         Player* player = m_env->getPlayer(peer_id);
4093         assert(player);
4094
4095         // Get a preview for crafting
4096         ItemStack preview;
4097         // No crafting in creative mode
4098         if(g_settings->getBool("creative_mode") == false)
4099                 getCraftingResult(&player->inventory, preview, false, this);
4100
4101         // Put the new preview in
4102         InventoryList *plist = player->inventory.getList("craftpreview");
4103         assert(plist);
4104         assert(plist->getSize() >= 1);
4105         plist->changeItem(0, preview);
4106 }
4107
4108 RemoteClient* Server::getClient(u16 peer_id)
4109 {
4110         DSTACK(__FUNCTION_NAME);
4111         //JMutexAutoLock lock(m_con_mutex);
4112         core::map<u16, RemoteClient*>::Node *n;
4113         n = m_clients.find(peer_id);
4114         // A client should exist for all peers
4115         assert(n != NULL);
4116         return n->getValue();
4117 }
4118
4119 std::wstring Server::getStatusString()
4120 {
4121         std::wostringstream os(std::ios_base::binary);
4122         os<<L"# Server: ";
4123         // Version
4124         os<<L"version="<<narrow_to_wide(VERSION_STRING);
4125         // Uptime
4126         os<<L", uptime="<<m_uptime.get();
4127         // Information about clients
4128         os<<L", clients={";
4129         for(core::map<u16, RemoteClient*>::Iterator
4130                 i = m_clients.getIterator();
4131                 i.atEnd() == false; i++)
4132         {
4133                 // Get client and check that it is valid
4134                 RemoteClient *client = i.getNode()->getValue();
4135                 assert(client->peer_id == i.getNode()->getKey());
4136                 if(client->serialization_version == SER_FMT_VER_INVALID)
4137                         continue;
4138                 // Get player
4139                 Player *player = m_env->getPlayer(client->peer_id);
4140                 // Get name of player
4141                 std::wstring name = L"unknown";
4142                 if(player != NULL)
4143                         name = narrow_to_wide(player->getName());
4144                 // Add name to information string
4145                 os<<name<<L",";
4146         }
4147         os<<L"}";
4148         if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false)
4149                 os<<std::endl<<L"# Server: "<<" WARNING: Map saving is disabled.";
4150         if(g_settings->get("motd") != "")
4151                 os<<std::endl<<L"# Server: "<<narrow_to_wide(g_settings->get("motd"));
4152         return os.str();
4153 }
4154
4155 void Server::setPlayerPassword(const std::string &name, const std::wstring &password)
4156 {
4157         // Add player to auth manager
4158         if(m_authmanager.exists(name) == false)
4159         {
4160                 infostream<<"Server: adding player "<<name
4161                                 <<" to auth manager"<<std::endl;
4162                 m_authmanager.add(name);
4163                 m_authmanager.setPrivs(name,
4164                         stringToPrivs(g_settings->get("default_privs")));
4165         }
4166         // Change password and save
4167         m_authmanager.setPassword(name, translatePassword(name, password));
4168         m_authmanager.save();
4169 }
4170
4171 // Saves g_settings to configpath given at initialization
4172 void Server::saveConfig()
4173 {
4174         if(m_path_config != "")
4175                 g_settings->updateConfigFile(m_path_config.c_str());
4176 }
4177
4178 void Server::notifyPlayer(const char *name, const std::wstring msg)
4179 {
4180         Player *player = m_env->getPlayer(name);
4181         if(!player)
4182                 return;
4183         SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg);
4184 }
4185
4186 void Server::notifyPlayers(const std::wstring msg)
4187 {
4188         BroadcastChatMessage(msg);
4189 }
4190
4191 void Server::queueBlockEmerge(v3s16 blockpos, bool allow_generate)
4192 {
4193         u8 flags = 0;
4194         if(!allow_generate)
4195                 flags |= BLOCK_EMERGE_FLAG_FROMDISK;
4196         m_emerge_queue.addBlock(PEER_ID_INEXISTENT, blockpos, flags);
4197 }
4198
4199 // IGameDef interface
4200 // Under envlock
4201 IItemDefManager* Server::getItemDefManager()
4202 {
4203         return m_itemdef;
4204 }
4205 INodeDefManager* Server::getNodeDefManager()
4206 {
4207         return m_nodedef;
4208 }
4209 ICraftDefManager* Server::getCraftDefManager()
4210 {
4211         return m_craftdef;
4212 }
4213 ITextureSource* Server::getTextureSource()
4214 {
4215         return NULL;
4216 }
4217 u16 Server::allocateUnknownNodeId(const std::string &name)
4218 {
4219         return m_nodedef->allocateDummy(name);
4220 }
4221
4222 IWritableItemDefManager* Server::getWritableItemDefManager()
4223 {
4224         return m_itemdef;
4225 }
4226 IWritableNodeDefManager* Server::getWritableNodeDefManager()
4227 {
4228         return m_nodedef;
4229 }
4230 IWritableCraftDefManager* Server::getWritableCraftDefManager()
4231 {
4232         return m_craftdef;
4233 }
4234
4235 const ModSpec* Server::getModSpec(const std::string &modname)
4236 {
4237         for(core::list<ModSpec>::Iterator i = m_mods.begin();
4238                         i != m_mods.end(); i++){
4239                 const ModSpec &mod = *i;
4240                 if(mod.name == modname)
4241                         return &mod;
4242         }
4243         return NULL;
4244 }
4245
4246 v3f findSpawnPos(ServerMap &map)
4247 {
4248         //return v3f(50,50,50)*BS;
4249
4250         v3s16 nodepos;
4251         
4252 #if 0
4253         nodepos = v2s16(0,0);
4254         groundheight = 20;
4255 #endif
4256
4257 #if 1
4258         // Try to find a good place a few times
4259         for(s32 i=0; i<1000; i++)
4260         {
4261                 s32 range = 1 + i;
4262                 // We're going to try to throw the player to this position
4263                 v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)),
4264                                 -range + (myrand()%(range*2)));
4265                 //v2s16 sectorpos = getNodeSectorPos(nodepos2d);
4266                 // Get ground height at point (fallbacks to heightmap function)
4267                 s16 groundheight = map.findGroundLevel(nodepos2d);
4268                 // Don't go underwater
4269                 if(groundheight < WATER_LEVEL)
4270                 {
4271                         //infostream<<"-> Underwater"<<std::endl;
4272                         continue;
4273                 }
4274                 // Don't go to high places
4275                 if(groundheight > WATER_LEVEL + 4)
4276                 {
4277                         //infostream<<"-> Underwater"<<std::endl;
4278                         continue;
4279                 }
4280                 
4281                 nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
4282                 bool is_good = false;
4283                 s32 air_count = 0;
4284                 for(s32 i=0; i<10; i++){
4285                         v3s16 blockpos = getNodeBlockPos(nodepos);
4286                         map.emergeBlock(blockpos, true);
4287                         MapNode n = map.getNodeNoEx(nodepos);
4288                         if(n.getContent() == CONTENT_AIR){
4289                                 air_count++;
4290                                 if(air_count >= 2){
4291                                         is_good = true;
4292                                         nodepos.Y -= 1;
4293                                         break;
4294                                 }
4295                         }
4296                         nodepos.Y++;
4297                 }
4298                 if(is_good){
4299                         // Found a good place
4300                         //infostream<<"Searched through "<<i<<" places."<<std::endl;
4301                         break;
4302                 }
4303         }
4304 #endif
4305         
4306         return intToFloat(nodepos, BS);
4307 }
4308
4309 ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
4310 {
4311         /*
4312                 Try to get an existing player
4313         */
4314         ServerRemotePlayer *player =
4315                         static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
4316         if(player != NULL)
4317         {
4318                 // If player is already connected, cancel
4319                 if(player->peer_id != 0)
4320                 {
4321                         infostream<<"emergePlayer(): Player already connected"<<std::endl;
4322                         return NULL;
4323                 }
4324
4325                 // Got one.
4326                 player->peer_id = peer_id;
4327                 
4328                 // Re-add player to environment
4329                 if(player->m_removed)
4330                 {
4331                         player->m_removed = false;
4332                         player->setId(0);
4333                         m_env->addActiveObject(player);
4334                 }
4335
4336                 // Reset inventory to creative if in creative mode
4337                 if(g_settings->getBool("creative_mode"))
4338                 {
4339                         // Warning: double code below
4340                         // Backup actual inventory
4341                         player->inventory_backup = new Inventory(m_itemdef);
4342                         *(player->inventory_backup) = player->inventory;
4343                         // Set creative inventory
4344                         player->resetInventory();
4345                         scriptapi_get_creative_inventory(m_lua, player);
4346                 }
4347
4348                 return player;
4349         }
4350
4351         /*
4352                 If player with the wanted peer_id already exists, cancel.
4353         */
4354         if(m_env->getPlayer(peer_id) != NULL)
4355         {
4356                 infostream<<"emergePlayer(): Player with wrong name but same"
4357                                 " peer_id already exists"<<std::endl;
4358                 return NULL;
4359         }
4360         
4361         /*
4362                 Create a new player
4363         */
4364         {
4365                 /* Set player position */
4366                 
4367                 infostream<<"Server: Finding spawn place for player \""
4368                                 <<name<<"\""<<std::endl;
4369
4370                 v3f pos = findSpawnPos(m_env->getServerMap());
4371
4372                 player = new ServerRemotePlayer(m_env, pos, peer_id, name);
4373                 ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
4374
4375                 /* Add player to environment */
4376                 m_env->addPlayer(player);
4377                 m_env->addActiveObject(srp);
4378
4379                 /* Run scripts */
4380                 scriptapi_on_newplayer(m_lua, srp);
4381
4382                 /* Add stuff to inventory */
4383                 if(g_settings->getBool("creative_mode"))
4384                 {
4385                         // Warning: double code above
4386                         // Backup actual inventory
4387                         player->inventory_backup = new Inventory(m_itemdef);
4388                         *(player->inventory_backup) = player->inventory;
4389                         // Set creative inventory
4390                         player->resetInventory();
4391                         scriptapi_get_creative_inventory(m_lua, player);
4392                 }
4393
4394                 return player;
4395                 
4396         } // create new player
4397 }
4398
4399 void Server::handlePeerChange(PeerChange &c)
4400 {
4401         JMutexAutoLock envlock(m_env_mutex);
4402         JMutexAutoLock conlock(m_con_mutex);
4403         
4404         if(c.type == PEER_ADDED)
4405         {
4406                 /*
4407                         Add
4408                 */
4409
4410                 // Error check
4411                 core::map<u16, RemoteClient*>::Node *n;
4412                 n = m_clients.find(c.peer_id);
4413                 // The client shouldn't already exist
4414                 assert(n == NULL);
4415
4416                 // Create client
4417                 RemoteClient *client = new RemoteClient();
4418                 client->peer_id = c.peer_id;
4419                 m_clients.insert(client->peer_id, client);
4420
4421         } // PEER_ADDED
4422         else if(c.type == PEER_REMOVED)
4423         {
4424                 /*
4425                         Delete
4426                 */
4427
4428                 // Error check
4429                 core::map<u16, RemoteClient*>::Node *n;
4430                 n = m_clients.find(c.peer_id);
4431                 // The client should exist
4432                 assert(n != NULL);
4433                 
4434                 /*
4435                         Mark objects to be not known by the client
4436                 */
4437                 RemoteClient *client = n->getValue();
4438                 // Handle objects
4439                 for(core::map<u16, bool>::Iterator
4440                                 i = client->m_known_objects.getIterator();
4441                                 i.atEnd()==false; i++)
4442                 {
4443                         // Get object
4444                         u16 id = i.getNode()->getKey();
4445                         ServerActiveObject* obj = m_env->getActiveObject(id);
4446                         
4447                         if(obj && obj->m_known_by_count > 0)
4448                                 obj->m_known_by_count--;
4449                 }
4450
4451                 ServerRemotePlayer* player =
4452                                 static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
4453
4454                 // Collect information about leaving in chat
4455                 std::wstring message;
4456                 {
4457                         if(player != NULL)
4458                         {
4459                                 std::wstring name = narrow_to_wide(player->getName());
4460                                 message += L"*** ";
4461                                 message += name;
4462                                 message += L" left game";
4463                                 if(c.timeout)
4464                                         message += L" (timed out)";
4465                         }
4466                 }
4467                 
4468                 // Remove from environment
4469                 if(player != NULL)
4470                         player->m_removed = true;
4471                 
4472                 // Set player client disconnected
4473                 if(player != NULL)
4474                         player->peer_id = 0;
4475         
4476                 /*
4477                         Print out action
4478                 */
4479                 {
4480                         if(player != NULL)
4481                         {
4482                                 std::ostringstream os(std::ios_base::binary);
4483                                 for(core::map<u16, RemoteClient*>::Iterator
4484                                         i = m_clients.getIterator();
4485                                         i.atEnd() == false; i++)
4486                                 {
4487                                         RemoteClient *client = i.getNode()->getValue();
4488                                         assert(client->peer_id == i.getNode()->getKey());
4489                                         if(client->serialization_version == SER_FMT_VER_INVALID)
4490                                                 continue;
4491                                         // Get player
4492                                         Player *player = m_env->getPlayer(client->peer_id);
4493                                         if(!player)
4494                                                 continue;
4495                                         // Get name of player
4496                                         os<<player->getName()<<" ";
4497                                 }
4498
4499                                 actionstream<<player->getName()<<" "
4500                                                 <<(c.timeout?"times out.":"leaves game.")
4501                                                 <<" List of players: "
4502                                                 <<os.str()<<std::endl;
4503                         }
4504                 }
4505                 
4506                 // Delete client
4507                 delete m_clients[c.peer_id];
4508                 m_clients.remove(c.peer_id);
4509
4510                 // Send player info to all remaining clients
4511                 //SendPlayerInfos();
4512                 
4513                 // Send leave chat message to all remaining clients
4514                 if(message.length() != 0)
4515                         BroadcastChatMessage(message);
4516                 
4517         } // PEER_REMOVED
4518         else
4519         {
4520                 assert(0);
4521         }
4522 }
4523
4524 void Server::handlePeerChanges()
4525 {
4526         while(m_peer_change_queue.size() > 0)
4527         {
4528                 PeerChange c = m_peer_change_queue.pop_front();
4529
4530                 verbosestream<<"Server: Handling peer change: "
4531                                 <<"id="<<c.peer_id<<", timeout="<<c.timeout
4532                                 <<std::endl;
4533
4534                 handlePeerChange(c);
4535         }
4536 }
4537
4538 u64 Server::getPlayerPrivs(Player *player)
4539 {
4540         if(player==NULL)
4541                 return 0;
4542         std::string playername = player->getName();
4543         // Local player gets all privileges regardless of
4544         // what's set on their account.
4545         if(g_settings->get("name") == playername)
4546         {
4547                 return PRIV_ALL;
4548         }
4549         else
4550         {
4551                 return getPlayerAuthPrivs(playername);
4552         }
4553 }
4554
4555 void dedicated_server_loop(Server &server, bool &kill)
4556 {
4557         DSTACK(__FUNCTION_NAME);
4558         
4559         verbosestream<<"dedicated_server_loop()"<<std::endl;
4560
4561         IntervalLimiter m_profiler_interval;
4562
4563         for(;;)
4564         {
4565                 float steplen = g_settings->getFloat("dedicated_server_step");
4566                 // This is kind of a hack but can be done like this
4567                 // because server.step() is very light
4568                 {
4569                         ScopeProfiler sp(g_profiler, "dedicated server sleep");
4570                         sleep_ms((int)(steplen*1000.0));
4571                 }
4572                 server.step(steplen);
4573
4574                 if(server.getShutdownRequested() || kill)
4575                 {
4576                         infostream<<"Dedicated server quitting"<<std::endl;
4577                         break;
4578                 }
4579
4580                 /*
4581                         Profiler
4582                 */
4583                 float profiler_print_interval =
4584                                 g_settings->getFloat("profiler_print_interval");
4585                 if(profiler_print_interval != 0)
4586                 {
4587                         if(m_profiler_interval.step(steplen, profiler_print_interval))
4588                         {
4589                                 infostream<<"Profiler:"<<std::endl;
4590                                 g_profiler->print(infostream);
4591                                 g_profiler->clear();
4592                         }
4593                 }
4594         }
4595 }
4596
4597