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