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