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