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