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