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