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