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