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