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