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